-
Notifications
You must be signed in to change notification settings - Fork 433
AppNotificationBuilder features #2786
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
7119200
4765ea2
30a4376
40bd764
8668d3a
1545006
e470027
422eae8
f55aad3
aa7ed04
e0b2847
15b477c
903956a
bbe8a26
f5a745f
435a152
238684d
5423935
d427450
5dc491a
2b24c69
33a4b1b
5bd1f9e
41a699e
5ea7ddd
019077a
f45fb7a
f81258e
8851cae
224877f
861014d
a934566
19d0cd4
9c6bb22
8f51b89
f8ed6ca
49c02bb
3b3b08c
604a24f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,341 @@ | ||
| // 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> | ||
|
|
||
| using namespace winrt::Windows::Globalization; | ||
| using namespace winrt::Windows::Globalization::DateTimeFormatting; | ||
|
|
||
| namespace winrt::Microsoft::Windows::AppNotifications::Builder::implementation | ||
| { | ||
| bool AppNotificationBuilder::IsUrgentScenarioSupported() | ||
| { | ||
| return GetBuildNumber() >= 19041; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Ugh. Version checks. That's a minefield (as in, a reliable answer is a minefield...) Please use functions in dev\common\IsWindowsVersion.h e.g. That avoids the minefield of GetVersion mechanisms which don't necessarily yield the expected answer |
||
| } | ||
|
|
||
| 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(key, value); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Locks? Specifically a write lock
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why? |
||
| 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; | ||
|
pmpurifoy marked this conversation as resolved.
|
||
| gmtime_s(&buf, &seconds); | ||
|
|
||
| std::wstringstream buffer; | ||
| buffer << std::put_time(&buf, L"%FT%T"); | ||
|
|
||
| m_timeStamp = wil::str_printf<std::wstring>(L" displayTimestamp='%wsZ'", buffer.str().c_str()); | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why the trailing 'Z'? Should above be |
||
| return *this; | ||
| } | ||
|
|
||
| winrt::Microsoft::Windows::AppNotifications::Builder::AppNotificationBuilder AppNotificationBuilder::SetScenario(AppNotificationScenario const& value) | ||
| { | ||
| m_scenario = value; | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. lock
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Here and everywhere else where we access members.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. See other comment re locks |
||
| 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>%ws</text>", text.c_str()).c_str()); | ||
|
pmpurifoy marked this conversation as resolved.
|
||
| 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"%ws%ws</text>", props.c_str(), 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'>%ws</text>", 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."); | ||
|
pmpurifoy marked this conversation as resolved.
|
||
|
|
||
| m_attributionText = wil::str_printf<std::wstring>(L"<text placement='attribution' lang='%ws'>%ws</text>", language.c_str(), 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='%ws'/>", 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='%ws' 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='%ws' alt='%ws'%ws/>", imageUri.ToString().c_str(), 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='%ws'/>", 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='%ws' 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='%ws' alt='%ws'%ws/>", imageUri.ToString().c_str(), 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='%ws'/>", 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='%ws' alt='%ws'/>", imageUri.ToString().c_str(), 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='%ws'/>", 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='%ws' loop='%ws'/>", 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='%ws'/>", GetWinSoundEventString(soundEvent).c_str()); | ||
| 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='%ws' loop='%ws'/>", GetWinSoundEventString(soundEvent).c_str(), 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::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::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{ }; | ||
|
pmpurifoy marked this conversation as resolved.
|
||
| for (auto pair : m_arguments) | ||
| { | ||
| if (!pair.Value().empty()) | ||
| { | ||
| arguments.append(wil::str_printf<std::wstring>(L"%ws=%ws;", pair.Key().c_str(), pair.Value().c_str())); | ||
| } | ||
| else | ||
| { | ||
| arguments.append(wil::str_printf<std::wstring>(L"%ws;", pair.Key().c_str())); | ||
| } | ||
| } | ||
| arguments.pop_back(); | ||
|
|
||
| return wil::str_printf<std::wstring>(L" launch='%ws'", 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"%ws%ws%ws", m_inlineImage.c_str(), m_heroImage.c_str(), m_appLogoOverride.c_str()); | ||
| } | ||
|
|
||
| std::wstring AppNotificationBuilder::GetButtons() | ||
| { | ||
| if (m_buttonList.size()) | ||
| { | ||
| std::wstring result{}; | ||
| 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 wil::str_printf<std::wstring>(L"<actions>%ws</actions>", result.c_str()); | ||
| } | ||
| else | ||
| { | ||
| return {}; | ||
| } | ||
| } | ||
|
|
||
| // You must call GetButtons first to retrieve this value. | ||
| std::wstring AppNotificationBuilder::GetButtonStyle() | ||
| { | ||
| return m_useButtonStyle ? L" useButtonStyle='true'" : L""; | ||
| } | ||
|
|
||
| winrt::Microsoft::Windows::AppNotifications::AppNotification AppNotificationBuilder::BuildNotification() | ||
| { | ||
| std::wstring xmlResult{}; | ||
| xmlResult.reserve(c_maxAppNotificationPayload); | ||
|
|
||
| // Build the button string and fill m_useButtonStyle | ||
| std::wstring buttons{ GetButtons() }; | ||
|
|
||
| xmlResult.append(L"<toast"); | ||
| xmlResult.append(m_timeStamp); | ||
| xmlResult.append(GetDuration()); | ||
| xmlResult.append(GetScenario()); | ||
| xmlResult.append(GetArguments()); | ||
| xmlResult.append(GetButtonStyle()); | ||
| xmlResult.append(L"><visual><binding template='ToastGeneric'>"); | ||
| xmlResult.append(GetText()); | ||
| xmlResult.append(m_attributionText); | ||
| xmlResult.append(GetImages()); | ||
| xmlResult.append(L"</binding></visual>"); | ||
| xmlResult.append(m_audio.c_str()); | ||
| xmlResult.append(buttons); | ||
| xmlResult.append(L"</toast>"); | ||
|
|
||
| winrt::Microsoft::Windows::AppNotifications::AppNotification appNotification{ xmlResult }; | ||
| appNotification.Tag(m_tag); | ||
| appNotification.Group(m_group); | ||
|
|
||
| return appNotification; | ||
| } | ||
| } | ||
Uh oh!
There was an error while loading. Please reload this page.