Commit e62fff29 by Sebastián Katzer

Added plugin without --link option

parent 2ded84a9
/Users/sebastian/Documents/github/cordova-plugin-local-notifications
\ No newline at end of file
ChangeLog
---------
Please also read the [Upgrade Guide](https://github.com/katzer/cordova-plugin-local-notifications/wiki/Upgrade-Guide) for more information.
#### Version 0.8.5 (22.05.2017)
- iOS 10
#### Version 0.8.4 (04.01.2016)
- Bug fixes
- SyntaxError: missing ) after argument list
#### Version 0.8.3 (03.01.2016)
- Platform enhancements
- Support for the `Crosswalk Engine`
- Support for `cordova-ios@4` and the `WKWebView Engine`
- Support for `cordova-windows@4` and `Windows 10` without using hooks
- Enhancements
- New `color` attribute for Android (Thanks to @Eusebius1920)
- New `quarter` intervall for iOS & Android
- `smallIcon` is optional (Android)
- `update` checks for permission like _schedule_
- Decreased time-frame for trigger event (iOS)
- Force `every:` to be a string on iOS
- Bug fixes
- Fixed #634 option to skip permission check
- Fixed #588 crash when basename & extension can't be extracted (Android)
- Fixed #732 loop between update and trigger (Android)
- Fixed #710 crash due to >500 notifications (Android)
- Fixed #682 crash while resuming app from notification (Android 6)
- Fixed #612 cannot update icon or sound (Android)
- Fixed crashing get(ID) if notification doesn't exist
- Fixed #569 getScheduled returns two items per notification
- Fixed #700 notifications appears on bootup
#### Version 0.8.2 (08.11.2015)
- Submitted to npm
- Initial support for the `windows` platform
- Re-add autoCancel option on Android
- Warn about unknown properties
- Fix crash on iOS 9
- Fixed webView-Problems with cordova-android 4.0
- Fix get* with single id
- Fix issue when passing data in milliseconds
- Update device plugin id
- Several other fixes
#### Version 0.8.1 (08.03.2015)
- Fix incompatibility with cordova version 3.5-3.0
- Fire `clear` instead of `cancel` event when clicked on repeating notifications
- Do not fire `clear` or `cancel` event when clicked on persistent notifications
### Version 0.8.0 (05.03.2015)
- Support for iOS 8, Android 2 (SDK >= 7) and Android 5
- Windows Phone 8.1 will be added soon
- New interfaces to ask for / register permissions required to schedule local notifications
- `hasPermission()` and `registerPermission()`
- _schedule()_ will register the permission automatically and schedule the notification if granted.
- New interface to update already scheduled|triggered local notifications
- `update()`
- New interfaces to clear the notification center
- `clear()` and `clearAll()`
- New interfaces to query for local notifications, their properties, their IDs and their existence depend on their state
- `isPresent()`, `isScheduled()`, `isTriggered()`
- `getIds()`, `getAllIds()`, `getScheduledIds()`, `getTriggeredIds()`
- `get()`, `getAll()`, `getScheduled()`, `getTriggered()`
- Schedule multiple local notifications at once
- `schedule( [{...},{...}] )`
- Update multiple local notifications at once
- `update( [{...},{...}] )`
- Clear multiple local notifications at once
- `clear( [1, 2] )`
- Cancel multiple local notifications at once
- `cancel( [1, 2] )`
- New URI format to specify sound and image resources
- `http(s):` for remote resources _(Android)_
- `file:` for local resources relative to the _www_ folder
- `res:` for native resources
- New events
- `schedule`, `update`, `clear`, `clearall` and `cancelall`
- Enhanced event informations
- Listener will get called with the local notification object instead of only the ID
- Multiple listener for one event
- `on(event, callback, scope)`
- Unregister event listener
- `un(event, callback)`
- New Android specific properties
- `led` properties
- `sound` and `image` accepts remote resources
- Callback function and scope for all interface methods
- `schedule( notification, callback, scope )`
- Renamed `add()` to `schedule()`
- `autoCancel` property has been removed
- Use `ongoing: true` for persistent local notifications on Android
- Renamed repeat intervals
- `second`, `minute`, `hour`, `day`, `week`, `month` and `year`
- Renamed some local notification properties
- `date`, `json`, `message` and `repeat`
- Scheduling local notifications with the deprecated properties is still possible
- [Kitchen Sink sample app](https://github.com/katzer/cordova-plugin-local-notifications/tree/example)
- [Wiki](https://github.com/katzer/cordova-plugin-local-notifications/wiki)
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright 2013 appPlant GmbH
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
\ No newline at end of file
[![npm version](https://badge.fury.io/js/de.appplant.cordova.plugin.local-notification.svg)](http://badge.fury.io/js/de.appplant.cordova.plugin.local-notification)
[![PayPayl donate button](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=L3HKQCD9UA35A "Donate once-off to this project using Paypal")
Cordova Local-Notification Plugin
=================================
The essential purpose of local notifications is to enable an application to inform its users that it has something for them — for example, a message or an upcoming appointment — when the application isn’t running in the foreground.<br>
They are scheduled by an application and delivered on the same device.
<img width="35%" align="right" hspace="19" vspace="12" src="https://raw.githubusercontent.com/katzer/cordova-plugin-local-notifications/example/images/android.png"></img>
### How they appear to the user
Users see notifications in the following ways:
- Displaying an alert or banner
- Badging the app’s icon
- Playing a sound
### Examples of Notification Usage
Local notifications are ideally suited for applications with time-based behaviors, such as calendar and to-do list applications. Applications that run in the background for the limited period allowed by iOS might also find local notifications useful.<br>
For example, applications that depend on servers for messages or data can poll their servers for incoming items while running in the background; if a message is ready to view or an update is ready to download, they can then present a local notification immediately to inform their users.
## Supported Platforms
The current 0.8 branch supports the following platforms:
- __iOS__ _(>= 8)_<br>
- __Android__ _(SDK >=7)_
- __Windows 8.1__ _(added with v0.8.2)_
- __Windows Phone 8.1__ _(added with v0.8.2)_
- __Windows 10__ _(added with v0.8.3)_
Find out more informations [here][wiki_platforms] in our wiki.
## Installation
The plugin is installable from source and available on Cordova Plugin Registry and PhoneGap Build.
Find out more informations [here][wiki_installation] in our wiki.
## I want to get a quick overview
All wiki pages contain samples, but for a quick overview the sample section may be the fastest way.
Find out more informations [here][wiki_samples] in our wiki.
## I want to get a deep overview
The plugin supports scheduling local notifications in various ways with a single interface. It also allows you to update, clear or cancel them. There are different interfaces to query for local notifications and a complete set of events to hook into the life cycle of local notifications.
Find out more about how to schedule single, multiple, delayed or repeating local notifications [here][wiki_schedule].<br>
Informations about events like _click_ or _trigger_ can be found [here][wiki_events].
To get a deep overview we recommend to read about all the topics in our [wiki][wiki] and try out the [Kitchen Sink App][wiki_kitchensink]
## I want to see the plugin in action
The plugin offers a kitchen sink sample app. Check out the cordova project and run the app directly from your command line or preferred IDE.
Find out more informations [here][wiki_kitchensink] in our wiki.
## What's new
We are proud to announce our newest release version 0.8.x. Beside the hard work at the office and at the weekends it contains a lot of goodies, new features and easy to use APIs.
Find out more informations [here][wiki_changelog] in our wiki.
## Sample
The sample demonstrates how to schedule a local notification which repeats every week. The listener will be called when the user has clicked on the local notification.
```javascript
cordova.plugins.notification.local.schedule({
id: 1,
title: "Production Jour fixe",
text: "Duration 1h",
firstAt: monday_9_am,
every: "week",
sound: "file://sounds/reminder.mp3",
icon: "http://icons.com/?cal_id=1",
data: { meetingId:"123#fg8" }
});
cordova.plugins.notification.local.on("click", function (notification) {
joinMeeting(notification.data.meetingId);
});
```
Find out more informations [here][wiki_samples] in our wiki.
## I would like to propose new features
We appreciate any feature proposal and support for their development. Please describe them [here][feature_proposal_issue].
Find out more informations [here][wiki_next] in our wiki.
## Supporting
Your support is needed. If you use the plugin please send us a drop through the donation button.
Thank you!
[![PayPayl donate button](https://img.shields.io/badge/paypal-donate-yellow.svg)](https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_id=L3HKQCD9UA35A "Donate once-off to this project using Paypal")
## Contributing
1. Fork it
2. Create your feature branch (`git checkout -b my-new-feature`)
3. Commit your changes (`git commit -am 'Add some feature'`)
4. Push to the branch (`git push origin my-new-feature`)
5. Create new Pull Request
## License
This software is released under the [Apache 2.0 License][apache2_license].
© 2013-2016 appPlant UG, Inc. All rights reserved
[cordova]: https://cordova.apache.org
[wiki]: https://github.com/katzer/cordova-plugin-local-notifications/wiki
[wiki_platforms]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/02.-Platforms
[wiki_installation]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/03.-Installation
[wiki_kitchensink]: https://github.com/katzer/cordova-plugin-local-notifications/tree/example
[wiki_schedule]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/04.-Scheduling
[wiki_events]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/09.-Events
[wiki_samples]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/11.-Samples
[wiki_changelog]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/Upgrade-Guide
[wiki_next]: https://github.com/katzer/cordova-plugin-local-notifications/wiki/Feature-Requests
[feature_proposal_issue]: https://github.com/katzer/cordova-plugin-local-notifications/issues/451
[apache2_license]: http://opensource.org/licenses/Apache-2.0
{
"name": "de.appplant.cordova.plugin.local-notification",
"cordova_name": "Cordova LocalNotification Plugin",
"version": "0.8.5",
"description": "Schedules and queries for local notifications",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/katzer/cordova-plugin-local-notifications.git#ios10"
},
"keywords": [
"appplant",
"notification",
"local notification",
"cordova",
"ecosystem:cordova",
"cordova-android",
"cordova-ios",
"cordova-windows"
],
"platforms": [
"ios",
"android",
"windows"
],
"engines": [
{
"name": "cordova",
"version": ">=3.6.0"
},
{
"name": "cordova-plugman",
"version": ">=4.3.0"
},
{
"name": "cordova-windows",
"version": ">=4.2.0"
}
],
"dependencies": {
"cordova-plugin-device": "*",
"cordova-plugin-app-event": ">=1.1.0"
},
"author": "Sebastián Katzer",
"license": "Apache-2.0",
"bugs": {
"url": "https://github.com/katzer/cordova-plugin-local-notifications/issues"
},
"homepage": "https://github.com/katzer/cordova-plugin-local-notifications#readme"
}
<?xml version="1.0" encoding="UTF-8"?>
<!--
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
-->
<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android"
id="cordova-plugin-local-notifications"
version="0.0.0">
<name>LocalNotification</name>
<description>The plugin supports scheduling local notifications in various ways with a single interface. It also allows you to update, clear or cancel them. There are different interfaces to query for local notifications and a complete set of events to hook into the life cycle of local notifications. To get a deep overview we recommend to read about all the topics in our wiki and try out the Kitchen Sink App</description>
<repo>https://github.com/katzer/cordova-plugin-local-notifications.git</repo>
<keywords>appplant, notification, local notification, user notification</keywords>
<license>Apache 2.0</license>
<author>Sebastián Katzer</author>
<!-- cordova -->
<engines>
<engine name="cordova" version=">=3.6.0" />
<engine name="cordova-plugman" version=">=4.3.0" />
<engine name="cordova-windows" version=">=4.2.0" />
<engine name="apple-ios" version=">=10.0.0" />
</engines>
<!-- dependencies -->
<dependency id="cordova-plugin-device" />
<!-- js -->
<js-module src="www/local-notification.js" name="LocalNotification">
<clobbers target="cordova.plugins.notification.local" />
</js-module>
<js-module src="www/local-notification-core.js" name="LocalNotification.Core">
<clobbers target="cordova.plugins.notification.local.core" />
<clobbers target="plugin.notification.local.core" />
</js-module>
<js-module src="www/local-notification-util.js" name="LocalNotification.Util">
<merges target="cordova.plugins.notification.local.core" />
<merges target="plugin.notification.local.core" />
</js-module>
<!-- ios -->
<platform name="ios">
<config-file target="config.xml" parent="/*">
<feature name="LocalNotification">
<param name="ios-package" value="APPLocalNotification" onload="true" />
<param name="onload" value="true" />
</feature>
</config-file>
<framework src="UserNotifications.framework" />
<framework src="CoreLocation.framework" />
<header-file src="src/ios/APPLocalNotification.h" />
<source-file src="src/ios/APPLocalNotification.m" />
<header-file src="src/ios/APPNotificationContent.h" />
<source-file src="src/ios/APPNotificationContent.m" />
<header-file src="src/ios/APPNotificationOptions.h" />
<source-file src="src/ios/APPNotificationOptions.m" />
<header-file src="src/ios/UNUserNotificationCenter+APPLocalNotification.h" />
<source-file src="src/ios/UNUserNotificationCenter+APPLocalNotification.m" />
<header-file src="src/ios/UNNotificationRequest+APPLocalNotification.h" />
<source-file src="src/ios/UNNotificationRequest+APPLocalNotification.m" />
</platform>
<!-- android -->
<!-- <platform name="android">
<framework src="com.android.support:support-v4:+" value="gradle" />
<config-file target="res/xml/config.xml" parent="/*">
<feature name="LocalNotification">
<param name="android-package" value="de.appplant.cordova.plugin.localnotification.LocalNotification"/>
</feature>
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<receiver
android:name="de.appplant.cordova.plugin.localnotification.TriggerReceiver"
android:exported="false" />
<receiver
android:name="de.appplant.cordova.plugin.localnotification.ClearReceiver"
android:exported="false" />
<activity
android:name="de.appplant.cordova.plugin.localnotification.ClickActivity"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.NoDisplay"
android:exported="false" />
<receiver
android:name="de.appplant.cordova.plugin.notification.TriggerReceiver"
android:exported="false" />
<receiver
android:name="de.appplant.cordova.plugin.notification.ClearReceiver"
android:exported="false" />
<receiver android:name="de.appplant.cordova.plugin.localnotification.RestoreReceiver" android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<activity
android:name="de.appplant.cordova.plugin.notification.ClickActivity"
android:launchMode="singleInstance"
android:theme="@android:style/Theme.NoDisplay"
android:exported="false" />
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest">
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
</config-file>
<source-file
src="src/android/LocalNotification.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/TriggerReceiver.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/ClickActivity.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/ClearReceiver.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/RestoreReceiver.java"
target-dir="src/de/appplant/cordova/plugin/localnotification" />
<source-file
src="src/android/notification/AbstractClearReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/AbstractClickActivity.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/AbstractRestoreReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/AbstractTriggerReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/AssetUtil.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/Builder.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/ClearReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/ClickActivity.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/Manager.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/Notification.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/Options.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
<source-file
src="src/android/notification/TriggerReceiver.java"
target-dir="src/de/appplant/cordova/plugin/notification" />
</platform> -->
<!-- windows -->
<platform name="windows">
<config-file target="config.xml" parent="/*" >
<preference name="WindowsToastCapable" value="true" />
</config-file>
<framework src="src/windows/lib.UW/ARM/LocalNotificationProxy.winmd" target-dir="x86" arch="x86" custom="true"/>
<framework src="src/windows/lib.UW/ARM/LocalNotificationProxy.winmd" target-dir="x64" arch="x64" custom="true"/>
<framework src="src/windows/lib.UW/ARM/LocalNotificationProxy.winmd" target-dir="ARM" arch="ARM" custom="true"/>
<js-module src="src/windows/LocalNotificationProxy.js" name="LocalNotification.Proxy" >
<merges target="" />
</js-module>
</platform>
</plugin>
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.localnotification;
import de.appplant.cordova.plugin.notification.Notification;
/**
* The clear intent receiver is triggered when the user clears a
* notification manually. It un-persists the cleared notification from the
* shared preferences.
*/
public class ClearReceiver extends de.appplant.cordova.plugin.notification.ClearReceiver {
/**
* Called when a local notification was cleared from outside of the app.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClear (Notification notification) {
super.onClear(notification);
LocalNotification.fireEvent("clear", notification);
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.localnotification;
import de.appplant.cordova.plugin.notification.Builder;
import de.appplant.cordova.plugin.notification.Notification;
import de.appplant.cordova.plugin.notification.TriggerReceiver;
/**
* The receiver activity is triggered when a notification is clicked by a user.
* The activity calls the background callback and brings the launch intent
* up to foreground.
*/
public class ClickActivity extends de.appplant.cordova.plugin.notification.ClickActivity {
/**
* Called when local notification was clicked by the user.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClick(Notification notification) {
LocalNotification.fireEvent("click", notification);
super.onClick(notification);
if (notification.getOptions().isOngoing())
return;
String event = notification.isRepeating() ? "clear" : "cancel";
LocalNotification.fireEvent(event, notification);
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder
.setTriggerReceiver(TriggerReceiver.class)
.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.localnotification;
import android.app.Activity;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaInterface;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.lang.Exception;
import de.appplant.cordova.plugin.notification.Manager;
import de.appplant.cordova.plugin.notification.Notification;
/**
* This plugin utilizes the Android AlarmManager in combination with local
* notifications. When a local notification is scheduled the alarm manager takes
* care of firing the event. When the event is processed, a notification is put
* in the Android notification center and status bar.
*/
public class LocalNotification extends CordovaPlugin {
// Reference to the web view for static access
private static CordovaWebView webView = null;
// Indicates if the device is ready (to receive events)
private static Boolean deviceready = false;
// To inform the user about the state of the app in callbacks
protected static Boolean isInBackground = true;
// Queues all events before deviceready
private static ArrayList<String> eventQueue = new ArrayList<String>();
/**
* Called after plugin construction and fields have been initialized.
* Prefer to use pluginInitialize instead since there is no value in
* having parameters on the initialize() function.
*
* pluginInitialize is not available for cordova 3.0-3.5 !
*/
@Override
public void initialize (CordovaInterface cordova, CordovaWebView webView) {
LocalNotification.webView = super.webView;
}
/**
* Called when the system is about to start resuming a previous activity.
*
* @param multitasking
* Flag indicating if multitasking is turned on for app
*/
@Override
public void onPause(boolean multitasking) {
super.onPause(multitasking);
isInBackground = true;
}
/**
* Called when the activity will start interacting with the user.
*
* @param multitasking
* Flag indicating if multitasking is turned on for app
*/
@Override
public void onResume(boolean multitasking) {
super.onResume(multitasking);
isInBackground = false;
deviceready();
}
/**
* The final call you receive before your activity is destroyed.
*/
@Override
public void onDestroy() {
deviceready = false;
isInBackground = true;
}
/**
* Executes the request.
*
* This method is called from the WebView thread. To do a non-trivial
* amount of work, use:
* cordova.getThreadPool().execute(runnable);
*
* To run on the UI thread, use:
* cordova.getActivity().runOnUiThread(runnable);
*
* @param action
* The action to execute.
* @param args
* The exec() arguments in JSON form.
* @param command
* The callback context used when calling back into JavaScript.
* @return
* Whether the action was valid.
*/
@Override
public boolean execute (final String action, final JSONArray args,
final CallbackContext command) throws JSONException {
Notification.setDefaultTriggerReceiver(TriggerReceiver.class);
cordova.getThreadPool().execute(new Runnable() {
public void run() {
if (action.equals("schedule")) {
schedule(args);
command.success();
}
else if (action.equals("update")) {
update(args);
command.success();
}
else if (action.equals("cancel")) {
cancel(args);
command.success();
}
else if (action.equals("cancelAll")) {
cancelAll();
command.success();
}
else if (action.equals("clear")) {
clear(args);
command.success();
}
else if (action.equals("clearAll")) {
clearAll();
command.success();
}
else if (action.equals("isPresent")) {
isPresent(args.optInt(0), command);
}
else if (action.equals("isScheduled")) {
isScheduled(args.optInt(0), command);
}
else if (action.equals("isTriggered")) {
isTriggered(args.optInt(0), command);
}
else if (action.equals("getAllIds")) {
getAllIds(command);
}
else if (action.equals("getScheduledIds")) {
getScheduledIds(command);
}
else if (action.equals("getTriggeredIds")) {
getTriggeredIds(command);
}
else if (action.equals("getSingle")) {
getSingle(args, command);
}
else if (action.equals("getSingleScheduled")) {
getSingleScheduled(args, command);
}
else if (action.equals("getSingleTriggered")) {
getSingleTriggered(args, command);
}
else if (action.equals("getAll")) {
getAll(args, command);
}
else if (action.equals("getScheduled")) {
getScheduled(args, command);
}
else if (action.equals("getTriggered")) {
getTriggered(args, command);
}
else if (action.equals("deviceready")) {
deviceready();
}
}
});
return true;
}
/**
* Schedule multiple local notifications.
*
* @param notifications
* Properties for each local notification
*/
private void schedule (JSONArray notifications) {
for (int i = 0; i < notifications.length(); i++) {
JSONObject options = notifications.optJSONObject(i);
try {
Notification notification =
getNotificationMgr().schedule(options, TriggerReceiver.class);
fireEvent("schedule", notification);
}
catch(Exception generic) {
//silently ignore the exception
//on some samsung devices there is a known bug where a 500 alarms limit can crash the app
//http://developer.samsung.com/forum/board/thread/view.do?boardName=General&messageId=280286&listLines=15&startId=zzzzz%7E&searchSubId=0000000001
}
}
}
/**
* Update multiple local notifications.
*
* @param updates
* Notification properties including their IDs
*/
private void update (JSONArray updates) {
for (int i = 0; i < updates.length(); i++) {
JSONObject update = updates.optJSONObject(i);
int id = update.optInt("id", 0);
Notification notification =
getNotificationMgr().update(id, update, TriggerReceiver.class);
if (notification == null)
continue;
fireEvent("update", notification);
}
}
/**
* Cancel multiple local notifications.
*
* @param ids
* Set of local notification IDs
*/
private void cancel (JSONArray ids) {
for (int i = 0; i < ids.length(); i++) {
int id = ids.optInt(i, 0);
Notification notification =
getNotificationMgr().cancel(id);
if (notification == null)
continue;
fireEvent("cancel", notification);
}
}
/**
* Cancel all scheduled notifications.
*/
private void cancelAll() {
getNotificationMgr().cancelAll();
fireEvent("cancelall");
}
/**
* Clear multiple local notifications without canceling them.
*
* @param ids
* Set of local notification IDs
*/
private void clear(JSONArray ids){
for (int i = 0; i < ids.length(); i++) {
int id = ids.optInt(i, 0);
Notification notification =
getNotificationMgr().clear(id);
if (notification == null)
continue;
fireEvent("clear", notification);
}
}
/**
* Clear all triggered notifications without canceling them.
*/
private void clearAll() {
getNotificationMgr().clearAll();
fireEvent("clearall");
}
/**
* If a notification with an ID is present.
*
* @param id
* Notification ID
* @param command
* The callback context used when calling back into JavaScript.
*/
private void isPresent (int id, CallbackContext command) {
boolean exist = getNotificationMgr().exist(id);
PluginResult result = new PluginResult(
PluginResult.Status.OK, exist);
command.sendPluginResult(result);
}
/**
* If a notification with an ID is scheduled.
*
* @param id
* Notification ID
* @param command
* The callback context used when calling back into JavaScript.
*/
private void isScheduled (int id, CallbackContext command) {
boolean exist = getNotificationMgr().exist(
id, Notification.Type.SCHEDULED);
PluginResult result = new PluginResult(
PluginResult.Status.OK, exist);
command.sendPluginResult(result);
}
/**
* If a notification with an ID is triggered.
*
* @param id
* Notification ID
* @param command
* The callback context used when calling back into JavaScript.
*/
private void isTriggered (int id, CallbackContext command) {
boolean exist = getNotificationMgr().exist(
id, Notification.Type.TRIGGERED);
PluginResult result = new PluginResult(
PluginResult.Status.OK, exist);
command.sendPluginResult(result);
}
/**
* Set of IDs from all existent notifications.
*
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getAllIds (CallbackContext command) {
List<Integer> ids = getNotificationMgr().getIds();
command.success(new JSONArray(ids));
}
/**
* Set of IDs from all scheduled notifications.
*
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getScheduledIds (CallbackContext command) {
List<Integer> ids = getNotificationMgr().getIdsByType(
Notification.Type.SCHEDULED);
command.success(new JSONArray(ids));
}
/**
* Set of IDs from all triggered notifications.
*
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getTriggeredIds (CallbackContext command) {
List<Integer> ids = getNotificationMgr().getIdsByType(
Notification.Type.TRIGGERED);
command.success(new JSONArray(ids));
}
/**
* Options from local notification.
*
* @param ids
* Set of local notification IDs
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getSingle (JSONArray ids, CallbackContext command) {
getOptions(ids.optString(0), Notification.Type.ALL, command);
}
/**
* Options from scheduled notification.
*
* @param ids
* Set of local notification IDs
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getSingleScheduled (JSONArray ids, CallbackContext command) {
getOptions(ids.optString(0), Notification.Type.SCHEDULED, command);
}
/**
* Options from triggered notification.
*
* @param ids
* Set of local notification IDs
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getSingleTriggered (JSONArray ids, CallbackContext command) {
getOptions(ids.optString(0), Notification.Type.TRIGGERED, command);
}
/**
* Set of options from local notification.
*
* @param ids
* Set of local notification IDs
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getAll (JSONArray ids, CallbackContext command) {
getOptions(ids, Notification.Type.ALL, command);
}
/**
* Set of options from scheduled notifications.
*
* @param ids
* Set of local notification IDs
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getScheduled (JSONArray ids, CallbackContext command) {
getOptions(ids, Notification.Type.SCHEDULED, command);
}
/**
* Set of options from triggered notifications.
*
* @param ids
* Set of local notification IDs
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getTriggered (JSONArray ids, CallbackContext command) {
getOptions(ids, Notification.Type.TRIGGERED, command);
}
/**
* Options from local notification.
*
* @param id
* Set of local notification IDs
* @param type
* The local notification life cycle type
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getOptions (String id, Notification.Type type,
CallbackContext command) {
JSONArray ids = new JSONArray().put(id);
PluginResult result;
List<JSONObject> options =
getNotificationMgr().getOptionsBy(type, toList(ids));
if (options.isEmpty()) {
// Status.NO_RESULT led to no callback invocation :(
// Status.OK led to no NPE and crash
result = new PluginResult(PluginResult.Status.NO_RESULT);
} else {
result = new PluginResult(PluginResult.Status.OK, options.get(0));
}
command.sendPluginResult(result);
}
/**
* Set of options from local notifications.
*
* @param ids
* Set of local notification IDs
* @param type
* The local notification life cycle type
* @param command
* The callback context used when calling back into JavaScript.
*/
private void getOptions (JSONArray ids, Notification.Type type,
CallbackContext command) {
List<JSONObject> options;
if (ids.length() == 0) {
options = getNotificationMgr().getOptionsByType(type);
} else {
options = getNotificationMgr().getOptionsBy(type, toList(ids));
}
command.success(new JSONArray(options));
}
/**
* Call all pending callbacks after the deviceready event has been fired.
*/
private static synchronized void deviceready () {
isInBackground = false;
deviceready = true;
for (String js : eventQueue) {
sendJavascript(js);
}
eventQueue.clear();
}
/**
* Fire given event on JS side. Does inform all event listeners.
*
* @param event
* The event name
*/
private void fireEvent (String event) {
fireEvent(event, null);
}
/**
* Fire given event on JS side. Does inform all event listeners.
*
* @param event
* The event name
* @param notification
* Optional local notification to pass the id and properties.
*/
static void fireEvent (String event, Notification notification) {
String state = getApplicationState();
String params = "\"" + state + "\"";
if (notification != null) {
params = notification.toString() + "," + params;
}
String js = "cordova.plugins.notification.local.core.fireEvent(" +
"\"" + event + "\"," + params + ")";
sendJavascript(js);
}
/**
* Use this instead of deprecated sendJavascript
*
* @param js
* JS code snippet as string
*/
private static synchronized void sendJavascript(final String js) {
if (!deviceready) {
eventQueue.add(js);
return;
}
Runnable jsLoader = new Runnable() {
public void run() {
webView.loadUrl("javascript:" + js);
}
};
try {
Method post = webView.getClass().getMethod("post",Runnable.class);
post.invoke(webView,jsLoader);
} catch(Exception e) {
((Activity)(webView.getContext())).runOnUiThread(jsLoader);
}
}
/**
* Convert JSON array of integers to List.
*
* @param ary
* Array of integers
*/
private List<Integer> toList (JSONArray ary) {
ArrayList<Integer> list = new ArrayList<Integer>();
for (int i = 0; i < ary.length(); i++) {
list.add(ary.optInt(i));
}
return list;
}
/**
* Current application state.
*
* @return
* "background" or "foreground"
*/
static String getApplicationState () {
return isInBackground ? "background" : "foreground";
}
/**
* Notification manager instance.
*/
private Manager getNotificationMgr() {
return Manager.getInstance(cordova.getActivity());
}
}
/*
* Copyright (c) 2014-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
package de.appplant.cordova.plugin.localnotification;
import de.appplant.cordova.plugin.notification.AbstractRestoreReceiver;
import de.appplant.cordova.plugin.notification.Builder;
import de.appplant.cordova.plugin.notification.Notification;
/**
* This class is triggered upon reboot of the device. It needs to re-register
* the alarms with the AlarmManager since these alarms are lost in case of
* reboot.
*/
public class RestoreReceiver extends AbstractRestoreReceiver {
/**
* Called when a local notification need to be restored.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onRestore (Notification notification) {
if (notification.isScheduled()) {
notification.schedule();
} else {
notification.cancel();
}
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder
.setTriggerReceiver(TriggerReceiver.class)
.setClearReceiver(ClearReceiver.class)
.setClickActivity(ClickActivity.class)
.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.localnotification;
import de.appplant.cordova.plugin.notification.Builder;
import de.appplant.cordova.plugin.notification.Notification;
/**
* The alarm receiver is triggered when a scheduled alarm is fired. This class
* reads the information in the intent and displays this information in the
* Android notification bar. The notification uses the default notification
* sound and it vibrates the phone.
*/
public class TriggerReceiver extends de.appplant.cordova.plugin.notification.TriggerReceiver {
/**
* Called when a local notification was triggered. Does present the local
* notification, re-schedule the alarm if necessary and fire trigger event.
*
* @param notification
* Wrapper around the local notification
* @param updated
* If an update has triggered or the original
*/
@Override
public void onTrigger (Notification notification, boolean updated) {
super.onTrigger(notification, updated);
if (!updated) {
LocalNotification.fireEvent("trigger", notification);
}
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder
.setTriggerReceiver(TriggerReceiver.class)
.setClickActivity(ClickActivity.class)
.setClearReceiver(ClearReceiver.class)
.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Abstract delete receiver for local notifications. Creates the local
* notification and calls the event functions for further proceeding.
*/
abstract public class AbstractClearReceiver extends BroadcastReceiver {
/**
* Called when the notification was cleared from the notification center.
*
* @param context
* Application context
* @param intent
* Received intent with content data
*/
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
JSONObject options;
try {
String data = bundle.getString(Options.EXTRA);
options = new JSONObject(data);
} catch (JSONException e) {
e.printStackTrace();
return;
}
Notification notification =
new Builder(context, options).build();
onClear(notification);
}
/**
* Called when a local notification was cleared from outside of the app.
*
* @param notification
* Wrapper around the local notification
*/
abstract public void onClear (Notification notification);
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
/**
* Abstract content receiver activity for local notifications. Creates the
* local notification and calls the event functions for further proceeding.
*/
abstract public class AbstractClickActivity extends Activity {
/**
* Called when local notification was clicked to launch the main intent.
*
* @param state
* Saved instance state
*/
@Override
public void onCreate (Bundle state) {
super.onCreate(state);
Intent intent = getIntent();
Bundle bundle = intent.getExtras();
Context context = getApplicationContext();
try {
String data = bundle.getString(Options.EXTRA);
JSONObject options = new JSONObject(data);
Builder builder =
new Builder(context, options);
Notification notification =
buildNotification(builder);
onClick(notification);
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* Fixes "Unable to resume activity" error.
* Theme_NoDisplay: Activities finish themselves before being resumed.
*/
@Override
protected void onResume() {
super.onResume();
finish();
}
/**
* Called when local notification was clicked by the user.
*
* @param notification
* Wrapper around the local notification
*/
abstract public void onClick (Notification notification);
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
abstract public Notification buildNotification (Builder builder);
/**
* Launch main intent from package.
*/
public void launchApp() {
Context context = getApplicationContext();
String pkgName = context.getPackageName();
Intent intent = context
.getPackageManager()
.getLaunchIntentForPackage(pkgName);
intent.addFlags(
Intent.FLAG_ACTIVITY_REORDER_TO_FRONT | Intent.FLAG_ACTIVITY_SINGLE_TOP);
context.startActivity(intent);
}
}
/*
* Copyright (c) 2014-2015 by appPlant UG. All rights reserved.
*
* @APPPLANT_LICENSE_HEADER_START@
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*
* @APPPLANT_LICENSE_HEADER_END@
*/
package de.appplant.cordova.plugin.notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import org.json.JSONObject;
import java.util.List;
/**
* This class is triggered upon reboot of the device. It needs to re-register
* the alarms with the AlarmManager since these alarms are lost in case of
* reboot.
*/
abstract public class AbstractRestoreReceiver extends BroadcastReceiver {
/**
* Called on device reboot.
*
* @param context
* Application context
* @param intent
* Received intent with content data
*/
@Override
public void onReceive (Context context, Intent intent) {
Manager notificationMgr =
Manager.getInstance(context);
List<JSONObject> options =
notificationMgr.getOptions();
for (JSONObject data : options) {
Builder builder = new Builder(context, data);
Notification notification =
buildNotification(builder);
onRestore(notification);
}
}
/**
* Called when a local notification need to be restored.
*
* @param notification
* Wrapper around the local notification
*/
abstract public void onRestore (Notification notification);
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
abstract public Notification buildNotification (Builder builder);
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Calendar;
/**
* Abstract broadcast receiver for local notifications. Creates the
* notification options and calls the event functions for further proceeding.
*/
abstract public class AbstractTriggerReceiver extends BroadcastReceiver {
/**
* Called when an alarm was triggered.
*
* @param context
* Application context
* @param intent
* Received intent with content data
*/
@Override
public void onReceive(Context context, Intent intent) {
Bundle bundle = intent.getExtras();
Options options;
try {
String data = bundle.getString(Options.EXTRA);
JSONObject dict = new JSONObject(data);
options = new Options(context).parse(dict);
} catch (JSONException e) {
e.printStackTrace();
return;
}
if (options == null)
return;
if (isFirstAlarmInFuture(options))
return;
Builder builder = new Builder(options);
Notification notification = buildNotification(builder);
boolean updated = notification.isUpdate(false);
onTrigger(notification, updated);
}
/**
* Called when a local notification was triggered.
*
* @param notification
* Wrapper around the local notification
* @param updated
* If an update has triggered or the original
*/
abstract public void onTrigger (Notification notification, boolean updated);
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
abstract public Notification buildNotification (Builder builder);
/*
* If you set a repeating alarm at 11:00 in the morning and it
* should trigger every morning at 08:00 o'clock, it will
* immediately fire. E.g. Android tries to make up for the
* 'forgotten' reminder for that day. Therefore we ignore the event
* if Android tries to 'catch up'.
*/
private Boolean isFirstAlarmInFuture (Options options) {
Notification notification = new Builder(options).build();
if (!notification.isRepeating())
return false;
Calendar now = Calendar.getInstance();
Calendar alarm = Calendar.getInstance();
alarm.setTime(notification.getOptions().getTriggerDate());
int alarmHour = alarm.get(Calendar.HOUR_OF_DAY);
int alarmMin = alarm.get(Calendar.MINUTE);
int currentHour = now.get(Calendar.HOUR_OF_DAY);
int currentMin = now.get(Calendar.MINUTE);
return (currentHour != alarmHour && currentMin != alarmMin);
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.content.Context;
import android.content.res.AssetManager;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.StrictMode;
import android.util.Log;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.UUID;
/**
* Util class to map unified asset URIs to native URIs. URIs like file:///
* map to absolute paths while file:// point relatively to the www folder
* within the asset resources. And res:// means a resource from the native
* res folder. Remote assets are accessible via http:// for example.
*/
class AssetUtil {
// Name of the storage folder
private static final String STORAGE_FOLDER = "/localnotification";
// Placeholder URI for default sound
private static final String DEFAULT_SOUND = "res://platform_default";
// Ref to the context passed through the constructor to access the
// resources and app directory.
private final Context context;
/**
* Constructor
*
* @param context
* Application context
*/
private AssetUtil(Context context) {
this.context = context;
}
/**
* Static method to retrieve class instance.
*
* @param context
* Application context
*/
static AssetUtil getInstance(Context context) {
return new AssetUtil(context);
}
/**
* Parse path path to native URI.
*
* @param path
* Path to path file
*/
Uri parseSound (String path) {
if (path == null || path.isEmpty())
return Uri.EMPTY;
if (path.equalsIgnoreCase(DEFAULT_SOUND)) {
return RingtoneManager.getDefaultUri(RingtoneManager
.TYPE_NOTIFICATION);
}
return parse(path);
}
/**
* The URI for a path.
*
* @param path
* The given path
*/
Uri parse (String path) {
if (path.startsWith("res:")) {
return getUriForResourcePath(path);
} else if (path.startsWith("file:///")) {
return getUriFromPath(path);
} else if (path.startsWith("file://")) {
return getUriFromAsset(path);
} else if (path.startsWith("http")){
return getUriFromRemote(path);
}
return Uri.EMPTY;
}
/**
* URI for a file.
*
* @param path
* Absolute path like file:///...
*
* @return
* URI pointing to the given path
*/
private Uri getUriFromPath(String path) {
String absPath = path.replaceFirst("file://", "");
File file = new File(absPath);
if (!file.exists()) {
Log.e("Asset", "File not found: " + file.getAbsolutePath());
return Uri.EMPTY;
}
return Uri.fromFile(file);
}
/**
* URI for an asset.
*
* @param path
* Asset path like file://...
*
* @return
* URI pointing to the given path
*/
private Uri getUriFromAsset(String path) {
String resPath = path.replaceFirst("file:/", "www");
String fileName = resPath.substring(resPath.lastIndexOf('/') + 1);
File file = getTmpFile(fileName);
if (file == null) {
Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
try {
AssetManager assets = context.getAssets();
FileOutputStream outStream = new FileOutputStream(file);
InputStream inputStream = assets.open(resPath);
copyFile(inputStream, outStream);
outStream.flush();
outStream.close();
return Uri.fromFile(file);
} catch (Exception e) {
Log.e("Asset", "File not found: assets/" + resPath);
e.printStackTrace();
}
return Uri.EMPTY;
}
/**
* The URI for a resource.
*
* @param path
* The given relative path
*
* @return
* URI pointing to the given path
*/
private Uri getUriForResourcePath(String path) {
String resPath = path.replaceFirst("res://", "");
int resId = getResIdForDrawable(resPath);
File file = getTmpFile();
if (resId == 0) {
Log.e("Asset", "File not found: " + resPath);
return Uri.EMPTY;
}
if (file == null) {
Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
try {
Resources res = context.getResources();
FileOutputStream outStream = new FileOutputStream(file);
InputStream inputStream = res.openRawResource(resId);
copyFile(inputStream, outStream);
outStream.flush();
outStream.close();
return Uri.fromFile(file);
} catch (Exception e) {
e.printStackTrace();
}
return Uri.EMPTY;
}
/**
* Uri from remote located content.
*
* @param path
* Remote address
*
* @return
* Uri of the downloaded file
*/
private Uri getUriFromRemote(String path) {
File file = getTmpFile();
if (file == null) {
Log.e("Asset", "Missing external cache dir");
return Uri.EMPTY;
}
try {
URL url = new URL(path);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
StrictMode.ThreadPolicy policy =
new StrictMode.ThreadPolicy.Builder().permitAll().build();
StrictMode.setThreadPolicy(policy);
connection.setRequestProperty("Connection", "close");
connection.setConnectTimeout(5000);
connection.connect();
InputStream input = connection.getInputStream();
FileOutputStream outStream = new FileOutputStream(file);
copyFile(input, outStream);
outStream.flush();
outStream.close();
return Uri.fromFile(file);
} catch (MalformedURLException e) {
Log.e("Asset", "Incorrect URL");
e.printStackTrace();
} catch (FileNotFoundException e) {
Log.e("Asset", "Failed to create new File from HTTP Content");
e.printStackTrace();
} catch (IOException e) {
Log.e("Asset", "No Input can be created from http Stream");
e.printStackTrace();
}
return Uri.EMPTY;
}
/**
* Copy content from input stream into output stream.
*
* @param in
* The input stream
* @param out
* The output stream
*/
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while ((read = in.read(buffer)) != -1) {
out.write(buffer, 0, read);
}
}
/**
* Resource ID for drawable.
*
* @param resPath
* Resource path as string
*/
int getResIdForDrawable(String resPath) {
int resId = getResIdForDrawable(getPkgName(), resPath);
if (resId == 0) {
resId = getResIdForDrawable("android", resPath);
}
return resId;
}
/**
* Resource ID for drawable.
*
* @param clsName
* Relative package or global android name space
* @param resPath
* Resource path as string
*/
int getResIdForDrawable(String clsName, String resPath) {
String drawable = getBaseName(resPath);
int resId = 0;
try {
Class<?> cls = Class.forName(clsName + ".R$drawable");
resId = (Integer) cls.getDeclaredField(drawable).get(Integer.class);
} catch (Exception ignore) {}
return resId;
}
/**
* Convert drawable resource to bitmap.
*
* @param drawable
* Drawable resource name
*/
Bitmap getIconFromDrawable (String drawable) {
Resources res = context.getResources();
int iconId;
iconId = getResIdForDrawable(getPkgName(), drawable);
if (iconId == 0) {
iconId = getResIdForDrawable("android", drawable);
}
if (iconId == 0) {
iconId = android.R.drawable.screen_background_dark_transparent;
}
return BitmapFactory.decodeResource(res, iconId);
}
/**
* Convert URI to Bitmap.
*
* @param uri
* Internal image URI
*/
Bitmap getIconFromUri (Uri uri) throws IOException {
InputStream input = context.getContentResolver().openInputStream(uri);
return BitmapFactory.decodeStream(input);
}
/**
* Extract name of drawable resource from path.
*
* @param resPath
* Resource path as string
*/
private String getBaseName (String resPath) {
String drawable = resPath;
if (drawable.contains("/")) {
drawable = drawable.substring(drawable.lastIndexOf('/') + 1);
}
if (resPath.contains(".")) {
drawable = drawable.substring(0, drawable.lastIndexOf('.'));
}
return drawable;
}
/**
* Returns a file located under the external cache dir of that app.
*
* @return
* File with a random UUID name
*/
private File getTmpFile () {
// If random UUID is not be enough see
// https://github.com/LukePulverenti/cordova-plugin-local-notifications/blob/267170db14044cbeff6f4c3c62d9b766b7a1dd62/src/android/notification/AssetUtil.java#L255
return getTmpFile(UUID.randomUUID().toString());
}
/**
* Returns a file located under the external cache dir of that app.
*
* @param name
* The name of the file
* @return
* File with the provided name
*/
private File getTmpFile (String name) {
File dir = context.getExternalCacheDir();
if (dir == null) {
Log.e("Asset", "Missing external cache dir");
return null;
}
String storage = dir.toString() + STORAGE_FOLDER;
//noinspection ResultOfMethodCallIgnored
new File(storage).mkdir();
return new File(storage, name);
}
/**
* Package name specified by context.
*/
private String getPkgName () {
return context.getPackageName();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import org.json.JSONObject;
import java.util.Random;
/**
* Builder class for local notifications. Build fully configured local
* notification specified by JSON object passed from JS side.
*/
public class Builder {
// Application context passed by constructor
private final Context context;
// Notification options passed by JS
private final Options options;
// Receiver to handle the trigger event
private Class<?> triggerReceiver;
// Receiver to handle the clear event
private Class<?> clearReceiver = ClearReceiver.class;
// Activity to handle the click event
private Class<?> clickActivity = ClickActivity.class;
/**
* Constructor
*
* @param context
* Application context
* @param options
* Notification options
*/
public Builder(Context context, JSONObject options) {
this.context = context;
this.options = new Options(context).parse(options);
}
/**
* Constructor
*
* @param options
* Notification options
*/
public Builder(Options options) {
this.context = options.getContext();
this.options = options;
}
/**
* Set trigger receiver.
*
* @param receiver
* Broadcast receiver
*/
public Builder setTriggerReceiver(Class<?> receiver) {
this.triggerReceiver = receiver;
return this;
}
/**
* Set clear receiver.
*
* @param receiver
* Broadcast receiver
*/
public Builder setClearReceiver(Class<?> receiver) {
this.clearReceiver = receiver;
return this;
}
/**
* Set click activity.
*
* @param activity
* Activity
*/
public Builder setClickActivity(Class<?> activity) {
this.clickActivity = activity;
return this;
}
/**
* Creates the notification with all its options passed through JS.
*/
public Notification build() {
Uri sound = options.getSoundUri();
int smallIcon = options.getSmallIcon();
int ledColor = options.getLedColor();
NotificationCompat.Builder builder;
builder = new NotificationCompat.Builder(context)
.setDefaults(0)
.setContentTitle(options.getTitle())
.setContentText(options.getText())
.setNumber(options.getBadgeNumber())
.setTicker(options.getText())
.setAutoCancel(options.isAutoClear())
.setOngoing(options.isOngoing())
.setColor(options.getColor());
if (ledColor != 0) {
builder.setLights(ledColor, 100, 100);
}
if (sound != null) {
builder.setSound(sound);
}
if (smallIcon == 0) {
builder.setSmallIcon(options.getIcon());
} else {
builder.setSmallIcon(options.getSmallIcon());
builder.setLargeIcon(options.getIconBitmap());
}
applyDeleteReceiver(builder);
applyContentReceiver(builder);
return new Notification(context, options, builder, triggerReceiver);
}
/**
* Set intent to handle the delete event. Will clean up some persisted
* preferences.
*
* @param builder
* Local notification builder instance
*/
private void applyDeleteReceiver(NotificationCompat.Builder builder) {
if (clearReceiver == null)
return;
Intent intent = new Intent(context, clearReceiver)
.setAction(options.getIdStr())
.putExtra(Options.EXTRA, options.toString());
PendingIntent deleteIntent = PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setDeleteIntent(deleteIntent);
}
/**
* Set intent to handle the click event. Will bring the app to
* foreground.
*
* @param builder
* Local notification builder instance
*/
private void applyContentReceiver(NotificationCompat.Builder builder) {
if (clickActivity == null)
return;
Intent intent = new Intent(context, clickActivity)
.putExtra(Options.EXTRA, options.toString())
.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY);
int reqCode = new Random().nextInt();
PendingIntent contentIntent = PendingIntent.getActivity(
context, reqCode, intent, PendingIntent.FLAG_UPDATE_CURRENT);
builder.setContentIntent(contentIntent);
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
/**
* The clear intent receiver is triggered when the user clears a
* notification manually. It un-persists the cleared notification from the
* shared preferences.
*/
public class ClearReceiver extends AbstractClearReceiver {
/**
* Called when a local notification was cleared from outside of the app.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClear (Notification notification) {
notification.clear();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
/**
* The receiver activity is triggered when a notification is clicked by a user.
* The activity calls the background callback and brings the launch intent
* up to foreground.
*/
public class ClickActivity extends AbstractClickActivity {
/**
* Called when local notification was clicked by the user. Will
* move the app to foreground.
*
* @param notification
* Wrapper around the local notification
*/
@Override
public void onClick(Notification notification) {
launchApp();
if (notification.isRepeating()) {
notification.clear();
} else {
notification.cancel();
}
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
public Notification buildNotification (Builder builder) {
return builder.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.SharedPreferences;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import static de.appplant.cordova.plugin.notification.Notification.PREF_KEY;
/**
* Central way to access all or single local notifications set by specific
* state like triggered or scheduled. Offers shortcut ways to schedule,
* cancel or clear local notifications.
*/
public class Manager {
// Context passed through constructor and used for notification builder.
private Context context;
/**
* Constructor
*
* @param context
* Application context
*/
private Manager(Context context){
this.context = context;
}
/**
* Static method to retrieve class instance.
*
* @param context
* Application context
*/
public static Manager getInstance(Context context) {
return new Manager(context);
}
/**
* Schedule local notification specified by JSON object.
*
* @param options
* JSON object with set of options
* @param receiver
* Receiver to handle the trigger event
*/
public Notification schedule (JSONObject options, Class<?> receiver) {
return schedule(new Options(context).parse(options), receiver);
}
/**
* Schedule local notification specified by options object.
*
* @param options
* Set of notification options
* @param receiver
* Receiver to handle the trigger event
*/
public Notification schedule (Options options, Class<?> receiver) {
Notification notification = new Builder(options)
.setTriggerReceiver(receiver)
.build();
notification.schedule();
return notification;
}
/**
* Clear local notification specified by ID.
*
* @param id
* The notification ID
* @param updates
* JSON object with notification options
* @param receiver
* Receiver to handle the trigger event
*/
public Notification update (int id, JSONObject updates, Class<?> receiver) {
Notification notification = get(id);
if (notification == null)
return null;
notification.cancel();
JSONObject options = mergeJSONObjects(
notification.getOptions().getDict(), updates);
try {
options.put("updated", true);
} catch (JSONException ignore) {}
return schedule(options, receiver);
}
/**
* Clear local notification specified by ID.
*
* @param id
* The notification ID
*/
public Notification clear (int id) {
Notification notification = get(id);
if (notification != null) {
notification.clear();
}
return notification;
}
/**
* Clear local notification specified by ID.
*
* @param id
* The notification ID
*/
public Notification cancel (int id) {
Notification notification = get(id);
if (notification != null) {
notification.cancel();
}
return notification;
}
/**
* Clear all local notifications.
*/
public void clearAll () {
List<Notification> notifications = getAll();
for (Notification notification : notifications) {
notification.clear();
}
getNotMgr().cancelAll();
}
/**
* Cancel all local notifications.
*/
public void cancelAll () {
List<Notification> notifications = getAll();
for (Notification notification : notifications) {
notification.cancel();
}
getNotMgr().cancelAll();
}
/**
* All local notifications IDs.
*/
public List<Integer> getIds() {
Set<String> keys = getPrefs().getAll().keySet();
ArrayList<Integer> ids = new ArrayList<Integer>();
for (String key : keys) {
try {
ids.add(Integer.parseInt(key));
} catch (NumberFormatException e) {
e.printStackTrace();
}
}
return ids;
}
/**
* All local notification IDs for given type.
*
* @param type
* The notification life cycle type
*/
public List<Integer> getIdsByType(Notification.Type type) {
List<Notification> notifications = getAll();
ArrayList<Integer> ids = new ArrayList<Integer>();
for (Notification notification : notifications) {
if (notification.getType() == type) {
ids.add(notification.getId());
}
}
return ids;
}
/**
* List of local notifications with matching ID.
*
* @param ids
* Set of notification IDs
*/
public List<Notification> getByIds(List<Integer> ids) {
ArrayList<Notification> notifications = new ArrayList<Notification>();
for (int id : ids) {
Notification notification = get(id);
if (notification != null) {
notifications.add(notification);
}
}
return notifications;
}
/**
* List of all local notification.
*/
public List<Notification> getAll() {
return getByIds(getIds());
}
/**
* List of local notifications from given type.
*
* @param type
* The notification life cycle type
*/
public List<Notification> getByType(Notification.Type type) {
List<Notification> notifications = getAll();
ArrayList<Notification> list = new ArrayList<Notification>();
if (type == Notification.Type.ALL)
return notifications;
for (Notification notification : notifications) {
if (notification.getType() == type) {
list.add(notification);
}
}
return list;
}
/**
* List of local notifications with matching ID from given type.
*
* @param type
* The notification life cycle type
* @param ids
* Set of notification IDs
*/
@SuppressWarnings("UnusedDeclaration")
public List<Notification> getBy(Notification.Type type, List<Integer> ids) {
ArrayList<Notification> notifications = new ArrayList<Notification>();
for (int id : ids) {
Notification notification = get(id);
if (notification != null && notification.isScheduled()) {
notifications.add(notification);
}
}
return notifications;
}
/**
* If a notification with an ID exists.
*
* @param id
* Notification ID
*/
public boolean exist (int id) {
return get(id) != null;
}
/**
* If a notification with an ID and type exists.
*
* @param id
* Notification ID
* @param type
* Notification type
*/
public boolean exist (int id, Notification.Type type) {
Notification notification = get(id);
return notification != null && notification.getType() == type;
}
/**
* List of properties from all local notifications.
*/
public List<JSONObject> getOptions() {
return getOptionsById(getIds());
}
/**
* List of properties from local notifications with matching ID.
*
* @param ids
* Set of notification IDs
*/
public List<JSONObject> getOptionsById(List<Integer> ids) {
ArrayList<JSONObject> options = new ArrayList<JSONObject>();
for (int id : ids) {
Notification notification = get(id);
if (notification != null) {
options.add(notification.getOptions().getDict());
}
}
return options;
}
/**
* List of properties from all local notifications from given type.
*
* @param type
* The notification life cycle type
*/
public List<JSONObject> getOptionsByType(Notification.Type type) {
ArrayList<JSONObject> options = new ArrayList<JSONObject>();
List<Notification> notifications = getByType(type);
for (Notification notification : notifications) {
options.add(notification.getOptions().getDict());
}
return options;
}
/**
* List of properties from local notifications with matching ID from
* given type.
*
* @param type
* The notification life cycle type
* @param ids
* Set of notification IDs
*/
public List<JSONObject> getOptionsBy(Notification.Type type,
List<Integer> ids) {
if (type == Notification.Type.ALL)
return getOptionsById(ids);
ArrayList<JSONObject> options = new ArrayList<JSONObject>();
List<Notification> notifications = getByIds(ids);
for (Notification notification : notifications) {
if (notification.getType() == type) {
options.add(notification.getOptions().getDict());
}
}
return options;
}
/**
* Get existent local notification.
*
* @param id
* Notification ID
*/
public Notification get(int id) {
Map<String, ?> alarms = getPrefs().getAll();
String notId = Integer.toString(id);
JSONObject options;
if (!alarms.containsKey(notId))
return null;
try {
String json = alarms.get(notId).toString();
options = new JSONObject(json);
} catch (JSONException e) {
e.printStackTrace();
return null;
}
Builder builder = new Builder(context, options);
return builder.build();
}
/**
* Merge two JSON objects.
*
* @param obj1
* JSON object
* @param obj2
* JSON object with new options
*/
private JSONObject mergeJSONObjects (JSONObject obj1, JSONObject obj2) {
Iterator it = obj2.keys();
while (it.hasNext()) {
try {
String key = (String)it.next();
obj1.put(key, obj2.opt(key));
} catch (JSONException e) {
e.printStackTrace();
}
}
return obj1;
}
/**
* Shared private preferences for the application.
*/
private SharedPreferences getPrefs () {
return context.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);
}
/**
* Notification manager for the application.
*/
private NotificationManager getNotMgr () {
return (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.app.AlarmManager;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.support.v4.app.NotificationCompat;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
/**
* Wrapper class around OS notification class. Handles basic operations
* like show, delete, cancel for a single local notification instance.
*/
public class Notification {
// Used to differ notifications by their life cycle state
public enum Type {
ALL, SCHEDULED, TRIGGERED
}
// Default receiver to handle the trigger event
private static Class<?> defaultReceiver = TriggerReceiver.class;
// Key for private preferences
static final String PREF_KEY = "LocalNotification";
// Application context passed by constructor
private final Context context;
// Notification options passed by JS
private final Options options;
// Builder with full configuration
private final NotificationCompat.Builder builder;
// Receiver to handle the trigger event
private Class<?> receiver = defaultReceiver;
/**
* Constructor
*
* @param context
* Application context
* @param options
* Parsed notification options
* @param builder
* Pre-configured notification builder
*/
protected Notification (Context context, Options options,
NotificationCompat.Builder builder, Class<?> receiver) {
this.context = context;
this.options = options;
this.builder = builder;
this.receiver = receiver != null ? receiver : defaultReceiver;
}
/**
* Get application context.
*/
public Context getContext () {
return context;
}
/**
* Get notification options.
*/
public Options getOptions () {
return options;
}
/**
* Get notification ID.
*/
public int getId () {
return options.getId();
}
/**
* If it's a repeating notification.
*/
public boolean isRepeating () {
return getOptions().getRepeatInterval() > 0;
}
/**
* If the notification was in the past.
*/
public boolean wasInThePast () {
return new Date().after(options.getTriggerDate());
}
/**
* If the notification is scheduled.
*/
public boolean isScheduled () {
return isRepeating() || !wasInThePast();
}
/**
* If the notification is triggered.
*/
public boolean isTriggered () {
return wasInThePast();
}
/**
* If the notification is an update.
*
* @param keepFlag
* Set to false to remove the flag from the option map
*/
protected boolean isUpdate (boolean keepFlag) {
boolean updated = options.getDict().optBoolean("updated", false);
if (!keepFlag) {
options.getDict().remove("updated");
}
return updated;
}
/**
* Notification type can be one of pending or scheduled.
*/
public Type getType () {
return isScheduled() ? Type.SCHEDULED : Type.TRIGGERED;
}
/**
* Schedule the local notification.
*/
public void schedule() {
long triggerTime = options.getTriggerTime();
persist();
// Intent gets called when the Notification gets fired
Intent intent = new Intent(context, receiver)
.setAction(options.getIdStr())
.putExtra(Options.EXTRA, options.toString());
PendingIntent pi = PendingIntent.getBroadcast(
context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
if (isRepeating()) {
getAlarmMgr().setRepeating(AlarmManager.RTC_WAKEUP,
triggerTime, options.getRepeatInterval(), pi);
} else {
getAlarmMgr().set(AlarmManager.RTC_WAKEUP, triggerTime, pi);
}
}
/**
* Clear the local notification without canceling repeating alarms.
*/
public void clear () {
if (!isRepeating() && wasInThePast())
unpersist();
if (!isRepeating())
getNotMgr().cancel(getId());
}
/**
* Cancel the local notification.
*
* Create an intent that looks similar, to the one that was registered
* using schedule. Making sure the notification id in the action is the
* same. Now we can search for such an intent using the 'getService'
* method and cancel it.
*/
public void cancel() {
Intent intent = new Intent(context, receiver)
.setAction(options.getIdStr());
PendingIntent pi = PendingIntent.
getBroadcast(context, 0, intent, 0);
getAlarmMgr().cancel(pi);
getNotMgr().cancel(options.getId());
unpersist();
}
/**
* Present the local notification to user.
*/
public void show () {
// TODO Show dialog when in foreground
showNotification();
}
/**
* Show as local notification when in background.
*/
@SuppressWarnings("deprecation")
private void showNotification () {
int id = getOptions().getId();
if (Build.VERSION.SDK_INT <= 15) {
// Notification for HoneyComb to ICS
getNotMgr().notify(id, builder.getNotification());
} else {
// Notification for Jellybean and above
getNotMgr().notify(id, builder.build());
}
}
/**
* Count of triggers since schedule.
*/
public int getTriggerCountSinceSchedule() {
long now = System.currentTimeMillis();
long triggerTime = options.getTriggerTime();
if (!wasInThePast())
return 0;
if (!isRepeating())
return 1;
return (int) ((now - triggerTime) / options.getRepeatInterval());
}
/**
* Encode options to JSON.
*/
public String toString() {
JSONObject dict = options.getDict();
JSONObject json = new JSONObject();
try {
json = new JSONObject(dict.toString());
} catch (JSONException e) {
e.printStackTrace();
}
json.remove("firstAt");
json.remove("updated");
json.remove("soundUri");
json.remove("iconUri");
return json.toString();
}
/**
* Persist the information of this notification to the Android Shared
* Preferences. This will allow the application to restore the notification
* upon device reboot, app restart, retrieve notifications, aso.
*/
private void persist () {
SharedPreferences.Editor editor = getPrefs().edit();
editor.putString(options.getIdStr(), options.toString());
if (Build.VERSION.SDK_INT < 9) {
editor.commit();
} else {
editor.apply();
}
}
/**
* Remove the notification from the Android shared Preferences.
*/
private void unpersist () {
SharedPreferences.Editor editor = getPrefs().edit();
editor.remove(options.getIdStr());
if (Build.VERSION.SDK_INT < 9) {
editor.commit();
} else {
editor.apply();
}
}
/**
* Shared private preferences for the application.
*/
private SharedPreferences getPrefs () {
return context.getSharedPreferences(PREF_KEY, Context.MODE_PRIVATE);
}
/**
* Notification manager for the application.
*/
private NotificationManager getNotMgr () {
return (NotificationManager) context
.getSystemService(Context.NOTIFICATION_SERVICE);
}
/**
* Alarm manager for the application.
*/
private AlarmManager getAlarmMgr () {
return (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
}
/**
* Set default receiver to handle the trigger event.
*
* @param receiver
* broadcast receiver
*/
public static void setDefaultTriggerReceiver (Class<?> receiver) {
defaultReceiver = receiver;
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
import android.app.AlarmManager;
import android.content.Context;
import android.graphics.Bitmap;
import android.net.Uri;
import android.support.v4.app.NotificationCompat;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Date;
/**
* Wrapper around the JSON object passed through JS which contains all
* possible option values. Class provides simple readers and more advanced
* methods to convert independent values into platform specific values.
*/
public class Options {
// Key name for bundled extras
static final String EXTRA = "NOTIFICATION_OPTIONS";
// The original JSON object
private JSONObject options = new JSONObject();
// Repeat interval
private long interval = 0;
// Application context
private final Context context;
// Asset util instance
private final AssetUtil assets;
/**
* Constructor
*
* @param context
* Application context
*/
public Options(Context context){
this.context = context;
this.assets = AssetUtil.getInstance(context);
}
/**
* Parse given JSON properties.
*
* @param options
* JSON properties
*/
public Options parse (JSONObject options) {
this.options = options;
parseInterval();
parseAssets();
return this;
}
/**
* Parse repeat interval.
*/
private void parseInterval() {
String every = options.optString("every").toLowerCase();
if (every.isEmpty()) {
interval = 0;
} else
if (every.equals("second")) {
interval = 1000;
} else
if (every.equals("minute")) {
interval = AlarmManager.INTERVAL_FIFTEEN_MINUTES / 15;
} else
if (every.equals("hour")) {
interval = AlarmManager.INTERVAL_HOUR;
} else
if (every.equals("day")) {
interval = AlarmManager.INTERVAL_DAY;
} else
if (every.equals("week")) {
interval = AlarmManager.INTERVAL_DAY * 7;
} else
if (every.equals("month")) {
interval = AlarmManager.INTERVAL_DAY * 31;
} else
if (every.equals("quarter")) {
interval = AlarmManager.INTERVAL_HOUR * 2190;
} else
if (every.equals("year")) {
interval = AlarmManager.INTERVAL_DAY * 365;
} else {
try {
interval = Integer.parseInt(every) * 60000;
} catch (Exception e) {
e.printStackTrace();
}
}
}
/**
* Parse asset URIs.
*/
private void parseAssets() {
if (options.has("iconUri") && !options.optBoolean("updated"))
return;
Uri iconUri = assets.parse(options.optString("icon", "res://icon"));
Uri soundUri = assets.parseSound(options.optString("sound", null));
try {
options.put("iconUri", iconUri.toString());
options.put("soundUri", soundUri.toString());
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* Application context.
*/
public Context getContext () {
return context;
}
/**
* Wrapped JSON object.
*/
JSONObject getDict () {
return options;
}
/**
* Text for the local notification.
*/
public String getText() {
return options.optString("text", "");
}
/**
* Repeat interval (day, week, month, year, aso.)
*/
public long getRepeatInterval() {
return interval;
}
/**
* Badge number for the local notification.
*/
public int getBadgeNumber() {
return options.optInt("badge", 0);
}
/**
* ongoing flag for local notifications.
*/
public Boolean isOngoing() {
return options.optBoolean("ongoing", false);
}
/**
* autoClear flag for local notifications.
*/
public Boolean isAutoClear() {
return options.optBoolean("autoClear", false);
}
/**
* ID for the local notification as a number.
*/
public Integer getId() {
return options.optInt("id", 0);
}
/**
* ID for the local notification as a string.
*/
public String getIdStr() {
return getId().toString();
}
/**
* Trigger date.
*/
public Date getTriggerDate() {
return new Date(getTriggerTime());
}
/**
* Trigger date in milliseconds.
*/
public long getTriggerTime() {
return options.optLong("at", 0) * 1000;
}
/**
* Title for the local notification.
*/
public String getTitle() {
String title = options.optString("title", "");
if (title.isEmpty()) {
title = context.getApplicationInfo().loadLabel(
context.getPackageManager()).toString();
}
return title;
}
/**
* @return
* The notification color for LED
*/
public int getLedColor() {
String hex = options.optString("led", null);
if (hex == null) {
return 0;
}
int aRGB = Integer.parseInt(hex, 16);
return aRGB + 0xFF000000;
}
/**
* @return
* The notification background color for the small icon
* Returns null, if no color is given.
*/
public int getColor() {
String hex = options.optString("color", null);
if (hex == null) {
return NotificationCompat.COLOR_DEFAULT;
}
int aRGB = Integer.parseInt(hex, 16);
return aRGB + 0xFF000000;
}
/**
* Sound file path for the local notification.
*/
public Uri getSoundUri() {
Uri uri = null;
try{
uri = Uri.parse(options.optString("soundUri"));
} catch (Exception e){
e.printStackTrace();
}
return uri;
}
/**
* Icon bitmap for the local notification.
*/
public Bitmap getIconBitmap() {
Bitmap bmp;
try {
Uri uri = Uri.parse(options.optString("iconUri"));
bmp = assets.getIconFromUri(uri);
} catch (Exception e){
e.printStackTrace();
bmp = assets.getIconFromDrawable("icon");
}
return bmp;
}
/**
* Icon resource ID for the local notification.
*/
public int getIcon () {
String icon = options.optString("icon", "");
int resId = assets.getResIdForDrawable(icon);
if (resId == 0) {
resId = getSmallIcon();
}
if (resId == 0) {
resId = android.R.drawable.ic_popup_reminder;
}
return resId;
}
/**
* Small icon resource ID for the local notification.
*/
public int getSmallIcon () {
String icon = options.optString("smallIcon", "");
return assets.getResIdForDrawable(icon);
}
/**
* JSON object as string.
*/
public String toString() {
return options.toString();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
package de.appplant.cordova.plugin.notification;
/**
* The alarm receiver is triggered when a scheduled alarm is fired. This class
* reads the information in the intent and displays this information in the
* Android notification bar. The notification uses the default notification
* sound and it vibrates the phone.
*/
public class TriggerReceiver extends AbstractTriggerReceiver {
/**
* Called when a local notification was triggered. Does present the local
* notification and re-schedule the alarm if necessary.
*
* @param notification
* Wrapper around the local notification
* @param updated
* If an update has triggered or the original
*/
@Override
public void onTrigger (Notification notification, boolean updated) {
notification.show();
}
/**
* Build notification specified by options.
*
* @param builder
* Notification builder
*/
@Override
public Notification buildNotification (Builder builder) {
return builder.build();
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import <Cordova/CDVPlugin.h>
@import UserNotifications;
@interface APPLocalNotification : CDVPlugin <UNUserNotificationCenterDelegate>
// Set launchDetails object
- (void) launchDetails:(CDVInvokedUrlCommand*)command;
// Execute all queued events
- (void) deviceready:(CDVInvokedUrlCommand*)command;
// Check permission to show notifications
- (void) check:(CDVInvokedUrlCommand*)command;
// Request permission to show notifications
- (void) request:(CDVInvokedUrlCommand*)command;
// Register/update an action group
- (void) registerCategory:(CDVInvokedUrlCommand*)command;
// Schedule notifications
- (void) schedule:(CDVInvokedUrlCommand*)command;
//// Update set of notifications
//- (void) update:(CDVInvokedUrlCommand*)command;
// Clear notifications by id
- (void) clear:(CDVInvokedUrlCommand*)command;
// Clear all notifications
- (void) clearAll:(CDVInvokedUrlCommand*)command;
// Cancel notifications by id
- (void) cancel:(CDVInvokedUrlCommand*)command;
// Cancel all notifications
- (void) cancelAll:(CDVInvokedUrlCommand*)command;
// Notification type
- (void) type:(CDVInvokedUrlCommand*)command;
// List of all notification IDs
- (void) ids:(CDVInvokedUrlCommand*)command;
// List of all scheduled notification IDs
- (void) scheduledIds:(CDVInvokedUrlCommand*)command;
// List of all triggered notification IDs
- (void) triggeredIds:(CDVInvokedUrlCommand*)command;
// Notification by id
- (void) notification:(CDVInvokedUrlCommand*)command;
// List of notifications by id
- (void) notifications:(CDVInvokedUrlCommand*)command;
// List of scheduled notifications by id
- (void) scheduledNotifications:(CDVInvokedUrlCommand*)command;
// List of triggered notifications by id
- (void) triggeredNotifications:(CDVInvokedUrlCommand*)command;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPLocalNotification.h"
#import "APPNotificationOptions.h"
#import "UNUserNotificationCenter+APPLocalNotification.h"
#import "UNNotificationRequest+APPLocalNotification.h"
#import "APPNotificationContent.h"
@interface APPLocalNotification ()
@property (strong, nonatomic) UIApplication* app;
@property (strong, nonatomic) UNUserNotificationCenter* center;
@property (readwrite, assign) BOOL deviceready;
@property (readonly, nonatomic, retain) NSArray* launchDetails;
@property (readonly, nonatomic, retain) NSMutableArray* eventQueue;
@end
@implementation APPLocalNotification
@synthesize deviceready, eventQueue;
#pragma mark -
#pragma mark Interface
/**
* Set launchDetails object.
*
* @return [ Void ]
*/
- (void) launchDetails:(CDVInvokedUrlCommand*)command
{
if (!_launchDetails)
return;
NSString* js;
js = [NSString stringWithFormat:
@"cordova.plugins.notification.local.launchDetails = {id:%@, action:'%@'}",
_launchDetails[0], _launchDetails[1]];
[self.commandDelegate evalJs:js];
_launchDetails = NULL;
}
/**
* Execute all queued events.
*
* @return [ Void ]
*/
- (void) deviceready:(CDVInvokedUrlCommand*)command
{
deviceready = YES;
for (NSString* js in eventQueue) {
[self.commandDelegate evalJs:js];
}
[eventQueue removeAllObjects];
}
/**
* Schedule notifications.
*
* @param [Array<Hash>] properties A list of key-value properties.
*
* @return [ Void ]
*/
- (void) schedule:(CDVInvokedUrlCommand*)command
{
NSArray* notifications = command.arguments;
[self.commandDelegate runInBackground:^{
for (NSDictionary* options in notifications) {
APPNotificationContent* notification;
notification = [[APPNotificationContent alloc]
initWithOptions:options];
[self scheduleNotification:notification];
}
[self execCallback:command];
}];
}
///**
// * Update a set of notifications.
// *
// * @param properties
// * A dict of properties for each notification
// */
//- (void) update:(CDVInvokedUrlCommand*)command
//{
// NSArray* notifications = command.arguments;
//
// [self.commandDelegate runInBackground:^{
// if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"10.0")) {
// for (NSDictionary* options in notifications) {
// NSNumber* id = [options objectForKey:@"id"];
// UNNotificationRequest* notification;
//
// notification = [_center getNotificationWithId:id];
//
// if (!notification)
// continue;
//
// // [self updateNotification:[notification copy]
// // withOptions:options];
// //
// // [self fireEvent:@"update" notification:notification];
// //
// // if (notifications.count > 1) {
// // [NSThread sleepForTimeInterval:0.01];
// // }
// }
// } else {
// for (NSDictionary* options in notifications) {
// NSNumber* id = [options objectForKey:@"id"];
// UILocalNotification* notification;
//
// notification = [_app localNotificationWithId:id];
//
// if (!notification)
// continue;
//
// [self updateLocalNotification:[notification copy]
// withOptions:options];
//
// [self fireEvent:@"update" localnotification:notification];
//
// if (notifications.count > 1) {
// [NSThread sleepForTimeInterval:0.01];
// }
// }
// }
//
// [self execCallback:command];
// }];
//}
/**
* Clear notifications by id.
*
* @param [ Array<Int> ] The IDs of the notifications to clear.
*
* @return [ Void ]
*/
- (void) clear:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) {
UNNotificationRequest* notification;
notification = [_center getNotificationWithId:id];
if (!notification)
continue;
[_center clearNotification:notification];
[self fireEvent:@"clear" notification:notification];
}
[self execCallback:command];
}];
}
/**
* Clear all local notifications.
*
* @return [ Void ]
*/
- (void) clearAll:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
[_center clearAllNotifications];
[_app setApplicationIconBadgeNumber:0];
[self fireEvent:@"clearall"];
[self execCallback:command];
}];
}
/**
* Cancel notifications by id.
*
* @param [ Array<Int> ] The IDs of the notifications to clear.
*
* @return [ Void ]
*/
- (void) cancel:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
for (NSNumber* id in command.arguments) {
UNNotificationRequest* notification;
notification = [_center getNotificationWithId:id];
if (!notification)
continue;
[_center cancelNotification:notification];
[self fireEvent:@"cancel" notification:notification];
}
[self execCallback:command];
}];
}
/**
* Cancel all local notifications.
*
* @return [ Void ]
*/
- (void) cancelAll:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
[_center cancelAllNotifications];
[_app setApplicationIconBadgeNumber:0];
[self fireEvent:@"cancelall"];
[self execCallback:command];
}];
}
/**
* Get type of notification.
*
* @param [ Int ] id The ID of the notification.
*
* @return [ Void ]
*/
- (void) type:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
NSNumber* id = [command argumentAtIndex:0];
NSString* type;
switch ([_center getTypeOfNotificationWithId:id]) {
case NotifcationTypeScheduled:
type = @"scheduled";
break;
case NotifcationTypeTriggered:
type = @"triggered";
break;
default:
type = @"unknown";
}
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsString:type];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* List of all notification IDs.
*
* @return [ Void ]
*/
- (void) ids:(CDVInvokedUrlCommand*)command
{
[self ids:command byType:NotifcationTypeAll];
}
/**
* List of all scheduled notification IDs.
*
* @return [ Void ]
*/
- (void) scheduledIds:(CDVInvokedUrlCommand*)command
{
[self ids:command byType:NotifcationTypeScheduled];
}
/**
* List of all triggered notification IDs.
*
* @return [ Void ]
*/
- (void) triggeredIds:(CDVInvokedUrlCommand*)command
{
[self ids:command byType:NotifcationTypeTriggered];
}
/**
* List of ids for given local notifications.
*
* @param [ APPNotificationType ] type The type of notifications to look for.
*
* @return [ Void ]
*/
- (void) ids:(CDVInvokedUrlCommand*)command
byType:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
NSArray* ids = [_center getNotificationIdsByType:type];
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:ids];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* Notification by id.
*
* @param [ Number ] id The id of the notification to return.
*
* @return [ Void ]
*/
- (void) notification:(CDVInvokedUrlCommand*)command
{
[self.commandDelegate runInBackground:^{
NSArray* ids = command.arguments;
NSArray* notifications;
notifications = [_center getNotificationOptionsById:ids];
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsDictionary:[notifications firstObject]];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* List of notifications by id.
*
* @param [ Array<Number> ] ids The ids of the notifications to return.
*
* @return [ Void ]
*/
- (void) notifications:(CDVInvokedUrlCommand*)command
{
[self notifications:command byType:NotifcationTypeAll];
}
/**
* List of scheduled notifications by id.
*
* @param [ Array<Number> ] ids The ids of the notifications to return.
*
* @return [ Void ]
*/
- (void) scheduledNotifications:(CDVInvokedUrlCommand*)command
{
[self notifications:command byType:NotifcationTypeScheduled];
}
/**
* List of triggered notifications by id.
*
* @param [ Array<Number> ] ids The ids of the notifications to return.
*
* @return [ Void ]
*/
- (void) triggeredNotifications:(CDVInvokedUrlCommand *)command
{
[self notifications:command byType:NotifcationTypeTriggered];
}
/**
* List of notifications by type or id.
*
* @param [ APPNotificationType ] type The type of notifications to look for.
*
* @return [ Void ]
*/
- (void) notifications:(CDVInvokedUrlCommand*)command
byType:(APPNotificationType)type;
{
[self.commandDelegate runInBackground:^{
NSArray* ids = command.arguments;
NSArray* notifications;
if (ids.count > 0) {
notifications = [_center getNotificationOptionsById:ids];
}
else {
notifications = [_center getNotificationOptionsByType:type];
}
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsArray:notifications];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* Check for permission to show notifications.
*
* @return [ Void ]
*/
- (void) check:(CDVInvokedUrlCommand*)command
{
[_center getNotificationSettingsWithCompletionHandler:^(UNNotificationSettings* settings) {
BOOL authorized = settings.authorizationStatus == UNAuthorizationStatusAuthorized;
BOOL enabled = settings.notificationCenterSetting == UNNotificationSettingEnabled;
BOOL permitted = authorized && enabled;
CDVPluginResult* result;
result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK
messageAsBool:permitted];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}];
}
/**
* Request for permission to show notifcations.
*
* @return [ Void ]
*/
- (void) request:(CDVInvokedUrlCommand*)command
{
UNAuthorizationOptions options =
(UNAuthorizationOptionBadge | UNAuthorizationOptionSound | UNAuthorizationOptionAlert);
[_center requestAuthorizationWithOptions:options completionHandler:^(BOOL granted, NSError* e) {
[self check:command];
}];
}
/**
* Register/update an action group.
*
* @return [ Void ]
*/
- (void) registerCategory:(CDVInvokedUrlCommand *)command
{
[self.commandDelegate runInBackground:^{
NSDictionary* options = command.arguments[0];
APPNotificationContent* notification;
notification = [[APPNotificationContent alloc]
initWithOptions:options];
[_center addNotificationCategory:notification.category];
[self execCallback:command];
}];
}
#pragma mark -
#pragma mark Private
/**
* Schedule the local notification.
*/
- (void) scheduleNotification:(APPNotificationContent*)notification
{
__weak APPLocalNotification* weakSelf = self;
UNNotificationRequest* request = notification.request;
[_center addNotificationCategory:notification.category];
[_center addNotificationRequest:request withCompletionHandler:^(NSError* e) {
__strong APPLocalNotification* strongSelf = weakSelf;
[strongSelf fireEvent:@"add" notification:request];
}];
}
///**
// * Update the local notification.
// */
//- (void) updateNotification:(UILocalNotification*)notification
// withOptions:(NSDictionary*)newOptions
//{APPNotificationRequest*
// NSMutableDictionary* options = [notification.userInfo mutableCopy];
//
// [options addEntriesFromDictionary:newOptions];
// [options setObject:[NSDate date] forKey:@"updatedAt"];
//
//// notification = [[UILocalNotification alloc]
//// initWithOptions:options];
////
//// [self scheduleLocalNotification:notification];
//}
#pragma mark -
#pragma mark UNUserNotificationCenterDelegate
/**
* Called when a notification is delivered to the app while being in foreground.
*/
- (void) userNotificationCenter:(UNUserNotificationCenter *)center
willPresentNotification:(UNNotification *)notification
withCompletionHandler:(void (^)(UNNotificationPresentationOptions))completionHandler
{
[self fireEvent:@"trigger" notification:notification.request];
completionHandler(UNNotificationPresentationOptionBadge|UNNotificationPresentationOptionSound|UNNotificationPresentationOptionAlert);
}
/**
* Called to let your app know which action was selected by the user for a given
* notification.
*/
- (void) userNotificationCenter:(UNUserNotificationCenter *)center
didReceiveNotificationResponse:(UNNotificationResponse *)response
withCompletionHandler:(void (^)())completionHandler
{
UNNotificationRequest* notification = response.notification.request;
NSMutableDictionary* data = [[NSMutableDictionary alloc] init];
NSString* action = response.actionIdentifier;
NSString* event = action;
completionHandler();
if ([action isEqualToString:UNNotificationDefaultActionIdentifier]) {
event = @"click";
} else
if ([action isEqualToString:UNNotificationDismissActionIdentifier]) {
event = @"clear";
}
if (!deviceready && [event isEqualToString:@"click"]) {
_launchDetails = @[notification.options.id, event];
}
if (![event isEqualToString:@"clear"]) {
[self fireEvent:@"clear" notification:notification];
}
if ([response isKindOfClass:UNTextInputNotificationResponse.class]) {
[data setObject:((UNTextInputNotificationResponse*) response).userText
forKey:@"text"];
}
[self fireEvent:event notification:notification data:data];
}
#pragma mark -
#pragma mark Life Cycle
/**
* Registers obervers after plugin was initialized.
*/
- (void) pluginInitialize
{
eventQueue = [[NSMutableArray alloc] init];
_app = [UIApplication sharedApplication];
_center = [UNUserNotificationCenter currentNotificationCenter];
_center.delegate = self;
[_center registerGeneralNotificationCategory];
}
#pragma mark -
#pragma mark Helper
/**
* Simply invokes the callback without any parameter.
*/
- (void) execCallback:(CDVInvokedUrlCommand*)command
{
CDVPluginResult *result = [CDVPluginResult
resultWithStatus:CDVCommandStatus_OK];
[self.commandDelegate sendPluginResult:result
callbackId:command.callbackId];
}
/**
* Fire general event.
*
* @param [ NSString* ] event The name of the event to fire.
*
* @return [ Void ]
*/
- (void) fireEvent:(NSString*)event
{
NSMutableDictionary* data = [[NSMutableDictionary alloc] init];
[self fireEvent:event notification:NULL data:data];
}
/**
* Fire event for about a local notification.
*
* @param [ NSString* ] event The name of the event to fire.
* @param [ APPNotificationRequest* ] notification The local notification.
*
* @return [ Void ]
*/
- (void) fireEvent:(NSString*)event
notification:(UNNotificationRequest*)notitification
{
NSMutableDictionary* data = [[NSMutableDictionary alloc] init];
[self fireEvent:event notification:notitification data:data];
}
/**
* Fire event for about a local notification.
*
* @param [ NSString* ] event The name of the event to fire.
* @param [ APPNotificationRequest* ] notification The local notification.
* @param [ NSMutableDictionary* ] data Event object with additional data.
*
* @return [ Void ]
*/
- (void) fireEvent:(NSString*)event
notification:(UNNotificationRequest*)request
data:(NSMutableDictionary*)data
{
BOOL isActive = [_app applicationState] == UIApplicationStateActive;
NSString *js, *params, *notiAsJSON, *dataAsJSON;
NSData* dataAsData;
[data setObject:event forKey:@"event"];
[data setObject:@(isActive) forKey:@"foreground"];
if (request) {
notiAsJSON = [request encodeToJSON];
[data setObject:request.options.id forKey:@"notification"];
}
dataAsData =
[NSJSONSerialization dataWithJSONObject:data options:0 error:NULL];
dataAsJSON =
[[NSString alloc] initWithData:dataAsData encoding:NSUTF8StringEncoding];
if (request) {
params = [NSString stringWithFormat:@"%@,%@", notiAsJSON, dataAsJSON];
} else {
params = [NSString stringWithFormat:@"%@", dataAsJSON];
}
js = [NSString stringWithFormat:
@"cordova.plugins.notification.local.core.fireEvent('%@', %@)",
event, params];
if (deviceready) {
[self.commandDelegate evalJs:js];
} else {
[self.eventQueue addObject:js];
}
}
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationOptions.h"
@import UserNotifications;
@interface APPNotificationContent : UNMutableNotificationContent
- (id) initWithOptions:(NSDictionary*)dict;
- (APPNotificationOptions*) options;
- (UNNotificationRequest*) request;
- (UNNotificationCategory*) category;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationContent.h"
#import "APPNotificationOptions.h"
#import <objc/runtime.h>
@import UserNotifications;
static char optionsKey;
@implementation APPNotificationContent : UNMutableNotificationContent
#pragma mark -
#pragma mark Init
/**
* Initialize a notification with the given options.
*
* @param [ NSDictionary* ] dict A key-value property map.
*
* @return [ UNMutableNotificationContent ]
*/
- (id) initWithOptions:(NSDictionary*)dict
{
self = [self init];
[self setUserInfo:dict];
[self __init];
return self;
}
/**
* Initialize a notification by using the options found under userInfo.
*
* @return [ Void ]
*/
- (void) __init
{
APPNotificationOptions* options = self.options;
self.title = options.title;
self.subtitle = options.subtitle;
self.body = options.text;
self.sound = options.sound;
self.badge = options.badge;
self.attachments = options.attachments;
self.categoryIdentifier = options.categoryId;
}
#pragma mark -
#pragma mark Public
/**
* The options used to initialize the notification.
*
* @return [ APPNotificationOptions* ] options
*/
- (APPNotificationOptions*) options
{
APPNotificationOptions* options = [self getOptions];
if (!options) {
options = [[APPNotificationOptions alloc]
initWithDict:[self userInfo]];
[self setOptions:options];
}
return options;
}
/**
* The notifcations request ready to add to the notification center including
* all informations about trigger behavior.
*
* @return [ UNNotificationRequest* ]
*/
- (UNNotificationRequest*) request
{
APPNotificationOptions* opts = [self getOptions];
return [UNNotificationRequest requestWithIdentifier:opts.identifier
content:self
trigger:opts.trigger];
}
/**
* The category for the notification with all the actions.
*
* @return [ UNNotificationCategory* ]
*/
- (UNNotificationCategory*) category
{
NSString* categoryId = self.categoryIdentifier;
NSArray* actions = self.options.actions;
if (!actions.count)
return NULL;
return [UNNotificationCategory categoryWithIdentifier:categoryId
actions:actions
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
}
#pragma mark -
#pragma mark Private
/**
* The options used to initialize the notification.
*
* @return [ APPNotificationOptions* ]
*/
- (APPNotificationOptions*) getOptions
{
return objc_getAssociatedObject(self, &optionsKey);
}
/**
* Set the options used to initialize the notification.
*
* @param [ NSDictionary* ] dict A key-value property map.
*
* @return [ Void ]
*/
- (void) setOptions:(APPNotificationOptions*)options
{
objc_setAssociatedObject(self, &optionsKey,
options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
@import UserNotifications;
@interface APPNotificationOptions : NSObject
@property (readonly, getter=id) NSNumber* id;
@property (readonly, getter=identifier) NSString* identifier;
@property (readonly, getter=categoryId) NSString* categoryId;
@property (readonly, getter=title) NSString* title;
@property (readonly, getter=subtitle) NSString* subtitle;
@property (readonly, getter=badge) NSNumber* badge;
@property (readonly, getter=text) NSString* text;
@property (readonly, getter=sound) UNNotificationSound* sound;
@property (readonly, getter=userInfo) NSDictionary* userInfo;
@property (readonly, getter=actions) NSArray<UNNotificationAction *> * actions;
@property (readonly, getter=attachments) NSArray<UNNotificationAttachment *> * attachments;
- (id) initWithDict:(NSDictionary*)dict;
- (UNNotificationTrigger*) trigger;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationOptions.h"
#import "UNUserNotificationCenter+APPLocalNotification.h"
@import CoreLocation;
@import UserNotifications;
@interface APPNotificationOptions ()
// The dictionary which contains all notification properties
@property(nonatomic, retain) NSDictionary* dict;
@end
@implementation APPNotificationOptions : NSObject
@synthesize dict;
#pragma mark -
#pragma mark Initialization
/**
* Initialize by using the given property values.
*
* @param [ NSDictionary* ] dict A key-value property map.
*
* @return [ APPNotificationOptions ]
*/
- (id) initWithDict:(NSDictionary*)dictionary
{
self = [self init];
self.dict = dictionary;
[self actions];
return self;
}
#pragma mark -
#pragma mark Properties
/**
* The type for the notification.
*
* @return [ NSString* ]
*/
- (NSString*) triggerType
{
NSString* type = [dict objectForKey:@"trigger"];
return type.length ? type : @"normal";
}
/**
* The ID for the notification.
*
* @return [ NSNumber* ]
*/
- (NSNumber*) id
{
NSInteger id = [[dict objectForKey:@"id"] integerValue];
return [NSNumber numberWithInteger:id];
}
/**
* The ID for the notification.
*
* @return [ NSString* ]
*/
- (NSString*) identifier
{
return [NSString stringWithFormat:@"%@", self.id];
}
/**
* The title for the notification.
*
* @return [ NSString* ]
*/
- (NSString*) title
{
return [dict objectForKey:@"title"];
}
/**
* The subtitle for the notification.
*
* @return [ NSString* ]
*/
- (NSString*) subtitle
{
NSArray *parts = [self.title componentsSeparatedByString:@"\n"];
return parts.count < 2 ? @"" : [parts objectAtIndex:1];
}
/**
* The text for the notification.
*
* @return [ NSString* ]
*/
- (NSString*) text
{
return [dict objectForKey:@"text"];
}
/**
* The badge number for the notification.
*
* @return [ NSNumber* ]
*/
- (NSNumber*) badge
{
id value = [dict objectForKey:@"badge"];
return (value == NULL) ? NULL : [NSNumber numberWithInt:[value intValue]];
}
/**
* The category of the notification.
*
* @return [ NSString* ]
*/
- (NSString*) categoryId
{
NSString* value = [dict objectForKey:@"actionGroupId"];
return value.length ? value : kAPPGeneralCategory;
}
/**
* The sound file for the notification.
*
* @return [ UNNotificationSound* ]
*/
- (UNNotificationSound*) sound
{
NSString* path = [dict objectForKey:@"sound"];
NSString* file;
if (!path.length)
return NULL;
if ([path isEqualToString:@"res://platform_default"])
return [UNNotificationSound defaultSound];
if ([path hasPrefix:@"file:/"]) {
file = [self soundNameForAsset:path];
} else
if ([path hasPrefix:@"res:"]) {
file = [self soundNameForResource:path];
}
return [UNNotificationSound soundNamed:file];
}
/**
* Additional content to attach.
*
* @return [ UNNotificationSound* ]
*/
- (NSArray<UNNotificationAttachment *> *) attachments
{
NSArray* paths = [dict objectForKey:@"attachments"];
NSMutableArray* attachments = [[NSMutableArray alloc] init];
if (!paths)
return attachments;
for (NSString* path in paths) {
NSURL* url = [self urlForAttachmentPath:path];
UNNotificationAttachment* attachment;
attachment = [UNNotificationAttachment attachmentWithIdentifier:path
URL:url
options:NULL
error:NULL];
if (attachment) {
[attachments addObject:attachment];
}
}
return attachments;
}
/**
* Additional actions for the notification.
*
* @return [ NSArray* ]
*/
- (NSArray<UNNotificationAction *> *) actions
{
NSArray* items = [dict objectForKey:@"actions"];
NSMutableArray* actions = [[NSMutableArray alloc] init];
if (!items)
return actions;
for (NSDictionary* item in items) {
NSString* id = [item objectForKey:@"id"];
NSString* title = [item objectForKey:@"title"];
NSString* type = [item objectForKey:@"type"];
UNNotificationActionOptions options = UNNotificationActionOptionNone;
UNNotificationAction* action;
if ([[item objectForKey:@"launch"] boolValue]) {
options = UNNotificationActionOptionForeground;
}
if ([[item objectForKey:@"ui"] isEqualToString:@"decline"]) {
options = options | UNNotificationActionOptionDestructive;
}
if ([[item objectForKey:@"needsAuth"] boolValue]) {
options = options | UNNotificationActionOptionAuthenticationRequired;
}
if ([type isEqualToString:@"input"]) {
NSString* submitTitle = [item objectForKey:@"submitTitle"];
NSString* placeholder = [item objectForKey:@"emptyText"];
if (!submitTitle.length) {
submitTitle = @"Submit";
}
action = [UNTextInputNotificationAction actionWithIdentifier:id
title:title
options:options
textInputButtonTitle:submitTitle
textInputPlaceholder:placeholder];
} else
if (!type.length || [type isEqualToString:@"button"]) {
action = [UNNotificationAction actionWithIdentifier:id
title:title
options:options];
} else {
NSLog(@"Unknown action type: %@", type);
}
if (action) {
[actions addObject:action];
}
}
return actions;
}
#pragma mark -
#pragma mark Public
/**
* Specify how and when to trigger the notification.
*
* @return [ UNNotificationTrigger* ]
*/
- (UNNotificationTrigger*) trigger
{
NSString* type = [self triggerType];
if ([type isEqualToString:@"location"])
return [self triggerWithRegion];
if (![type isEqualToString:@"date"])
NSLog(@"Unknown type: %@", type);
if ([self isRepeating])
return [self repeatingTrigger];
return [self nonRepeatingTrigger];
}
/**
* The notification's user info dict.
*
* @return [ NSDictionary* ]
*/
- (NSDictionary*) userInfo
{
if ([dict objectForKey:@"updatedAt"]) {
NSMutableDictionary* data = [dict mutableCopy];
[data removeObjectForKey:@"updatedAt"];
return data;
}
return dict;
}
#pragma mark -
#pragma mark Private
/**
* The date when to fire the notification.
*
* @return [ NSDate* ]
*/
- (NSDate*) triggerDate
{
double timestamp = [[dict objectForKey:@"at"]
doubleValue];
return [NSDate dateWithTimeIntervalSince1970:timestamp];
}
/**
* If the notification shall be repeating.
*
* @return [ BOOL ]
*/
- (BOOL) isRepeating
{
id every = [dict objectForKey:@"every"];
if ([every isKindOfClass:NSString.class])
return ((NSString*) every).length > 0;
if ([every isKindOfClass:NSDictionary.class])
return ((NSDictionary*) every).count > 0;
return every > 0;
}
/**
* Non repeating trigger.
*
* @return [ UNTimeIntervalNotificationTrigger* ]
*/
- (UNTimeIntervalNotificationTrigger*) nonRepeatingTrigger
{
return [UNTimeIntervalNotificationTrigger
triggerWithTimeInterval:[self timeInterval] repeats:NO];
}
/**
* Repeating trigger.
*
* @return [ UNNotificationTrigger* ]
*/
- (UNNotificationTrigger*) repeatingTrigger
{
id every = [dict objectForKey:@"every"];
if ([every isKindOfClass:NSString.class])
return [self triggerWithDateMatchingComponents];
if ([every isKindOfClass:NSDictionary.class])
return [self triggerWithCustomDateMatchingComponents];
return [self triggerWithTimeInterval];
}
/**
* A trigger based on a calendar time defined by the user.
*
* @return [ UNTimeIntervalNotificationTrigger* ]
*/
- (UNTimeIntervalNotificationTrigger*) triggerWithTimeInterval
{
long interval = [[dict objectForKey:@"every"] longValue];
if (interval < 60) {
NSLog(@"time interval must be at least 60 if repeating");
interval = 60;
}
return [UNTimeIntervalNotificationTrigger
triggerWithTimeInterval:interval repeats:YES];
}
/**
* A repeating trigger based on a calendar time intervals defined by the plugin.
*
* @return [ UNCalendarNotificationTrigger* ]
*/
- (UNCalendarNotificationTrigger*) triggerWithDateMatchingComponents
{
NSCalendar* cal = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *date = [cal components:[self repeatInterval]
fromDate:[self triggerDate]];
date.timeZone = [NSTimeZone defaultTimeZone];
return [UNCalendarNotificationTrigger
triggerWithDateMatchingComponents:date repeats:YES];
}
/**
* A repeating trigger based on a calendar time intervals defined by the user.
*
* @return [ UNCalendarNotificationTrigger* ]
*/
- (UNCalendarNotificationTrigger*) triggerWithCustomDateMatchingComponents
{
NSCalendar* cal = [[NSCalendar alloc]
initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
NSDateComponents *date = [self customDateComponents];
date.calendar = cal;
date.timeZone = [NSTimeZone defaultTimeZone];
return [UNCalendarNotificationTrigger
triggerWithDateMatchingComponents:date repeats:YES];
}
/**
* A repeating trigger based on a location region.
*
* @return [ UNLocationNotificationTrigger* ]
*/
- (UNLocationNotificationTrigger*) triggerWithRegion
{
NSArray* center = [dict objectForKey:@"center"];
double radius = [[dict objectForKey:@"radius"] doubleValue];
CLLocationCoordinate2D coord =
CLLocationCoordinate2DMake([center[0] doubleValue], [center[1] doubleValue]);
CLCircularRegion* region =
[[CLCircularRegion alloc] initWithCenter:coord
radius:radius
identifier:self.identifier];
region.notifyOnEntry = [[dict objectForKey:@"notifyOnEntry"] boolValue];
region.notifyOnExit = [[dict objectForKey:@"notifyOnExit"] boolValue];
return [UNLocationNotificationTrigger triggerWithRegion:region repeats:YES];
}
/**
* The time interval between the next fire date and now.
*
* @return [ double ]
*/
- (double) timeInterval
{
return MAX(0.01f, [self.triggerDate timeIntervalSinceDate:[NSDate date]]);
}
/**
* The repeat interval for the notification.
*
* @return [ NSCalendarUnit ]
*/
- (NSCalendarUnit) repeatInterval
{
NSString* interval = [dict objectForKey:@"every"];
NSCalendarUnit units = NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
if ([interval isEqualToString:@"minute"])
return NSCalendarUnitSecond;
if ([interval isEqualToString:@"hour"])
return NSCalendarUnitMinute|NSCalendarUnitSecond;
if ([interval isEqualToString:@"day"])
return NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
if ([interval isEqualToString:@"week"])
return NSCalendarUnitWeekday|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
if ([interval isEqualToString:@"month"])
return NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
if ([interval isEqualToString:@"year"])
return NSCalendarUnitMonth|NSCalendarUnitDay|NSCalendarUnitHour|NSCalendarUnitMinute|NSCalendarUnitSecond;
return units;
}
/**
* The repeat interval for the notification.
*
* @return [ NSDateComponents* ]
*/
- (NSDateComponents*) customDateComponents
{
NSDateComponents* date = [[NSDateComponents alloc] init];
NSDictionary* every = [dict objectForKey:@"every"];
for (NSString* key in every) {
long value = [[every valueForKey:key] longValue];
if ([key isEqualToString:@"second"]) {
date.second = value;
} else
if ([key isEqualToString:@"minute"]) {
date.minute = value;
} else
if ([key isEqualToString:@"hour"]) {
date.hour = value;
} else
if ([key isEqualToString:@"day"]) {
date.day = value;
} else
if ([key isEqualToString:@"weekday"]) {
date.weekday = value;
} else
if ([key isEqualToString:@"weekdayOrdinal"]) {
date.weekdayOrdinal = value;
} else
if ([key isEqualToString:@"week"]) {
date.weekOfYear = value;
} else
if ([key isEqualToString:@"weekOfMonth"]) {
date.weekOfMonth = value;
} else
if ([key isEqualToString:@"month"]) {
date.month = value;
} else
if ([key isEqualToString:@"quarter"]) {
date.quarter = value;
} else
if ([key isEqualToString:@"year"]) {
date.year = value;
}
}
return date;
}
/**
* Convert an assets path to an valid sound name attribute.
*
* @param [ NSString* ] path A relative assets file path.
*
* @return [ NSString* ]
*/
- (NSString*) soundNameForAsset:(NSString*)path
{
return [path stringByReplacingOccurrencesOfString:@"file:/"
withString:@"www"];
}
/**
* Convert a ressource path to an valid sound name attribute.
*
* @param [ NSString* ] path A relative ressource file path.
*
* @return [ NSString* ]
*/
- (NSString*) soundNameForResource:(NSString*)path
{
return [path pathComponents].lastObject;
}
/**
* URL for the specified attachment path.
*
* @param [ NSString* ] path Absolute/relative path or a base64 data.
*
* @return [ NSURL* ]
*/
- (NSURL*) urlForAttachmentPath:(NSString*)path
{
if ([path hasPrefix:@"file:///"])
{
return [self urlForFile:path];
}
else if ([path hasPrefix:@"res:"])
{
return [self urlForResource:path];
}
else if ([path hasPrefix:@"file://"])
{
return [self urlForAsset:path];
}
else if ([path hasPrefix:@"base64:"])
{
return [self urlFromBase64:path];
}
NSFileManager* fm = [NSFileManager defaultManager];
if (![fm fileExistsAtPath:path]){
NSLog(@"File not found: %@", path);
}
return [NSURL fileURLWithPath:path];
}
/**
* URL to an absolute file path.
*
* @param [ NSString* ] path An absolute file path.
*
* @return [ NSURL* ]
*/
- (NSURL*) urlForFile:(NSString*)path
{
NSFileManager* fm = [NSFileManager defaultManager];
NSString* absPath;
absPath = [path stringByReplacingOccurrencesOfString:@"file://"
withString:@""];
if (![fm fileExistsAtPath:absPath]) {
NSLog(@"File not found: %@", absPath);
}
return [NSURL fileURLWithPath:absPath];
}
/**
* URL to a resource file.
*
* @param [ NSString* ] path A relative file path.
*
* @return [ NSURL* ]
*/
- (NSURL*) urlForResource:(NSString*)path
{
NSFileManager* fm = [NSFileManager defaultManager];
NSBundle* mainBundle = [NSBundle mainBundle];
NSString* bundlePath = [mainBundle resourcePath];
if ([path isEqualToString:@"res://icon"]) {
path = @"res://AppIcon60x60@3x.png";
}
NSString* absPath;
absPath = [path stringByReplacingOccurrencesOfString:@"res:/"
withString:@""];
absPath = [bundlePath stringByAppendingString:absPath];
if (![fm fileExistsAtPath:absPath]) {
NSLog(@"File not found: %@", absPath);
}
return [NSURL fileURLWithPath:absPath];
}
/**
* URL to an asset file.
*
* @param path A relative www file path.
*
* @return [ NSURL* ]
*/
- (NSURL*) urlForAsset:(NSString*)path
{
NSFileManager* fm = [NSFileManager defaultManager];
NSBundle* mainBundle = [NSBundle mainBundle];
NSString* bundlePath = [mainBundle bundlePath];
NSString* absPath;
absPath = [path stringByReplacingOccurrencesOfString:@"file:/"
withString:@"/www"];
absPath = [bundlePath stringByAppendingString:absPath];
if (![fm fileExistsAtPath:absPath]) {
NSLog(@"File not found: %@", absPath);
}
return [NSURL fileURLWithPath:absPath];
}
/**
* URL for a base64 encoded string.
*
* @param [ NSString* ] base64String Base64 encoded string.
*
* @return [ NSURL* ]
*/
- (NSURL*) urlFromBase64:(NSString*)base64String
{
NSString *filename = [self getBasenameFromAttachmentPath:base64String];
NSUInteger length = [base64String length];
NSRegularExpression *regex;
NSString *dataString;
regex = [NSRegularExpression regularExpressionWithPattern:@"^base64:[^/]+.."
options:NSRegularExpressionCaseInsensitive
error:Nil];
dataString = [regex stringByReplacingMatchesInString:base64String
options:0
range:NSMakeRange(0, length)
withTemplate:@""];
NSData* data = [[NSData alloc] initWithBase64EncodedString:dataString
options:0];
return [self urlForData:data withFileName:filename];
}
/**
* Extract the attachments basename.
*
* @param [ NSString* ] path The file path or base64 data.
*
* @return [ NSString* ]
*/
- (NSString*) getBasenameFromAttachmentPath:(NSString*)path
{
if ([path hasPrefix:@"base64:"]) {
NSString* pathWithoutPrefix;
pathWithoutPrefix = [path stringByReplacingOccurrencesOfString:@"base64:"
withString:@""];
return [pathWithoutPrefix substringToIndex:
[pathWithoutPrefix rangeOfString:@"//"].location];
}
return path;
}
/**
* Write the data into a temp file.
*
* @param [ NSData* ] data The data to save to file.
* @param [ NSString* ] name The name of the file.
*
* @return [ NSURL* ]
*/
- (NSURL*) urlForData:(NSData*)data withFileName:(NSString*) filename
{
NSFileManager* fm = [NSFileManager defaultManager];
NSString* tempDir = NSTemporaryDirectory();
[fm createDirectoryAtPath:tempDir withIntermediateDirectories:YES
attributes:NULL
error:NULL];
NSString* absPath = [tempDir stringByAppendingPathComponent:filename];
NSURL* url = [NSURL fileURLWithPath:absPath];
[data writeToURL:url atomically:NO];
if (![fm fileExistsAtPath:absPath]) {
NSLog(@"File not found: %@", absPath);
}
return url;
}
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationOptions.h"
@import UserNotifications;
@interface UNNotificationRequest (APPLocalNotification)
// The options provided by the plug-in
- (APPNotificationOptions*) options;
// Encode the user info dict to JSON
- (NSString*) encodeToJSON;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationOptions.h"
#import "UNNotificationRequest+APPLocalNotification.h"
#import "APPNotificationContent.h"
#import <objc/runtime.h>
@import UserNotifications;
static char optionsKey;
@implementation UNNotificationRequest (APPLocalNotification)
/**
* Get associated option object
*/
- (APPNotificationOptions*) getOptions
{
return objc_getAssociatedObject(self, &optionsKey);
}
/**
* Set associated option object
*/
- (void) setOptions:(APPNotificationOptions*)options
{
objc_setAssociatedObject(self, &optionsKey,
options, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
/**
* The options provided by the plug-in.
*/
- (APPNotificationOptions*) options
{
APPNotificationOptions* options = [self getOptions];
if (!options) {
options = [[APPNotificationOptions alloc]
initWithDict:[self.content userInfo]];
[self setOptions:options];
}
return options;
}
/**
* Encode the user info dict to JSON.
*/
- (NSString*) encodeToJSON
{
NSString* json;
NSData* data;
NSMutableDictionary* obj = [self.content.userInfo mutableCopy];
[obj removeObjectForKey:@"updatedAt"];
if (obj == NULL || obj.count == 0)
return json;
data = [NSJSONSerialization dataWithJSONObject:obj
options:NSJSONWritingPrettyPrinted
error:NULL];
json = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
return [json stringByReplacingOccurrencesOfString:@"\n"
withString:@""];
}
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "APPNotificationContent.h"
@interface UNUserNotificationCenter (APPLocalNotification)
extern NSString * const kAPPGeneralCategory;
typedef NS_ENUM(NSUInteger, APPNotificationType) {
NotifcationTypeAll = 0,
NotifcationTypeScheduled = 1,
NotifcationTypeTriggered = 2,
NotifcationTypeUnknown = 3
};
#define APPNotificationType_DEFINED
@property (readonly, getter=getNotifications) NSArray* localNotifications;
@property (readonly, getter=getNotificationIds) NSArray* localNotificationIds;
// Register general notification category to listen for dismiss actions
- (void) registerGeneralNotificationCategory;
// Add the specified category to the list of categories
- (void) addNotificationCategory:(UNNotificationCategory*)category;
// List of all notification IDs from given type
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type;
// Find notification by ID
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id;
// Find notification type by ID
- (APPNotificationType) getTypeOfNotificationWithId:(NSNumber*)id;
// Property list from all local notifications
- (NSArray*) getNotificationOptions;
// Property list from given local notifications
- (NSArray*) getNotificationOptionsById:(NSArray*)ids;
// Property list from all local notifications with type constraint
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type;
// Clear specified notfication
- (void) clearNotification:(UNNotificationRequest*)notification;
// Clear all notfications
- (void) clearAllNotifications;
// Cancel specified notfication
- (void) cancelNotification:(UNNotificationRequest*)notification;
// Cancel all notfications
- (void) cancelAllNotifications;
@end
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
#import "UNUserNotificationCenter+APPLocalNotification.h"
#import "UNNotificationRequest+APPLocalNotification.h"
@import UserNotifications;
NSString * const kAPPGeneralCategory = @"GENERAL";
@implementation UNUserNotificationCenter (APPLocalNotification)
#pragma mark -
#pragma mark NotificationCategory
/**
* Register general notification category to listen for dismiss actions.
*
* @return [ Void ]
*/
- (void) registerGeneralNotificationCategory
{
UNNotificationCategory* category;
category = [UNNotificationCategory
categoryWithIdentifier:kAPPGeneralCategory
actions:@[]
intentIdentifiers:@[]
options:UNNotificationCategoryOptionCustomDismissAction];
[self setNotificationCategories:[NSSet setWithObject:category]];
}
/**
* Add the specified category to the list of categories.
*
* @param [ UNNotificationCategory* ] category The category to add.
*
* @return [ Void ]
*/
- (void) addNotificationCategory:(UNNotificationCategory*)category
{
if (!category)
return;
[self getNotificationCategoriesWithCompletionHandler:^(NSSet<UNNotificationCategory *> *set) {
NSMutableSet* categories = [NSMutableSet setWithSet:set];
for (UNNotificationCategory* item in categories) {
if ([category.identifier isEqualToString:item.identifier]) {
[categories removeObject:item];
break;
}
}
[categories addObject:category];
[self setNotificationCategories:categories];
}];
}
#pragma mark -
#pragma mark LocalNotifications
/**
* List of all delivered or still pending notifications.
*/
- (NSArray*) getNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
[notifications addObjectsFromArray:[self getPendingNotifications]];
[notifications addObjectsFromArray:[self getDeliveredNotifications]];
return notifications;
}
/**
* List of all triggered notifications.
*/
- (NSArray*) getDeliveredNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self getDeliveredNotificationsWithCompletionHandler:^(NSArray<UNNotification *> *delivered) {
for (UNNotification* notification in delivered) {
[notifications addObject:notification.request];
}
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return notifications;
}
/**
* List of all pending notifications.
*/
- (NSArray*) getPendingNotifications
{
NSMutableArray* notifications = [[NSMutableArray alloc] init];
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[self getPendingNotificationRequestsWithCompletionHandler:^(NSArray<UNNotificationRequest *> *requests) {
[notifications addObjectsFromArray:requests];
dispatch_semaphore_signal(sema);
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return notifications;
}
/**
* List of all notifications from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationsByType:(APPNotificationType)type
{
switch (type) {
case NotifcationTypeScheduled:
return [self getPendingNotifications];
case NotifcationTypeTriggered:
return [self getDeliveredNotifications];
default:
return [self getNotifications];
}
}
/**
* List of all local notifications IDs.
*/
- (NSArray*) getNotificationIds
{
NSArray* notifications = [self getNotifications];
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[ids addObject:notification.options.id];
}
return ids;
}
/**
* List of all notifications IDs from given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationIdsByType:(APPNotificationType)type
{
NSArray* notifications = [self getNotificationsByType:type];
NSMutableArray* ids = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[ids addObject:notification.options.id];
}
return ids;
}
/**
* Find notification by ID.
*
* @param id
* Notification ID
*/
- (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id
{
NSArray* notifications = [self getNotifications];
for (UNNotificationRequest* notification in notifications)
{
NSString* fid = [NSString stringWithFormat:@"%@", notification.options.id];
if ([fid isEqualToString:[id stringValue]]) {
return notification;
}
}
return NULL;
}
/**
* Find notification type by ID
*/
- (APPNotificationType) getTypeOfNotificationWithId:(NSNumber*)id
{
NSArray* ids = [self getNotificationIdsByType:NotifcationTypeTriggered];
if ([ids containsObject:id])
return NotifcationTypeTriggered;
ids = [self getNotificationIdsByType:NotifcationTypeScheduled];
if ([ids containsObject:id])
return NotifcationTypeScheduled;
return NotifcationTypeUnknown;
}
/**
* List of properties from all notifications.
*/
- (NSArray*) getNotificationOptions
{
return [self getNotificationOptionsByType:NotifcationTypeAll];
}
/**
* List of properties from all notifications of given type.
*
* @param type
* Notification life cycle type
*/
- (NSArray*) getNotificationOptionsByType:(APPNotificationType)type
{
NSArray* notifications = [self getNotificationsByType:type];
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
[options addObject:notification.options.userInfo];
}
return options;
}
/**
* List of properties from given local notifications.
*
* @param ids
* Notification IDs
*/
- (NSArray*) getNotificationOptionsById:(NSArray*)ids
{
NSArray* notifications = [self getNotifications];
NSMutableArray* options = [[NSMutableArray alloc] init];
for (UNNotificationRequest* notification in notifications)
{
if ([ids containsObject:notification.options.id]) {
[options addObject:notification.options.userInfo];
}
}
return options;
}
/*
* Clear all notfications.
*/
- (void) clearAllNotifications
{
[self removeAllDeliveredNotifications];
}
/*
* Clear Specified notfication.
*
* @param notification
* The notification object
*/
- (void) clearNotification:(UNNotificationRequest*)notification
{
NSArray* ids = [[NSArray alloc]
initWithObjects:notification.identifier, nil];
[self removeDeliveredNotificationsWithIdentifiers:ids];
}
/*
* Cancel all notfications.
*/
- (void) cancelAllNotifications
{
[self removeAllPendingNotificationRequests];
[self removeAllDeliveredNotifications];
}
/*
* Cancel specified notfication.
*
* @param notification
* The notification object
*/
- (void) cancelNotification:(UNNotificationRequest*)notification
{
NSArray* ids = [[NSArray alloc]
initWithObjects:notification.identifier, nil];
[self removeDeliveredNotificationsWithIdentifiers:ids];
[self removePendingNotificationRequestsWithIdentifiers:ids];
}
@end
/*
Copyright 2013-2015 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
var proxy = require('de.appplant.cordova.plugin.local-notification.LocalNotification.Proxy');
var Notifications = Windows.UI.Notifications;
proxy.core = {
/**
* Executes all queued events.
*/
deviceready: function () {
var plugin = cordova.plugins.notification.local,
events = this.eventQueue;
this.isReady = true;
for (var i = 0; i < events.length; i++) {
plugin.fireEvent.apply(plugin, events[i]);
}
this.eventQueue = [];
},
/**
* Schedules new local notifications.
*
* @param {Object[]} notifications
* Array of local notifications
* @param {String} event
* 'schedule' or 'update'
*/
schedule: function (notifications) {
var triggerFn = function (notification) {
this.updateBadge(notification.badge);
this.fireEvent('trigger', notification);
};
for (var i = 0; i < notifications.length; i++) {
var options = notifications[i],
notification = this.build(options);
this.cancelLocalNotification(options.id);
this.scheduleLocalNotification(notification, options);
this.scheduleBackupNotification(notification, options);
this.fireEvent('schedule', options);
this.callOnTrigger(options, triggerFn);
}
},
/**
* Schedules a single local notification.
*
* @param {Windows.Data.Xml.Dom.XmlDocument} notification
* The local notification
* @param {Object} options
* Local notification properties
*/
scheduleLocalNotification: function (notification, options) {
var interval = this.getRepeatInterval(options.every),
triggerTime = new Date((options.at * 1000)),
now = new Date().getTime(),
toast;
if (triggerTime <= now) {
triggerTime = new Date(now + 10);
}
try {
if (interval !== 0 && interval < 360001 && interval > 59999) {
toast = new Notifications.ScheduledToastNotification(
notification, triggerTime, interval, 5);
} else {
toast = new Notifications.ScheduledToastNotification(
notification, triggerTime);
}
} catch (e) {
console.error(e);
return;
}
toast.id = options.id;
toast.tag = 'Toast' + toast.id;
this.getToastNotifier().addToSchedule(toast);
},
/**
* Schedules a backup local notification 10 years later.
*
* @param {Object} notification
* The local notification
*/
scheduleBackupNotification: function (notification, options) {
var properties = Object.create(options);
properties.id = options.id + '-2';
properties.at = options.at + 315360000; // 10 years later
this.scheduleLocalNotification(notification, properties);
},
/**
* Updates the badge number of the active tile.
*
* @param {Number} badge
* The badge number. Zero will clean the badge.
*/
updateBadge: function (badge) {
var notifications = Windows.UI.Notifications,
type = notifications.BadgeTemplateType.badgeNumber,
xml = notifications.BadgeUpdateManager.getTemplateContent(type),
attrs = xml.getElementsByTagName('badge'),
notification = new notifications.BadgeNotification(xml);
attrs[0].setAttribute('value', badge);
notifications.BadgeUpdateManager.createBadgeUpdaterForApplication()
.update(notification);
},
/**
* Updates existing notifications specified by IDs in options.
*
* @param {Object[]} notifications
* Array of local notifications
*/
update: function (notifications) {
for (var i = 0; i < notifications.length; i++) {
var updates = notifications[i],
options = getAll(updates.id || '0')[0];
this.updateLocalNotification(options, updates);
this.fireEvent('update', options);
}
},
/**
* Updates a single local notification.
*
* @param {Object} notification
* The local notification
* @param {Object} updates
* Updated properties
*/
updateLocalNotification: function (notification, updates) {
for (var key in updates) {
notification[key] = updates[key];
}
this.cancelLocalNotification(notification.id);
this.scheduleLocalNotification(notification);
},
/**
* Clears the specified notifications.
*
* @param {int[]} ids
* List of local notification IDs
*/
clear: function (ids) {
for (var i = 0; i < ids.length; i++) {
var id = ids[i],
notification = this.getAll([id])[0];
this.clearLocalNotification(id);
this.fireEvent('clear', notification);
}
},
/**
* Clears the local notification with the given ID.
*
* @param {String} id
* Local notification ID
*/
clearLocalNotification: function (id) {
var notification = this.getAll([id])[0];
try {
this.getToastHistory().remove('Toast' + id);
} catch (e) {/*Only Phones support the NotificationHistory*/ }
if (this.isRepeating(notification))
return;
if (this.isTriggered(id) && !this.isScheduled(id)) {
this.cancelLocalNotification(id);
}
},
/**
* Clears all notifications.
*/
clearAll: function () {
var ids = this.getTriggeredIds();
for (var i = 0; i < ids.length; i++) {
this.clearLocalNotification(ids[i]);
}
try {
this.getToastHistory().clear();
} catch (e) {/*Only Phones support the NotificationHistory*/ }
this.fireEvent('clearall');
},
/**
* Cancels all specified notifications.
*
* @param {int[]} ids
* List of local notification IDs
*/
cancel: function (ids) {
for (var i = 0; i < ids.length; i++) {
var id = ids[i],
notification = this.getAll([id])[0];
this.cancelLocalNotification(ids[i]);
this.fireEvent('cancel', notification);
}
},
/**
* Cancels the local notification with the given ID.
*
* @param {String} id
* Local notification ID
*/
cancelLocalNotification: function (id) {
var notifier = this.getToastNotifier(),
history = this.getToastHistory(),
toasts = this.getScheduledToasts();
try {
history.remove('Toast' + id);
} catch (e) {/*Only Phones support the NotificationHistory*/ }
for (var i = 0; i < toasts.length; i++) {
var toast = toasts[i];
if (toast.id == id || toast.id == id + '-2') {
notifier.removeFromSchedule(toast);
}
}
},
/**
* Cancels all notifications.
*/
cancelAll: function () {
var ids = this.getAllIds();
for (var i = 0; i < ids.length; i++) {
this.cancelLocalNotification(ids[i]);
}
try {
this.getToastHistory().clear();
} catch (e) {/*Only Phones support the NotificationHistory*/ }
this.fireEvent('cancelall');
},
/**
* Checks if a notification with an ID is present.
*
* @param {int} id
* Local notification ID
*/
isPresent: function (id) {
return !!this.findToastById(id);
},
/**
* Checks if a notification with an ID was scheduled.
*
* @param {int} id
* Local notification ID
*/
isScheduled: function (id) {
var toast = this.findToastById(id);
return toast && this.isToastScheduled(toast);
},
/**
* Checks if a notification with an ID was triggered.
*
* @param {int} id
* Local notification ID
*/
isTriggered: function (id) {
var toast = this.findToastById(id);
return toast && this.isToastTriggered(toast);
},
/**
* Lists all local notification IDs.
*/
getAllIds: function () {
var toasts = this.getScheduledToasts(),
ids = [];
for (var i = 0; i < toasts.length; i++) {
var toast = toasts[i],
toastId = this.getToastId(toast);
if (ids.indexOf(toastId) == -1) {
ids.push(toastId);
}
}
return ids;
},
/**
* Lists all scheduled notification IDs.
*/
getScheduledIds: function () {
var toasts = this.getScheduledToasts(),
ids = [];
for (var i = 0; i < toasts.length; i++) {
var toast = toasts[i];
if (!this.isToastScheduled(toast))
continue;
ids.push(this.getToastId(toast));
}
return ids;
},
/**
* Lists all scheduled notification IDs.
*/
getTriggeredIds: function () {
var toasts = this.getScheduledToasts(),
ids = [];
for (var i = 0; i < toasts.length; i++) {
var toast = toasts[i];
if (!this.isToastTriggered(toast))
continue;
ids.push(this.getToastId(toast));
}
return ids;
},
/**
* Property list for given notifications.
* If called without IDs, all notification will be returned.
*
* @param {int[]} ids
* List of local notification IDs.
* @param {String?} type
* Local notification life cycle type
*/
getAll: function (ids, type) {
var toasts = this.getScheduledToasts(),
notifications = [];
if (!ids || ids.length === 0) {
ids = this.getAllIds();
}
for (var index = 0; index < ids.length; index++) {
var id = ids[index],
toast = this.findToastById(id);
if (!toast || type && this.getToastType(toast) != type)
continue;
var json = toast.content.lastChild.lastChild.innerText;
notifications.push(JSON.parse(json));
}
return notifications;
},
/**
* Property list for given notifications.
* If called without IDs, all notification will be returned.
*
* @param {int[]} ids
* List of local notification IDs
*/
getScheduled: function (ids) {
if (!ids || ids.length === 0) {
ids = this.getAllIds();
}
return this.getAll(ids, 'scheduled');
},
/**
* Property list for given notifications.
* If called without IDs, all notification will be returned.
*
* @param {int[]} ids
* List of local notification IDs
*/
getTriggered: function (ids) {
if (!ids || ids.length === 0) {
ids = this.getAllIds();
}
return this.getAll(ids, 'triggered');
},
};
/*
Copyright 2013-2015 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
/**
* Executes all queued events.
*/
exports.deviceready = function () {
exports.core.deviceready();
};
/**
* Schedule a new local notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {Object[]} notifications
* Array of local notifications
*/
exports.schedule = function (success, error, notifications) {
exports.core.schedule(notifications, 'schedule');
success();
};
/**
* Update existing notifications specified by IDs in options.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {Object[]} notifications
* Array of local notifications
*/
exports.update = function (success, error, notifications) {
exports.core.update(notifications);
success();
};
/**
* Clear the specified notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.clear = function (success, error, ids) {
exports.core.clear(ids, true);
success();
};
/**
* Clear all previously sheduled notifications.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.clearAll = function (success, error) {
exports.core.clearAll();
success();
};
/**
* Cancel the specified notifications.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.cancel = function (success, error, ids) {
exports.core.cancel(ids, true);
success();
};
/**
* Remove all previously registered notifications.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.cancelAll = function (success, error) {
exports.core.cancelAll();
success();
};
/**
* Check if a notification with an ID is present.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int} id
* Local notification ID
*/
exports.isPresent = function (success, error, args) {
var found = exports.core.isPresent(args[0]);
success(found);
};
/**
* Check if a notification with an ID is scheduled.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int} id
* Local notification ID
*/
exports.isScheduled = function (success, error, args) {
var found = exports.core.isScheduled(args[0]);
success(found);
};
/**
* Check if a notification with an ID was triggered.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int} id
* Local notification ID
*/
exports.isTriggered = function (success, error, args) {
var found = exports.core.isTriggered(args[0]);
success(found);
};
/**
* List all local notification IDs.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.getAllIds = function (success, error) {
var ids = exports.core.getAllIds();
success(ids);
};
/**
* List all scheduled notification IDs.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.getScheduledIds = function (success, error) {
var ids = exports.core.getScheduledIds();
success(ids);
};
/**
* List all triggered notification IDs.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
*/
exports.getTriggeredIds = function (success, error) {
var ids = exports.core.getTriggeredIds();
success(ids);
};
/**
* Propertys for given notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getSingle = function (success, error, ids) {
var notification = exports.core.getAll(ids)[0];
success(notification);
};
/**
* Propertys for given scheduled notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getSingleScheduled = function (success, error, ids) {
var notification = exports.core.getScheduled(ids)[0];
success(notification);
};
/**
* Propertys for given triggered notification.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getSingleTriggered = function (success, error, ids) {
var notification = exports.core.getTriggered(ids)[0];
success(notification);
};
/**
* Property list for given notifications.
* If called without IDs, all notification will be returned.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getAll = function (success, error, ids) {
var notifications = exports.core.getAll(ids);
success(notifications);
};
/**
* Property list for given triggered notifications.
* If called without IDs, all notification will be returned.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getScheduled = function (success, error, ids) {
var notifications = exports.core.getScheduled(ids);
success(notifications);
};
/**
* Property list for given triggered notifications.
* If called without IDs, all notification will be returned.
*
* @param {Function} success
* Success callback
* @param {Function} error
* Error callback
* @param {int[]} ids
* List of local notification IDs
*/
exports.getTriggered = function (success, error, ids) {
var notifications = exports.core.getTriggered(ids);
success(notifications);
};
cordova.commandProxy.add('LocalNotification', exports);
/*
Copyright 2013-2015 appPlant UG
Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file
distributed with this work for additional information
regarding copyright ownership. The ASF licenses this file
to you under the Apache License, Version 2.0 (the
"License"); you may not use this file except in compliance
with the License. You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing,
software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
KIND, either express or implied. See the License for the
specific language governing permissions and limitations
under the License.
*/
exports = require('de.appplant.cordova.plugin.local-notification.LocalNotification.Proxy').core;
var channel = require('cordova/channel');
/***********
* MEMBERS *
***********/
// True if App is running, false if suspended
exports.isInBackground = true;
// Indicates if the device is ready (to receive events)
exports.isReady = false;
// Queues all events before deviceready
exports.eventQueue = [];
/********
* UTIL *
********/
/**
* The repeating interval in milliseconds.
*
* @param {String} interval
* A number or a placeholder like `minute`.
*
* @return {Number}
* Interval in milliseconds
*/
exports.getRepeatInterval = function (every) {
if (!every)
return 0;
if (every == 'minute')
return 60000;
if (every == 'hour')
return 360000;
if (!NaN(every))
return parseInt(every) * 60000;
return 0;
};
/**
* If the notification is repeating.
*
* @param {Object} notification
* Local notification object
*
* @return Boolean
*/
exports.isRepeating = function (notification) {
return this.getRepeatInterval(notification.every) !== 0;
};
/**
* Parses sound file path.
*
* @param {String} path
* Relative path to sound resource
*
* @return {String} XML Tag for Sound-File
*/
exports.parseSound = function (path) {
if (!path.match(/^file/))
return '';
var uri = this.parseUri(path),
audio = "<audio src=" + uri + " loop='false'/>";
return audio;
};
/**
* Parses image file path.
*
* @param {String} path
* Relative path to image resource
*
* @return {String} XML-Tag for Image-File
*/
exports.parseImage = function (path) {
if (!path.match(/^file/))
return '';
var uri = this.parseUri(path),
image = "<image id='1' src=" + uri + " />";
return image;
};
/**
* Parses file path to URI.
*
* @param {String} path
* Relative path to a resource
*
* @return {String} URI to File
*/
exports.parseUri = function (path) {
var pkg = Windows.ApplicationModel.Package.current,
pkgId = pkg.id,
pkgName = pkgId.name;
var uri = "'ms-appx://" + pkgName + "/www" + path.slice(6, path.length) + "'";
return uri;
};
/**
* Builds the xml payload for a local notification based on its options.
*
* @param {Object} options
* Local notification properties
*
* @return Windows.Data.Xml.Dom.XmlDocument
*/
exports.build = function (options) {
var template = this.buildToastTemplate(options),
notification = new Windows.Data.Xml.Dom.XmlDocument();
try {
notification.loadXml(template);
} catch (e) {
console.error(
'LocalNotification#schedule',
'Error loading the xml, check for invalid characters.');
}
// Launch Attribute to enable onClick event
var launchAttr = notification.createAttribute('launch'),
toastNode = notification.selectSingleNode('/toast');
launchAttr.value = options.id.toString();
toastNode.attributes.setNamedItem(launchAttr);
return notification;
};
/**
* Builds the toast template with the right style depend on the options.
*
* @param {Object} options
* Local notification properties
*
* @return String
*/
exports.buildToastTemplate = function (options) {
var title = options.title,
message = options.text || '',
json = JSON.stringify(options),
sound = '';
if (options.sound && options.sound !== '') {
sound = this.parseSound(options.sound);
}
var templateName = "ToastText",
imageNode;
if (options.icon && options.icon !== '') {
imageNode = this.parseImage(options.icon);
// template with Image
if (imageNode !== '') {
templateName = "ToastImageAndText";
}
} else {
imageNode = "";
}
var bindingNode;
if (title && title !== '') {
bindingNode = "<binding template='" + templateName + "02'>" +
imageNode +
"<text id='1'>" + title + "</text>" +
"<text id='2'>" + message + "</text>" +
"</binding>";
} else {
bindingNode = "<binding template='" + templateName + "01'>" +
imageNode +
"<text id='1'>" + message + "</text>" +
"</binding>";
}
return "<toast>" +
"<visual>" +
bindingNode +
"</visual>" +
sound +
"<json>" + json + "</json>" +
"</toast>";
};
/**
* Short-hand method for the toast notification history.
*/
exports.getToastHistory = function () {
return Windows.UI.Notifications.ToastNotificationManager.history;
};
/**
* Gets a toast notifier instance.
*
* @return Object
*/
exports.getToastNotifier = function () {
return Windows.UI.Notifications.ToastNotificationManager
.createToastNotifier();
};
/**
* List of all scheduled toast notifiers.
*
* @return Array
*/
exports.getScheduledToasts = function () {
return this.getToastNotifier().getScheduledToastNotifications();
};
/**
* Gets the Id from the toast notifier.
*
* @param {Object} toast
* A toast notifier object
*
* @return String
*/
exports.getToastId = function (toast) {
var id = toast.id;
if (id.match(/-2$/))
return id.match(/^[^-]+/)[0];
return id;
};
/**
* Gets the notification life cycle type
* (scheduled or triggered)
*
* @param {Object} toast
* A toast notifier object
*
* @return String
*/
exports.getToastType = function (toast) {
return this.isToastTriggered(toast) ? 'triggered' : 'scheduled';
};
/**
* If the toast is already scheduled.
*
* @param {Object} toast
* A toast notifier object
*
* @return Boolean
*/
exports.isToastScheduled = function (toast) {
return !this.isToastTriggered(toast);
};
/**
* If the toast is already triggered.
*
* @param {Object} toast
* A toast notifier object
*
* @return Boolean
*/
exports.isToastTriggered = function (toast) {
var id = this.getToastId(toast),
notification = this.getAll([id])[0],
fireDate = new Date((notification.at) * 1000);
if (this.isRepeating(notification))
return false;
return fireDate <= new Date();
};
/**
* Finds the toast by it's ID.
*
* @param {String} id
* Local notification ID
*
* @param Object
*/
exports.findToastById = function (id) {
var toasts = this.getScheduledToasts();
for (var i = 0; i < toasts.length; i++) {
var toast = toasts[i];
if (this.getToastId(toast) == id)
return toast;
}
return null;
};
/**
* Sets trigger event for local notification.
*
* @param {Object} notification
* Local notification object
* @param {Function} callback
* Callback function
*/
exports.callOnTrigger = function (notification, callback) {
var triggerTime = new Date((notification.at * 1000)),
interval = triggerTime - new Date();
if (interval <= 0) {
callback.call(this, notification);
return;
}
WinJS.Promise.timeout(interval).then(function () {
if (exports.isPresent(notification.id)) {
callback.call(exports, notification);
}
});
};
/**
* Sets trigger event for all scheduled local notification.
*
* @param {Function} callback
* Callback function
*/
exports.callOnTriggerForScheduled = function (callback) {
var notifications = this.getScheduled();
for (var i = 0; i < notifications.length; i++) {
this.callOnTrigger(notifications[i], callback);
}
};
/**
* The application state - background or foreground.
*
* @return String
*/
exports.getApplicationState = function () {
return this.isInBackground ? 'background' : 'foreground';
};
/**
* Fires the event about a local notification.
*
* @param {String} event
* The event
* @param {Object} notification
* The notification
*/
exports.fireEvent = function (event, notification) {
var plugin = cordova.plugins.notification.local.core,
state = this.getApplicationState(),
args;
if (notification) {
args = [event, notification, state];
} else {
args = [event, state];
}
if (this.isReady && plugin) {
plugin.fireEvent.apply(plugin, args);
} else {
this.eventQueue.push(args);
}
};
/**************
* LIFE CYCLE *
**************/
// Called before 'deviceready' event
channel.onCordovaReady.subscribe(function () {
// Register trigger handler for each scheduled notification
exports.callOnTriggerForScheduled(function (notification) {
this.updateBadge(notification.badge);
this.fireEvent('trigger', notification);
});
});
// Handle onclick event
document.addEventListener('activated', function (e) {
var id = e.args,
notification = exports.getAll([id])[0];
if (!notification)
return;
exports.clearLocalNotification(id);
var repeating = exports.isRepeating(notification);
exports.fireEvent('click', notification);
exports.fireEvent(repeating ? 'clear' : 'cancel', notification);
}, false);
// App is running in background
document.addEventListener('pause', function () {
exports.isInBackground = true;
}, false);
// App is running in foreground
document.addEventListener('resume', function () {
exports.isInBackground = false;
}, false);
// App is running in foreground
document.addEventListener('deviceready', function () {
exports.isInBackground = false;
}, false);
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
var LocalNotification = LocalNotificationProxy.LocalNotification,
ActivationKind = Windows.ApplicationModel.Activation.ActivationKind;
var impl = new LocalNotificationProxy.LocalNotificationProxy();
/**
* Check permission to show notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.check = function (success, error) {
var granted = impl.hasPermission();
success(granted);
};
/**
* Request permission to show notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.request = function (success, error) {
exports.check(success, error);
};
/**
* Schedule notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.schedule = function (success, error, args) {
var options = [], actions = [];
for (var i = 0, props, opts; i < args.length; i++) {
props = args[i];
opts = new LocalNotification.Options();
for (var prop in opts) {
if (prop != 'actions' && props[prop]) opts[prop] = props[prop];
}
for (var j = 0, action, btn; j < props.actions.length; j++) {
action = props.actions[j];
if (!action.type || action.type == 'button') {
btn = new LocalNotification.Button();
} else
if (action.type == 'input') {
btn = new LocalNotification.Input();
}
for (prop in btn) {
if (action[prop]) btn[prop] = action[prop];
}
actions.push(btn);
}
opts.actions = actions;
options.push(opts);
}
impl.schedule(options);
for (i = 0; i < options.length; i++) {
exports.fireEvent('add', options[i]);
}
success();
};
/**
* Clear the notifications specified by id.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.clear = function (success, error, args) {
var toasts = impl.clear(args) || [];
for (var i = 0; i < toasts.length; i++) {
exports.fireEvent('clear', toasts[i]);
}
success();
};
/**
* Clear all notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.clearAll = function (success, error) {
impl.clearAll();
exports.fireEvent('clearall');
success();
};
/**
* Cancel the notifications specified by id.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.cancel = function (success, error, args) {
var toasts = impl.cancel(args) || [];
for (var i = 0; i < toasts.length; i++) {
exports.fireEvent('cancel', toasts[i]);
}
success();
};
/**
* Cancel all notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.cancelAll = function (success, error) {
impl.cancelAll();
exports.fireEvent('cancelall');
success();
};
/**
* Get the type of notification.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.type = function (success, error, args) {
var type = impl.type(args[0]);
success(type);
};
/**
* List of all notification ids.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.ids = function (success, error) {
var ids = impl.ids() || [];
success(Array.from(ids));
};
/**
* List of all scheduled notification ids.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.scheduledIds = function (success, error) {
var ids = impl.scheduledIds() || [];
success(Array.from(ids));
};
/**
* List of all triggered notification ids.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.triggeredIds = function (success, error) {
var ids = impl.triggeredIds() || [];
success(Array.from(ids));
};
/**
* Get a single notification by id.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.notification = function (success, error, args) {
var obj = impl.notification(args[0]);
success(exports.clone(obj));
};
/**
* List of (all) notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
* @param [ Array ] args Interface arguments
*
* @return [ Void ]
*/
exports.notifications = function (success, error, args) {
var objs = impl.notifications(args) || [];
success(exports.cloneAll(objs));
};
/**
* List of all scheduled notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.scheduledNotifications = function (success, error) {
var objs = impl.scheduledNotifications() || [];
success(exports.cloneAll(objs));
};
/**
* List of all triggered notifications.
*
* @param [ Function ] success Success callback
* @param [ Function ] error Error callback
*
* @return [ Void ]
*/
exports.triggeredNotifications = function (success, error) {
var objs = impl.triggeredNotifications() || [];
success(exports.cloneAll(objs));
};
/**
* Inform the user through the click event that a notification was clicked.
*
* @param [ String ] xml The launch identifier.
*
* @return [ Void ]
*/
exports.clicked = function (xml, input) {
var toast = LocalNotification.Options.parse(xml),
event = toast.action || 'click',
meta = Object.assign({}, input);
if (input && input.size > 0) {
meta.text = input.first().current.value;
}
exports.fireEvent(event, toast, meta);
};
/**
* Invoke listeners for the given event.
*
* @param [ String ] event The name of the event.
* @param [ Object ] toast Optional notification object.
* @param [ Object ] data Optional meta data about the event.
*
* @return [ Void ]
*/
exports.fireEvent = function (event, toast, data) {
var meta = Object.assign({ event: event }, data),
plugin = cordova.plugins.notification.local.core;
if (toast) {
plugin.fireEvent(event, exports.clone(toast), meta);
} else {
plugin.fireEvent(event, meta);
}
};
/**
* Clone the objects and delete internal properties.
*
* @param [ Array<Object> ] objs The objects to clone for.
*
* @return [ Array<Object> ]
*/
exports.cloneAll = function (objs) {
var clones = [];
for (var i = 0; i < objs.length; i++) {
clones.push(exports.clone(objs[i]));
}
return clones;
};
/**
* Clone the object and delete internal properties.
*
* @param [ Object ] obj The object to clone for.
*
* @return [ Object ]
*/
exports.clone = function (obj) {
var ignore = ['action'],
clone = {};
for (var prop in obj) {
if (ignore.includes(prop) || typeof obj[prop] === 'function')
continue;
try {
clone[prop] = obj[prop];
} catch (e) {
clone[prop] = null;
}
}
return clone;
};
// Handle onclick event
document.addEventListener('activated', function (e) {
if (e.kind == ActivationKind.toastNotification) {
exports.clicked(e.raw.argument, e.raw.userInput);
}
}, false);
cordova.commandProxy.add('LocalNotification', exports);

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.26430.14
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalNotificationProxy", "LocalNotificationProxy\LocalNotificationProxy.csproj", "{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Debug|ARM = Debug|ARM
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|Any CPU = Release|Any CPU
Release|ARM = Release|ARM
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.ActiveCfg = Debug|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.Build.0 = Debug|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.ActiveCfg = Debug|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.Build.0 = Debug|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.ActiveCfg = Debug|x86
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.Build.0 = Debug|x86
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.Build.0 = Release|Any CPU
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.ActiveCfg = Release|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.Build.0 = Release|ARM
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.ActiveCfg = Release|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.Build.0 = Release|x64
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.ActiveCfg = Release|x86
{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.Build.0 = Release|x86
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
using Microsoft.Toolkit.Uwp.Notifications;
using Windows.UI.Notifications;
internal class Builder
{
/// <summary>
/// Initializes a new instance of the <see cref="Builder"/> class.
/// </summary>
/// <param name="options">Notification properties to set.</param>
internal Builder(Options options)
{
this.Content = new Notification(options);
}
/// <summary>
/// Gets content
/// </summary>
public Notification Content { get; private set; }
/// <summary>
/// Gets options
/// </summary>
private Options Options { get => this.Content.Options; }
/// <summary>
/// Build a toast notification specified by the options.
/// </summary>
/// <returns>A fully configured toast notification instance.</returns>
public ScheduledToastNotification Build()
{
var toast = this.InitToast();
this.AddAttachmentsToToast(toast);
this.AddActionsToToast(toast);
return this.ConvertToastToNotification(toast);
}
/// <summary>
/// Gets the initialize skeleton for a toast notification.
/// </summary>
/// <returns>Basic skeleton with sound, image and text.</returns>
private ToastContent InitToast()
{
return new ToastContent()
{
Launch = this.Content.GetXml(),
Audio = this.Content.Sound,
Visual = new ToastVisual()
{
BindingGeneric = new ToastBindingGeneric()
{
Children =
{
new AdaptiveText()
{
Text = this.Options.Title
},
new AdaptiveText()
{
Text = this.Options.Text
}
},
AppLogoOverride = this.Content.Image
}
},
Actions = new ToastActionsCustom()
{
Buttons = { },
Inputs = { }
}
};
}
/// <summary>
/// Adds attachments to the toast.
/// </summary>
/// <param name="toast">Tho toast to extend for.</param>
private void AddAttachmentsToToast(ToastContent toast)
{
foreach (var image in this.Content.Attachments)
{
toast.Visual.BindingGeneric.Children.Add(image);
}
}
/// <summary>
/// Adds buttons and input fields to the toast.
/// </summary>
/// <param name="toast">Tho toast to extend for.</param>
private void AddActionsToToast(ToastContent toast)
{
foreach (var btn in this.Content.Inputs)
{
(toast.Actions as ToastActionsCustom).Inputs.Add(btn);
}
foreach (var btn in this.Content.Buttons)
{
(toast.Actions as ToastActionsCustom).Buttons.Add(btn);
}
}
/// <summary>
/// Converts the toast into a notification.
/// </summary>
/// <param name="toast">The toast to convert.</param>
/// <returns>A notification ready to schedule.</returns>
private ScheduledToastNotification ConvertToastToNotification(ToastContent toast)
{
var xml = toast.GetXml();
var at = this.Content.Date;
ScheduledToastNotification notification;
if (this.Content.IsRepeating())
{
var interval = this.Content.Interval;
notification = new ScheduledToastNotification(xml, at, interval, 5);
}
else
{
notification = new ScheduledToastNotification(xml, at);
}
notification.Id = this.Options.ID.ToString();
notification.Tag = notification.Id;
return notification;
}
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public sealed class Button : IAction
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
public string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to launch the app.
/// </summary>
public bool Launch { get; set; } = true;
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public interface IAction
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
string Title { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to launch the app.
/// </summary>
bool Launch { get; set; }
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
public sealed class Input : IAction
{
/// <summary>
/// Gets or sets the ID.
/// </summary>
public string ID { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets the title of the submit button.
/// </summary>
public string SubmitTitle { get; set; }
/// <summary>
/// Gets or sets placeholder text.
/// </summary>
public string EmptyText { get; set; }
/// <summary>
/// Gets or sets the default text.
/// </summary>
public string DefaultValue { get; set; }
/// <summary>
/// Gets or sets a value indicating whether to launch the app.
/// </summary>
public bool Launch { get; set; } = true;
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
using System.Collections.Generic;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.UI.Notifications;
internal class Manager
{
/// <summary>
/// Gets a value indicating whether the permission to schedule notifications is enabled.
/// </summary>
/// <returns>True if settings are enabled</returns>
public bool Enabled => ToastNotifier.Setting == NotificationSetting.Enabled;
/// <summary>
/// Gets the default toast notifier.
/// </summary>
internal static ToastNotifier ToastNotifier => ToastNotificationManager.CreateToastNotifier();
/// <summary>
/// Schedule notifications.
/// </summary>
/// <param name="notifications">List of key-value properties</param>
public void Schedule([ReadOnlyArray] Options[] notifications)
{
foreach (Options options in notifications)
{
var toast = new Builder(options).Build();
ToastNotifier.AddToSchedule(toast);
}
}
/// <summary>
/// Clear the notifications specified by id.
/// </summary>
/// <param name="ids">The IDs of the notification to clear.</param>
/// <returns>The cleared notifications.</returns>
public List<Options> Clear(int[] ids)
{
var triggered = ToastNotificationManager.History.GetHistory();
var tags = new List<int>(ids);
var toasts = new List<Options>();
foreach (var toast in triggered)
{
var id = int.Parse(toast.Tag);
if (tags.Contains(id))
{
tags.Remove(id);
toasts.Add(new Notification(toast).Options);
ToastNotificationManager.History.Remove(toast.Tag);
}
if (tags.Count == 0)
{
break;
}
}
return toasts;
}
/// <summary>
/// Clear all notifications.
/// </summary>
public void ClearAll()
{
ToastNotificationManager.History.Clear();
}
/// <summary>
/// Cancel the notifications specified by id.
/// </summary>
/// <param name="ids">The IDs of the notification to clear.</param>
/// <returns>The cleared notifications.</returns>
public List<Options> Cancel(int[] ids)
{
var scheduled = ToastNotifier.GetScheduledToastNotifications();
var tags = new List<int>(ids);
var toasts = new List<Options>();
foreach (var toast in scheduled)
{
var id = int.Parse(toast.Tag);
if (tags.Contains(id))
{
tags.Remove(id);
toasts.Add(new Notification(toast).Options);
ToastNotifier.RemoveFromSchedule(toast);
}
if (tags.Count == 0)
{
break;
}
}
if (tags.Count > 0)
{
toasts.AddRange(this.Clear(tags.ToArray()));
}
return toasts;
}
/// <summary>
/// Cancel all notifications.
/// </summary>
public void CancelAll()
{
var toasts = ToastNotifier.GetScheduledToastNotifications();
foreach (var toast in toasts)
{
ToastNotifier.RemoveFromSchedule(toast);
}
this.ClearAll();
}
/// <summary>
/// Gets all notifications by id.
/// </summary>
/// <returns>List of ids</returns>
public List<int> GetIds()
{
return this.GetIdsByType(Notification.Type.All);
}
/// <summary>
/// Gets all notifications by id for given type.
/// </summary>
/// <param name="type">The type of notification.</param>
/// <returns>List of ids</returns>
public List<int> GetIdsByType(Notification.Type type)
{
var ids = new List<int>();
if (type == Notification.Type.All || type == Notification.Type.Scheduled)
{
var toasts = ToastNotifier.GetScheduledToastNotifications();
foreach (var toast in toasts)
{
ids.Add(int.Parse(toast.Tag));
}
}
if (type == Notification.Type.All || type == Notification.Type.Triggered)
{
var toasts = ToastNotificationManager.History.GetHistory();
foreach (var toast in toasts)
{
ids.Add(int.Parse(toast.Tag));
}
}
return ids;
}
/// <summary>
/// Gets all notifications.
/// </summary>
/// <returns>A list of all triggered and scheduled notifications.</returns>
public List<Notification> GetAll()
{
return this.GetByType(Notification.Type.All);
}
/// <summary>
/// Gets all notifications of given type.
/// </summary>
/// <param name="type">The type of notification.</param>
/// <returns>A list of notifications.</returns>
public List<Notification> GetByType(Notification.Type type)
{
var notifications = new List<Notification>();
if (type == Notification.Type.All || type == Notification.Type.Scheduled)
{
var toasts = ToastNotifier.GetScheduledToastNotifications();
foreach (var toast in toasts)
{
notifications.Add(new Notification(toast));
}
}
if (type == Notification.Type.All || type == Notification.Type.Triggered)
{
var toasts = ToastNotificationManager.History.GetHistory();
foreach (var toast in toasts)
{
notifications.Add(new Notification(toast));
}
}
return notifications;
}
/// <summary>
/// Gets all notifications.
/// </summary>
/// <returns>A list of notification options instances.</returns>
public List<Options> GetOptions()
{
return this.GetOptionsByType(Notification.Type.All);
}
/// <summary>
/// Gets notifications specified by ID.
/// </summary>
/// <param name="ids">Optional list of IDs to find.</param>
/// <returns>A list of notification options instances.</returns>
public List<Options> GetOptions(int[] ids)
{
var options = new List<Options>();
foreach (var toast in this.Get(ids))
{
options.Add(toast.Options);
}
return options;
}
/// <summary>
/// Gets all notifications for given type.
/// </summary>
/// <param name="type">The type of notification.</param>
/// <returns>A list of notification options instances.</returns>
public List<Options> GetOptionsByType(Notification.Type type)
{
var options = new List<Options>();
var toasts = this.GetByType(type);
foreach (var toast in toasts)
{
options.Add(toast.Options);
}
return options;
}
/// <summary>
/// Gets the notifications specified by ID.
/// </summary>
/// <param name="ids">List of IDs to find.</param>
/// <returns>List of found notifications.</returns>
public List<Notification> Get(int[] ids)
{
var toasts = new List<Notification>();
foreach (var id in ids)
{
var toast = this.Get(id);
if (toast != null)
{
toasts.Add(toast);
}
}
return toasts;
}
/// <summary>
/// Gets the notification by ID.
/// </summary>
/// <param name="id">The ID of the notification to find.</param>
/// <returns>The found instance or null.</returns>
public Notification Get(int id)
{
return this.Get(id.ToString());
}
/// <summary>
/// Gets the notification by ID.
/// </summary>
/// <param name="id">The ID of the notification to find.</param>
/// <returns>The found instance or null.</returns>
public Notification Get(string id)
{
var scheduled = ToastNotifier.GetScheduledToastNotifications();
foreach (var toast in scheduled)
{
if (toast.Tag == id)
{
return new Notification(toast);
}
}
var triggered = ToastNotificationManager.History.GetHistory();
foreach (var toast in triggered)
{
if (toast.Tag == id)
{
return new Notification(toast);
}
}
return null;
}
/// <summary>
/// Gets the type (scheduled, triggered or unknown).
/// </summary>
/// <param name="id">The ID of the notification to find for.</param>
/// <returns>The type of the notification or unknown type.</returns>
public Notification.Type GetType(string id)
{
var scheduled = ToastNotifier.GetScheduledToastNotifications();
foreach (var toast in scheduled)
{
if (toast.Tag == id)
{
return Notification.Type.Scheduled;
}
}
var triggered = ToastNotificationManager.History.GetHistory();
foreach (var toast in triggered)
{
if (toast.Tag == id)
{
return Notification.Type.Triggered;
}
}
return Notification.Type.Unknown;
}
}
}
namespace LocalNotificationProxy.LocalNotification
{
using System;
using System.Collections.Generic;
using Microsoft.Toolkit.Uwp.Notifications;
using Windows.UI.Notifications;
internal class Notification
{
/// <summary>
/// Initializes a new instance of the <see cref="Notification"/> class.
/// </summary>
/// <param name="options">The options hash map from JS side.</param>
public Notification(Options options)
{
this.Options = options;
}
/// <summary>
/// Initializes a new instance of the <see cref="Notification"/> class.
/// </summary>
/// <param name="xml">The options as a xml string.</param>
public Notification(string xml)
{
this.Options = Options.Parse(xml);
}
/// <summary>
/// Initializes a new instance of the <see cref="Notification"/> class.
/// </summary>
/// <param name="toast">The options as a toast object.</param>
public Notification(ScheduledToastNotification toast)
{
this.Options = Options.Parse(toast.Content.GetXml());
}
/// <summary>
/// Initializes a new instance of the <see cref="Notification"/> class.
/// </summary>
/// <param name="toast">The options as a toast object.</param>
public Notification(ToastNotification toast)
{
var xml = toast.Content.DocumentElement.GetAttribute("launch");
this.Options = Options.Parse(xml);
}
public enum Type
{
All, Scheduled, Triggered, Unknown
}
public Options Options { get; private set; }
/// <summary>
/// Gets a ToastAudio object based on the specified sound uri.
/// </summary>
public ToastAudio Sound
{
get
{
var sound = new ToastAudio();
var path = this.Options.Sound;
if (path == null || path.Length == 0 || path.Equals("false"))
{
sound.Silent = true;
}
else
if (path.StartsWith("file:///") || path.StartsWith("http"))
{
sound.Src = new Uri(path, UriKind.Absolute);
}
else
if (path.StartsWith("file://"))
{
sound.Src = new Uri(path.Replace("file:/", "ms-appx:///www"));
}
else
if (path.StartsWith("res://"))
{
sound.Src = new Uri(path.Replace("res://", "ms-winsoundevent:notification."));
}
else
if (path.StartsWith("app://"))
{
sound.Src = new Uri(path.Replace("app:/", "ms-appdata://"));
}
return sound;
}
}
/// <summary>
/// Gets a GenericAppLogo object based on the specified icon uri.
/// </summary>
public ToastGenericAppLogo Image
{
get
{
var image = new ToastGenericAppLogo();
var path = this.Options.Image;
if (path == null || path.StartsWith("res://logo"))
{
image.Source = string.Empty;
}
else
if (path.StartsWith("file:///") || path.StartsWith("http"))
{
image.Source = path;
}
else
if (path.StartsWith("file://"))
{
image.Source = path.Replace("file:/", "ms-appx:///www");
}
else
if (path.StartsWith("res://"))
{
image.Source = path.Replace("res://", "ms-appx:///images");
}
else
if (path.StartsWith("app://"))
{
image.Source = path.Replace("app:/", "ms-appdata://local");
}
else
{
image.Source = string.Empty;
}
if (image.Source.EndsWith("?crop=none"))
{
image.HintCrop = ToastGenericAppLogoCrop.None;
}
else
if (image.Source.EndsWith("?crop=cirlce"))
{
image.HintCrop = ToastGenericAppLogoCrop.Circle;
}
return image;
}
}
/// <summary>
/// Gets the parsed image attachments.
/// </summary>
public List<AdaptiveImage> Attachments
{
get
{
var images = new List<AdaptiveImage>();
if (this.Options.Attachments == null)
{
return images;
}
foreach (string path in this.Options.Attachments)
{
var image = new AdaptiveImage();
if (path.StartsWith("file:///") || path.StartsWith("http"))
{
image.Source = path;
}
else
if (path.StartsWith("file://"))
{
image.Source = path.Replace("file:/", "ms-appx:///www");
}
else
if (path.StartsWith("res://"))
{
image.Source = path.Replace("res://", "ms-appx:///images");
}
else
if (path.StartsWith("app://"))
{
image.Source = path.Replace("app:/", "ms-appdata://local");
}
if (image.Source != null)
{
images.Add(image);
}
}
return images;
}
}
/// <summary>
/// Gets all toast buttons.
/// </summary>
public List<ToastButton> Buttons
{
get
{
var buttons = new List<ToastButton>();
foreach (var action in this.Options.Actions)
{
if (action is Button)
{
buttons.Add(new ToastButton(action.Title, this.Options.GetXml(action.ID))
{
ActivationType = action.Launch ? ToastActivationType.Foreground : ToastActivationType.Background
});
}
else if (action is Input && (action as Input).SubmitTitle != null)
{
var input = action as Input;
buttons.Add(new ToastButton(input.SubmitTitle, this.Options.GetXml(input.ID))
{
ActivationType = input.Launch ? ToastActivationType.Foreground : ToastActivationType.Background,
TextBoxId = input.ID
});
}
}
return buttons;
}
}
/// <summary>
/// Gets all toast inputs.
/// </summary>
public List<ToastTextBox> Inputs
{
get
{
var inputs = new List<ToastTextBox>();
foreach (var action in this.Options.Actions)
{
if (!(action is Input))
{
continue;
}
inputs.Add(new ToastTextBox(action.ID)
{
Title = action.Title,
PlaceholderContent = (action as Input).EmptyText,
DefaultInput = (action as Input).DefaultValue
});
}
return inputs;
}
}
/// <summary>
/// Gets the date when to trigger the notification.
/// </summary>
public DateTime Date
{
get
{
var date = DateTimeOffset.FromUnixTimeMilliseconds(this.Options.At * 1000).LocalDateTime;
var minDate = DateTime.Now.AddSeconds(0.1);
return (date < minDate) ? minDate : date;
}
}
/// <summary>
/// Gets the parsed repeat interval.
/// </summary>
public TimeSpan Interval
{
get
{
switch (this.Options.Every)
{
case "minute":
return new TimeSpan(TimeSpan.TicksPerMinute);
case "hour":
return new TimeSpan(TimeSpan.TicksPerHour);
case "day":
return new TimeSpan(TimeSpan.TicksPerDay);
default:
return TimeSpan.Zero;
}
}
}
/// <summary>
/// Gets the instance as an serialized xml element.
/// </summary>
/// <returns>Element with all property values set as attributes.</returns>
public string GetXml()
{
return this.Options.GetXml();
}
/// <summary>
/// If the notification shall be repeating.
/// </summary>
/// <returns>True if the Every property has some value.</returns>
public bool IsRepeating()
{
var every = this.Options.Every;
return every != null && every.Length > 0 && !every.Equals("0");
}
}
}
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy.LocalNotification
{
using Windows.Data.Xml.Dom;
public sealed class Options
{
/// <summary>
/// Gets notification event.
/// </summary>
public string Action { get; private set; } = "click";
/// <summary>
/// Gets or sets notification ID.
/// </summary>
public int ID { get; set; }
/// <summary>
/// Gets or sets notification title.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Gets or sets notification text.
/// </summary>
public string Text { get; set; }
/// <summary>
/// Gets or sets app badge number.
/// </summary>
public int Badge { get; set; }
/// <summary>
/// Gets or sets the notification sound.
/// </summary>
public string Sound { get; set; }
/// <summary>
/// Gets or sets the notification image.
/// </summary>
public string Image { get; set; }
/// <summary>
/// Gets or sets the notification fire date.
/// </summary>
public long At { get; set; }
/// <summary>
/// Gets or sets the notification repeat interval.
/// </summary>
public string Every { get; set; }
/// <summary>
/// Gets or sets the notification user data.
/// </summary>
public string Data { get; set; }
/// <summary>
/// Gets or sets the notification attachments.
/// </summary>
public string[] Attachments { get; set; }
/// <summary>
/// Gets or sets the notification actions.
/// </summary>
public IAction[] Actions { get; set; }
/// <summary>
/// Deserializes the XML string into an instance of Options.
/// </summary>
/// <param name="identifier">The serialized instance of Options as an xml string.</param>
/// <returns>An instance where all properties have been assigned.</returns>
public static Options Parse(string identifier)
{
var doc = new XmlDocument();
doc.LoadXml(identifier);
var options = new Options();
var node = doc.DocumentElement;
options.ID = int.Parse(node.GetAttribute("id"));
options.Badge = int.Parse(node.GetAttribute("badge"));
options.At = int.Parse(node.GetAttribute("at"));
if (node.GetAttributeNode("text") != null)
{
options.Text = node.GetAttribute("text");
}
if (node.GetAttributeNode("title") != null)
{
options.Title = node.GetAttribute("title");
}
if (node.GetAttributeNode("sound") != null)
{
options.Sound = node.GetAttribute("sound");
}
if (node.GetAttributeNode("image") != null)
{
options.Image = node.GetAttribute("image");
}
if (node.GetAttributeNode("every") != null)
{
options.Every = node.GetAttribute("every");
}
if (node.GetAttributeNode("data") != null)
{
options.Data = node.GetAttribute("data");
}
if (node.GetAttributeNode("action") != null)
{
options.Action = node.GetAttribute("action");
}
return options;
}
/// <summary>
/// Gets the instance as an serialized xml element.
/// </summary>
/// <returns>Element with all property values set as attributes.</returns>
public string GetXml()
{
return this.GetXml(null);
}
/// <summary>
/// Gets the instance as an serialized xml element.
/// </summary>
/// <param name="action">Optional (internal) event name.</param>
/// <returns>Element with all property values set as attributes.</returns>
internal string GetXml(string action)
{
var node = new XmlDocument().CreateElement("options");
node.SetAttribute("id", this.ID.ToString());
node.SetAttribute("badge", this.Badge.ToString());
node.SetAttribute("at", this.At.ToString());
if (this.Title != null)
{
node.SetAttribute("title", this.Title);
}
if (this.Text != null)
{
node.SetAttribute("text", this.Text);
}
if (this.Sound != null)
{
node.SetAttribute("sound", this.Sound);
}
if (this.Image != null)
{
node.SetAttribute("image", this.Image);
}
if (this.Every != null)
{
node.SetAttribute("every", this.Every);
}
if (this.Data != null)
{
node.SetAttribute("data", this.Data);
}
if (action != null)
{
node.SetAttribute("action", action);
}
return node.GetXml();
}
}
}
\ No newline at end of file
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
namespace LocalNotificationProxy
{
using System.Runtime.InteropServices.WindowsRuntime;
using LocalNotification;
public sealed class LocalNotificationProxy
{
/// <summary>
/// Manager wrapps the native SDK methods.
/// </summary>
private Manager manager = new Manager();
/// <summary>
/// Check permission to schedule notifications.
/// </summary>
/// <returns>True if settings are enabled</returns>
public bool HasPermission()
{
return this.manager.Enabled;
}
/// <summary>
/// Schedule notifications.
/// </summary>
/// <param name="notifications">List of key-value properties</param>
public void Schedule([ReadOnlyArray] Options[] notifications)
{
this.manager.Schedule(notifications);
}
/// <summary>
/// Clear the notifications specified by id.
/// </summary>
/// <param name="ids">The IDs of the notification to clear.</param>
/// <returns>The cleared notifications.</returns>
public Options[] Clear([ReadOnlyArray] int[] ids)
{
return this.manager.Clear(ids).ToArray();
}
/// <summary>
/// Clear all notifications.
/// </summary>
public void ClearAll()
{
this.manager.ClearAll();
}
/// <summary>
/// Cancel the notifications specified by id.
/// </summary>
/// <param name="ids">The IDs of the notification to clear.</param>
/// <returns>The cleared notifications.</returns>
public Options[] Cancel([ReadOnlyArray] int[] ids)
{
return this.manager.Cancel(ids).ToArray();
}
/// <summary>
/// Cancel all notifications.
/// </summary>
public void CancelAll()
{
this.manager.CancelAll();
}
/// <summary>
/// Gets the type of the notification specified by ID.
/// </summary>
/// <param name="id">The ID of the notification to find for.</param>
/// <returns>The type (scheduled, triggered or unknown).</returns>
public string Type(int id)
{
return this.manager.GetType(id.ToString()).ToString().ToLower();
}
/// <summary>
/// List of all notifiation by id.
/// </summary>
/// <returns>List of numbers</returns>
public int[] Ids()
{
return this.manager.GetIds().ToArray();
}
/// <summary>
/// List of all scheduled notifiation by id.
/// </summary>
/// <returns>List of numbers</returns>
public int[] ScheduledIds()
{
return this.manager.GetIdsByType(Notification.Type.Scheduled).ToArray();
}
/// <summary>
/// List of all triggered notifiation by id.
/// </summary>
/// <returns>List of numbers</returns>
public int[] TriggeredIds()
{
return this.manager.GetIdsByType(Notification.Type.Triggered).ToArray();
}
#pragma warning disable SA1300 // Element must begin with upper-case letter
/// <summary>
/// Gets a single notifiation specified by id.
/// </summary>
/// <param name="id">The ID of the notification to find.</param>
/// <returns>List of options instances</returns>
public Options notification(int id)
{
var toast = this.manager.Get(id);
return toast != null ? toast.Options : null;
}
#pragma warning restore SA1300 // Element must begin with upper-case letter
/// <summary>
/// List of (all) notifiation specified by id.
/// </summary>
/// <param name="ids">Optional list of IDs to find.</param>
/// <returns>List of options instances</returns>
public Options[] Notifications([ReadOnlyArray] int[] ids)
{
if (ids == null || ids.Length == 0)
{
return this.manager.GetOptions().ToArray();
}
return this.manager.GetOptions(ids).ToArray();
}
/// <summary>
/// List of all scheduled notifiation.
/// </summary>
/// <returns>List of options instances</returns>
public Options[] ScheduledNotifications()
{
return this.manager.GetOptionsByType(Notification.Type.Scheduled).ToArray();
}
/// <summary>
/// List of all triggered notifiation.
/// </summary>
/// <returns>List of options instances</returns>
public Options[] TriggeredNotifications()
{
return this.manager.GetOptionsByType(Notification.Type.Triggered).ToArray();
}
}
}
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}</ProjectGuid>
<OutputType>winmdobj</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>LocalNotificationProxy</RootNamespace>
<AssemblyName>LocalNotificationProxy</AssemblyName>
<DefaultLanguage>de-DE</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion Condition=" '$(TargetPlatformVersion)' == '' ">10.0.15063.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.15063.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<AllowCrossPlatformRetargeting>false</AllowCrossPlatformRetargeting>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x86'">
<PlatformTarget>x86</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x86\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x86'">
<PlatformTarget>x86</PlatformTarget>
<OutputPath>bin\x86\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x86</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\ARM\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
<Optimize>false</Optimize>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|ARM'">
<PlatformTarget>ARM</PlatformTarget>
<OutputPath>bin\ARM\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>ARM</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<AllowUnsafeBlocks>false</AllowUnsafeBlocks>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<NoWarn>;2008</NoWarn>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<PlatformTarget>x64</PlatformTarget>
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<Optimize>true</Optimize>
<NoWarn>;2008</NoWarn>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
</PropertyGroup>
<PropertyGroup>
<RestoreProjectStyle>PackageReference</RestoreProjectStyle>
</PropertyGroup>
<ItemGroup>
<Compile Include="LocalNotificationProxy.cs" />
<Compile Include="LocalNotification\Builder.cs" />
<Compile Include="LocalNotification\Button.cs" />
<Compile Include="LocalNotification\Notification.cs" />
<Compile Include="LocalNotification\IAction.cs" />
<Compile Include="LocalNotification\Input.cs" />
<Compile Include="LocalNotification\Manager.cs" />
<Compile Include="LocalNotification\Options.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NETCore">
<Version>5.0.0</Version>
</PackageReference>
<PackageReference Include="Microsoft.NETCore.Portable.Compatibility">
<Version>1.0.1</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\Microsoft.Toolkit.Uwp.Notifications.UWP\Microsoft.Toolkit.Uwp.Notifications.UWP.csproj">
<Project>{fb381278-f4ad-4703-a12a-c43ee0b231bd}</Project>
<Name>Microsoft.Toolkit.Uwp.Notifications.UWP</Name>
</ProjectReference>
</ItemGroup>
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("LocalNotificationProxy")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("LocalNotificationProxy")]
[assembly: AssemblyCopyright("Copyright © 2017")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]
\ No newline at end of file
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Debug\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Debug\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Debug\LocalNotificationProxy.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\LocalNotificationProxy.winmdobj
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\LocalNotificationProxy.compile.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\priconfig.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\priconfig.xml.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\layout.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\layout.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\resources.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\resources.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\pri.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\pri.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\qualifiers.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\qualifiers.txt.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\MultipleQualifiersPerDimensionFound.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Debug\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Debug\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Debug\Microsoft.Toolkit.Uwp.Notifications.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Debug\Microsoft.Toolkit.Uwp.Notifications.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Debug\LocalNotificationProxy.csprojResolveAssemblyReference.cache
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\ARM\Debug\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\ARM\Debug\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\ARM\Debug\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\ARM\Debug" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\ARM\Debug\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\ARM\Debug\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\ARM\Debug\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\ARM\Debug" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Release\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Release\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Release\LocalNotificationProxy.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\LocalNotificationProxy.csprojResolveAssemblyReference.cache
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\LocalNotificationProxy.winmdobj
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\LocalNotificationProxy.compile.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\priconfig.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\priconfig.xml.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\layout.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\layout.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\resources.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\resources.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\pri.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\pri.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\qualifiers.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\qualifiers.txt.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\ARM\Release\MultipleQualifiersPerDimensionFound.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Release\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Release\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Release\Microsoft.Toolkit.Uwp.Notifications.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\ARM\Release\Microsoft.Toolkit.Uwp.Notifications.pri
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\ARM\Release\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\ARM\Release\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\ARM\Release\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\ARM\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\ARM\Release\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\ARM\Release\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\ARM\Release\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\ARM\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Debug\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Debug\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Debug\LocalNotificationProxy.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\LocalNotificationProxy.winmdobj
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\LocalNotificationProxy.compile.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\priconfig.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\priconfig.xml.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\layout.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\layout.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\resources.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\resources.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\pri.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\pri.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\qualifiers.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\qualifiers.txt.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Debug\MultipleQualifiersPerDimensionFound.txt
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Debug\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Debug\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Debug\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Debug" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Debug\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Debug\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Debug\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Debug" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Condition=" '$(ExcludeRestorePackageImports)' != 'true' ">
<RestoreSuccess Condition=" '$(RestoreSuccess)' == '' ">True</RestoreSuccess>
<RestoreTool Condition=" '$(RestoreTool)' == '' ">NuGet</RestoreTool>
<ProjectAssetsFile Condition=" '$(ProjectAssetsFile)' == '' ">Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\project.assets.json</ProjectAssetsFile>
<NuGetPackageRoot Condition=" '$(NuGetPackageRoot)' == '' ">$(UserProfile)\.nuget\packages\</NuGetPackageRoot>
<NuGetPackageFolders Condition=" '$(NuGetPackageFolders)' == '' ">C:\Users\katze\.nuget\packages\</NuGetPackageFolders>
<NuGetProjectStyle Condition=" '$(NuGetProjectStyle)' == '' ">PackageReference</NuGetProjectStyle>
<NuGetToolVersion Condition=" '$(NuGetToolVersion)' == '' ">4.2.0</NuGetToolVersion>
</PropertyGroup>
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
</PropertyGroup>
</Project>
\ No newline at end of file
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Release\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Release\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Release\LocalNotificationProxy.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Release\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Release\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Release\Microsoft.Toolkit.Uwp.Notifications.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\Release\Microsoft.Toolkit.Uwp.Notifications.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\LocalNotificationProxy.csprojResolveAssemblyReference.cache
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\LocalNotificationProxy.winmdobj
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\LocalNotificationProxy.compile.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\priconfig.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\priconfig.xml.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\layout.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\layout.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\resources.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\resources.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\pri.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\pri.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\qualifiers.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\qualifiers.txt.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\Release\MultipleQualifiersPerDimensionFound.txt
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Release\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Release\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Release\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Release\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Release\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Release\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x64\Release\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x64\Release\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x64\Release\LocalNotificationProxy.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x64\Release\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x64\Release\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x64\Release\Microsoft.Toolkit.Uwp.Notifications.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x64\Release\Microsoft.Toolkit.Uwp.Notifications.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\LocalNotificationProxy.winmdobj
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\LocalNotificationProxy.compile.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\priconfig.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\priconfig.xml.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\layout.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\layout.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\resources.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\resources.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\pri.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\pri.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\qualifiers.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\qualifiers.txt.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\MultipleQualifiersPerDimensionFound.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x64\Release\LocalNotificationProxy.csprojResolveAssemblyReference.cache
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\x64\Release\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\x64\Release\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\x64\Release\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\x64\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\x64\Release\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\x64\Release\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\x64\Release\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\x64\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x86\Release\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x86\Release\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x86\Release\LocalNotificationProxy.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x86\Release\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x86\Release\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x86\Release\Microsoft.Toolkit.Uwp.Notifications.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\bin\x86\Release\Microsoft.Toolkit.Uwp.Notifications.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\LocalNotificationProxy.winmd
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\LocalNotificationProxy.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\LocalNotificationProxy.winmdobj
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\LocalNotificationProxy.compile.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\priconfig.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\priconfig.xml.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\layout.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\layout.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\resources.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\resources.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\pri.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\pri.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\qualifiers.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\qualifiers.txt.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\MultipleQualifiersPerDimensionFound.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\LocalNotificationProxy\LocalNotificationProxy\obj\x86\Release\LocalNotificationProxy.csprojResolveAssemblyReference.cache
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\x86\Release\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\x86\Release\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\x86\Release\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\x86\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\x86\Release\layout.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\x86\Release\resources.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="LocalNotificationProxy" />
<indexer-config type="RESJSON" initialPath="LocalNotificationProxy" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\x86\Release\pri.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\x86\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="de-DE" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Groups semantically identify that the content in the group must either be displayed as a whole, or not displayed if it cannot fit. Groups also allow creating multiple columns. Supported on Tiles since RTM. Supported on Toasts since Anniversary Update.
/// </summary>
public sealed class AdaptiveGroup : ITileBindingContentAdaptiveChild, IAdaptiveChild, IToastBindingGenericChild
{
/// <summary>
/// The only valid children of groups are <see cref="AdaptiveSubgroup"/>. Each subgroup is displayed as a separate vertical column. Note that you must include at least one subgroup in your group, otherwise an <see cref="InvalidOperationException"/> will be thrown when you try to retrieve the XML for the notification.
/// </summary>
public IList<AdaptiveSubgroup> Children { get; private set; } = new List<AdaptiveSubgroup>();
internal Element_AdaptiveGroup ConvertToElement()
{
if (Children.Count == 0)
{
throw new InvalidOperationException("Groups must have at least one child subgroup. The Children property had zero items in it.");
}
Element_AdaptiveGroup group = new Element_AdaptiveGroup();
foreach (var subgroup in Children)
{
group.Children.Add(subgroup.ConvertToElement());
}
return group;
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive
{
internal static class AdaptiveHelper
{
internal static object ConvertToElement(object obj)
{
if (obj is AdaptiveText)
{
return (obj as AdaptiveText).ConvertToElement();
}
if (obj is AdaptiveImage)
{
return (obj as AdaptiveImage).ConvertToElement();
}
if (obj is AdaptiveGroup)
{
return (obj as AdaptiveGroup).ConvertToElement();
}
if (obj is AdaptiveSubgroup)
{
return (obj as AdaptiveSubgroup).ConvertToElement();
}
if (obj is AdaptiveProgressBar)
{
return (obj as AdaptiveProgressBar).ConvertToElement();
}
throw new NotImplementedException("Unknown object: " + obj.GetType());
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// An inline image.
/// </summary>
public sealed class AdaptiveImage
: IBaseImage,
IToastBindingGenericChild,
ITileBindingContentAdaptiveChild,
IAdaptiveChild,
IAdaptiveSubgroupChild
{
/// <summary>
/// Control the desired cropping of the image. Supported on Tiles since RTM. Supported on Toast since Anniversary Update.
/// </summary>
public AdaptiveImageCrop HintCrop { get; set; }
/// <summary>
/// By default, images have an 8px margin around them. You can remove this margin by setting this property to true. Supported on Tiles since RTM. Supported on Toast since Anniversary Update.
/// </summary>
public bool? HintRemoveMargin { get; set; }
/// <summary>
/// The horizontal alignment of the image. For Toast, this is only supported when inside an <see cref="AdaptiveSubgroup"/>.
/// </summary>
public AdaptiveImageAlign HintAlign { get; set; }
private string _source;
/// <summary>
/// Required. The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size.
/// </summary>
public string Source
{
get { return _source; }
set { BaseImageHelper.SetSource(ref _source, value); }
}
/// <summary>
/// A description of the image, for users of assistive technologies.
/// </summary>
public string AlternateText { get; set; }
/// <summary>
/// Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language.
/// </summary>
public bool? AddImageQuery { get; set; }
/// <summary>
/// Returns the image's source string.
/// </summary>
/// <returns>The image's source string.</returns>
public override string ToString()
{
if (Source == null)
{
return "Source is null";
}
return Source;
}
internal Element_AdaptiveImage ConvertToElement()
{
Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this);
image.Crop = HintCrop;
image.RemoveMargin = HintRemoveMargin;
image.Align = HintAlign;
image.Placement = AdaptiveImagePlacement.Inline;
return image;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Specifies the horizontal alignment for an image.
/// </summary>
public enum AdaptiveImageAlign
{
/// <summary>
/// Default value, alignment behavior determined by renderer.
/// </summary>
Default,
/// <summary>
/// Image stretches to fill available width (and potentially available height too, depending on where the image is).
/// </summary>
[EnumString("stretch")]
Stretch,
/// <summary>
/// Align the image to the left, displaying the image at its native resolution.
/// </summary>
[EnumString("left")]
Left,
/// <summary>
/// Align the image in the center horizontally, displaying the image at its native resolution.
/// </summary>
[EnumString("center")]
Center,
/// <summary>
/// Align the image to the right, displaying the image at its native resolution.
/// </summary>
[EnumString("right")]
Right
}
/// <summary>
/// Specify the desired cropping of the image.
/// </summary>
public enum AdaptiveImageCrop
{
/// <summary>
/// Default value, cropping behavior determined by renderer.
/// </summary>
Default,
/// <summary>
/// Image is not cropped.
/// </summary>
[EnumString("none")]
None,
/// <summary>
/// Image is cropped to a circle shape.
/// </summary>
[EnumString("circle")]
Circle
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
#if WINRT
using System.Collections.Generic;
#endif
using System;
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// New in Creators Update: A progress bar. Only supported on toasts on Desktop, build 15007 or newer.
/// </summary>
public sealed class AdaptiveProgressBar : IToastBindingGenericChild
{
#if WINRT
/// <summary>
/// Gets a dictionary of the current data bindings, where you can assign new bindings.
/// </summary>
public IDictionary<AdaptiveProgressBarBindableProperty, string> Bindings { get; private set; } = new Dictionary<AdaptiveProgressBarBindableProperty, string>();
#endif
/// <summary>
/// Gets or sets an optional title string. Supports data binding.
/// </summary>
public
#if WINRT
string
#else
BindableString
#endif
Title { get; set; }
/// <summary>
/// Gets or sets the value of the progress bar. Supports data binding. Defaults to 0.
/// </summary>
public
#if WINRT
AdaptiveProgressBarValue
#else
BindableProgressBarValue
#endif
Value { get; set; } = AdaptiveProgressBarValue.FromValue(0);
/// <summary>
/// Gets or sets an optional string to be displayed instead of the default percentage string. If this isn't provided, something like "70%" will be displayed.
/// </summary>
public
#if WINRT
string
#else
BindableString
#endif
ValueStringOverride { get; set; }
/// <summary>
/// Required. Gets or sets a status string, which is displayed underneath the progress bar. This string should reflect the status of the operation, like "Downloading..." or "Installing..."
/// </summary>
public
#if WINRT
string
#else
BindableString
#endif
Status { get; set; }
internal Element_AdaptiveProgressBar ConvertToElement()
{
// If Value not provided, we use 0
var val = Value;
if (val == null)
{
val = AdaptiveProgressBarValue.FromValue(0);
}
var answer = new Element_AdaptiveProgressBar();
#if WINRT
answer.Title = XmlWriterHelper.GetBindingOrAbsoluteXmlValue(Bindings, AdaptiveProgressBarBindableProperty.Title, Title);
answer.Value = XmlWriterHelper.GetBindingOrAbsoluteXmlValue(Bindings, AdaptiveProgressBarBindableProperty.Value, val.ToXmlString());
answer.ValueStringOverride = XmlWriterHelper.GetBindingOrAbsoluteXmlValue(Bindings, AdaptiveProgressBarBindableProperty.ValueStringOverride, ValueStringOverride);
answer.Status = XmlWriterHelper.GetBindingOrAbsoluteXmlValue(Bindings, AdaptiveProgressBarBindableProperty.Status, Status);
#else
answer.Title = Title?.ToXmlString();
answer.Value = val.ToXmlString();
answer.ValueStringOverride = ValueStringOverride?.ToXmlString();
answer.Status = Status?.ToXmlString();
#endif
if (answer.Status == null)
{
throw new NullReferenceException("Status property is required.");
}
return answer;
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
// Note that this code is only compiled for WinRT. It is not compiled in any of the other projects.
#if WINRT
/// <summary>
/// An enumeration of the properties that support data binding on <see cref="AdaptiveProgressBar"/> .
/// </summary>
public enum AdaptiveProgressBarBindableProperty
{
/// <summary>
/// An optional title string
/// </summary>
Title,
/// <summary>
/// The value of the progress bar.
/// </summary>
Value,
/// <summary>
/// An optional string to be displayed instead of the default percentage string. If this isn't provided, something like "70%" will be displayed.
/// </summary>
ValueStringOverride,
/// <summary>
/// An optional status string, which is displayed underneath the progress bar. If provided, this string should reflect the status of the download, like "Downloading..." or "Installing...".
/// </summary>
Status
}
#endif
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A class that represents the progress bar's value.
/// </summary>
public sealed class AdaptiveProgressBarValue
{
/// <summary>
/// Gets or sets the value (0-1) representing the percent complete.
/// </summary>
public double Value { get; set; }
/// <summary>
/// Gets or sets whether the progress bar is indeterminate.
/// </summary>
public bool IsIndeterminate { get; set; }
/// <summary>
/// Private constructor
/// </summary>
private AdaptiveProgressBarValue()
{
}
internal string ToXmlString()
{
if (IsIndeterminate)
{
return "indeterminate";
}
return Value.ToString();
}
/// <summary>
/// Returns an indeterminate progress bar value.
/// </summary>
public static AdaptiveProgressBarValue Indeterminate
{
get
{
return new AdaptiveProgressBarValue()
{
IsIndeterminate = true
};
}
}
/// <summary>
/// Returns a progress bar value using the specified value (0-1) representing the percent complete.
/// </summary>
/// <param name="d">The value, 0-1, inclusive.</param>
/// <returns>A progress bar value.</returns>
public static AdaptiveProgressBarValue FromValue(double d)
{
if (d < 0 || d > 1)
{
throw new ArgumentOutOfRangeException("d", "Value must be between 0 and 1, inclusive.");
}
return new AdaptiveProgressBarValue()
{
Value = d
};
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Subgroups are vertical columns that can contain text and images. Supported on Tiles since RTM. Supported on Toasts since Anniversary Update.
/// </summary>
public sealed class AdaptiveSubgroup
{
/// <summary>
/// <see cref="AdaptiveText"/> and <see cref="AdaptiveImage"/> are valid children of subgroups.
/// </summary>
public IList<IAdaptiveSubgroupChild> Children { get; private set; } = new List<IAdaptiveSubgroupChild>();
private int? _hintWeight;
/// <summary>
/// Control the width of this subgroup column by specifying the weight, relative to the other subgroups.
/// </summary>
public int? HintWeight
{
get
{
return _hintWeight;
}
set
{
Element_AdaptiveSubgroup.CheckWeight(value);
_hintWeight = value;
}
}
/// <summary>
/// Control the vertical alignment of this subgroup's content.
/// </summary>
public AdaptiveSubgroupTextStacking HintTextStacking { get; set; } = Element_AdaptiveSubgroup.DEFAULT_TEXT_STACKING;
internal Element_AdaptiveSubgroup ConvertToElement()
{
var subgroup = new Element_AdaptiveSubgroup()
{
Weight = HintWeight,
TextStacking = HintTextStacking
};
foreach (var child in Children)
{
subgroup.Children.Add(ConvertToSubgroupChildElement(child));
}
return subgroup;
}
private static IElement_AdaptiveSubgroupChild ConvertToSubgroupChildElement(IAdaptiveSubgroupChild child)
{
if (child is AdaptiveText)
{
return (child as AdaptiveText).ConvertToElement();
}
if (child is AdaptiveImage)
{
return (child as AdaptiveImage).ConvertToElement();
}
throw new NotImplementedException("Unknown child: " + child.GetType());
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// TextStacking specifies the vertical alignment of content.
/// </summary>
public enum AdaptiveSubgroupTextStacking
{
/// <summary>
/// Renderer automatically selects the default vertical alignment.
/// </summary>
Default,
/// <summary>
/// Vertical align to the top.
/// </summary>
[EnumString("top")]
Top,
/// <summary>
/// Vertical align to the center.
/// </summary>
[EnumString("center")]
Center,
/// <summary>
/// Vertical align to the bottom.
/// </summary>
[EnumString("bottom")]
Bottom
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
#if WINRT
using System.Collections.Generic;
#endif
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// An adaptive text element.
/// </summary>
public sealed class AdaptiveText
: IAdaptiveChild,
IAdaptiveSubgroupChild,
ITileBindingContentAdaptiveChild,
IToastBindingGenericChild
{
#if WINRT
/// <summary>
/// Gets a dictionary of the current data bindings, where you can assign new bindings.
/// </summary>
public IDictionary<AdaptiveTextBindableProperty, string> Bindings { get; private set; } = new Dictionary<AdaptiveTextBindableProperty, string>();
#endif
/// <summary>
/// The text to display. Data binding support added in Creators Update, only works for toast top-level text elements.
/// </summary>
public
#if WINRT
string
#else
BindableString
#endif
Text { get; set; }
/// <summary>
/// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string.
/// </summary>
public string Language { get; set; }
/// <summary>
/// The style controls the text's font size, weight, and opacity. Note that for Toast, the style will only take effect if the text is inside an <see cref="AdaptiveSubgroup"/>.
/// </summary>
public AdaptiveTextStyle HintStyle { get; set; }
/// <summary>
/// Set this to true to enable text wrapping. For Tiles, this is false by default. For Toasts, this is true on top-level text elements, and false inside an <see cref="AdaptiveSubgroup"/>. Note that for Toast, setting wrap will only take effect if the text is inside an <see cref="AdaptiveSubgroup"/> (you can use HintMaxLines = 1 to prevent top-level text elements from wrapping).
/// </summary>
public bool? HintWrap { get; set; }
private int? _hintMaxLines;
/// <summary>
/// The maximum number of lines the text element is allowed to display. For Tiles, this is infinity by default. For Toasts, top-level text elements will have varying max line amounts (and in the Anniversary Update you can change the max lines). Text on a Toast inside an <see cref="AdaptiveSubgroup"/> will behave identically to Tiles (default to infinity).
/// </summary>
public int? HintMaxLines
{
get
{
return _hintMaxLines;
}
set
{
if (value != null)
{
Element_AdaptiveText.CheckMaxLinesValue(value.Value);
}
_hintMaxLines = value;
}
}
private int? _hintMinLines;
/// <summary>
/// The minimum number of lines the text element must display. Note that for Toast, this property will only take effect if the text is inside an <see cref="AdaptiveSubgroup"/>.
/// </summary>
public int? HintMinLines
{
get
{
return _hintMinLines;
}
set
{
if (value != null)
{
Element_AdaptiveText.CheckMinLinesValue(value.Value);
}
_hintMinLines = value;
}
}
/// <summary>
/// The horizontal alignment of the text. Note that for Toast, this property will only take effect if the text is inside an <see cref="AdaptiveSubgroup"/>.
/// </summary>
public AdaptiveTextAlign HintAlign { get; set; }
internal Element_AdaptiveText ConvertToElement()
{
var answer = new Element_AdaptiveText()
{
Lang = Language,
Style = HintStyle,
Wrap = HintWrap,
MaxLines = HintMaxLines,
MinLines = HintMinLines,
Align = HintAlign
};
#if WINRT
answer.Text = XmlWriterHelper.GetBindingOrAbsoluteXmlValue(Bindings, AdaptiveTextBindableProperty.Text, Text);
#else
answer.Text = Text?.ToXmlString();
#endif
return answer;
}
/// <summary>
/// Returns the value of the Text property.
/// </summary>
/// <returns>The value of the Text property.</returns>
public override string ToString()
{
return Text;
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
// Note that this code is only compiled for WinRT. It is not compiled in any of the other projects.
#if WINRT
/// <summary>
/// An enumeration of the properties that support data binding on <see cref="AdaptiveText"/> .
/// </summary>
public enum AdaptiveTextBindableProperty
{
/// <summary>
/// The text to display. Added in Creators Update only for toast top-level elements.
/// </summary>
Text
}
#endif
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Text style controls font size, weight, and opacity.
/// </summary>
public enum AdaptiveTextStyle
{
/// <summary>
/// Style is determined by the renderer.
/// </summary>
Default,
/// <summary>
/// Default value. Paragraph font size, normal weight and opacity.
/// </summary>
[EnumString("caption")]
Caption,
/// <summary>
/// Same as Caption but with subtle opacity.
/// </summary>
[EnumString("captionSubtle")]
CaptionSubtle,
/// <summary>
/// H5 font size.
/// </summary>
[EnumString("body")]
Body,
/// <summary>
/// Same as Body but with subtle opacity.
/// </summary>
[EnumString("bodySubtle")]
BodySubtle,
/// <summary>
/// H5 font size, bold weight. Essentially the bold version of Body.
/// </summary>
[EnumString("base")]
Base,
/// <summary>
/// Same as Base but with subtle opacity.
/// </summary>
[EnumString("baseSubtle")]
BaseSubtle,
/// <summary>
/// H4 font size.
/// </summary>
[EnumString("subtitle")]
Subtitle,
/// <summary>
/// Same as Subtitle but with subtle opacity.
/// </summary>
[EnumString("subtitleSubtle")]
SubtitleSubtle,
/// <summary>
/// H3 font size.
/// </summary>
[EnumString("title")]
Title,
/// <summary>
/// Same as Title but with subtle opacity.
/// </summary>
[EnumString("titleSubtle")]
TitleSubtle,
/// <summary>
/// Same as Title but with top/bottom padding removed.
/// </summary>
[EnumString("titleNumeral")]
TitleNumeral,
/// <summary>
/// H2 font size.
/// </summary>
[EnumString("subheader")]
Subheader,
/// <summary>
/// Same as Subheader but with subtle opacity.
/// </summary>
[EnumString("subheaderSubtle")]
SubheaderSubtle,
/// <summary>
/// Same as Subheader but with top/bottom padding removed.
/// </summary>
[EnumString("subheaderNumeral")]
SubheaderNumeral,
/// <summary>
/// H1 font size.
/// </summary>
[EnumString("header")]
Header,
/// <summary>
/// Same as Header but with subtle opacity.
/// </summary>
[EnumString("headerSubtle")]
HeaderSubtle,
/// <summary>
/// Same as Header but with top/bottom padding removed.
/// </summary>
[EnumString("headerNumeral")]
HeaderNumeral
}
/// <summary>
/// Controls the horizontal alignment of text.
/// </summary>
public enum AdaptiveTextAlign
{
/// <summary>
/// Alignment is automatically determined by
/// </summary>
Default,
/// <summary>
/// The system automatically decides the alignment based on the language and culture.
/// </summary>
[EnumString("auto")]
Auto,
/// <summary>
/// Horizontally align the text to the left.
/// </summary>
[EnumString("left")]
Left,
/// <summary>
/// Horizontally align the text in the center.
/// </summary>
[EnumString("center")]
Center,
/// <summary>
/// Horizontally align the text to the right.
/// </summary>
[EnumString("right")]
Right
}
internal enum AdaptiveTextPlacement
{
/// <summary>
/// Default value
/// </summary>
Inline,
[EnumString("attribution")]
Attribution
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal static class BaseImageHelper
{
internal static void SetSource(ref string destination, string value)
{
if (value == null)
{
throw new ArgumentNullException(nameof(value));
}
destination = value;
}
internal static Element_AdaptiveImage CreateBaseElement(IBaseImage curr)
{
if (curr.Source == null)
{
throw new NullReferenceException("Source property is required.");
}
return new Element_AdaptiveImage()
{
Src = curr.Source,
Alt = curr.AlternateText,
AddImageQuery = curr.AddImageQuery
};
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal class BaseTextHelper
{
internal static Element_AdaptiveText CreateBaseElement(IBaseText curr)
{
return new Element_AdaptiveText()
{
Text = curr.Text,
Lang = curr.Language
};
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
// Note that this code is NOT compiled for WinRT.
// WinRT uses a different binding system since it doesn't support implicit type converters.
#if !WINRT
/// <summary>
/// A binding value for doubles.
/// </summary>
public sealed class BindableProgressBarValue
{
/// <summary>
/// Raw value is used for the implicit converter case, where dev provided a raw double. We store the raw value,
/// so that later on when generating the XML, we can provide this value rather than binding syntax.
/// </summary>
internal AdaptiveProgressBarValue RawValue { get; private set; }
internal bool RawIsIndeterminate { get; private set; }
/// <summary>
/// The name that maps to your binding data value.
/// </summary>
public string BindingName { get; set; }
/// <summary>
/// Initializes a new binding for a double value, with the required binding value name. Do NOT include surrounding {} brackets.
/// </summary>
/// <param name="bindingName">The name that maps to your binding data value.</param>
public BindableProgressBarValue(string bindingName)
{
BindingName = bindingName;
}
/// <summary>
/// Private constructor used by the implicit converter to assign the raw value.
/// </summary>
private BindableProgressBarValue()
{
}
internal string ToXmlString()
{
if (BindingName != null)
{
return "{" + BindingName + "}";
}
if (RawValue != null)
{
return RawValue.ToXmlString();
}
return null;
}
/// <summary>
/// Creates a <see cref="BindableProgressBarValue"/> that has a raw value assigned.
/// </summary>
/// <param name="v">The raw value</param>
public static implicit operator BindableProgressBarValue(AdaptiveProgressBarValue v)
{
return new BindableProgressBarValue()
{
RawValue = v
};
}
/// <summary>
/// Returns the raw value of the <see cref="BindableProgressBarValue"/>.
/// </summary>
/// <param name="b">The <see cref="BindableProgressBarValue"/> to obtain the raw value from.</param>
public static implicit operator AdaptiveProgressBarValue(BindableProgressBarValue b)
{
return b.RawValue;
}
/// <summary>
/// Creates an <see cref="BindableProgressBarValue"/> that has tbe raw double value.
/// </summary>
/// <param name="d">The raw value</param>
public static implicit operator BindableProgressBarValue(double d)
{
return AdaptiveProgressBarValue.FromValue(d);
}
}
#endif
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
// Note that this code is NOT compiled for WinRT.
// WinRT uses a different binding system since it doesn't support implicit type converters.
#if !WINRT
/// <summary>
/// A binding value for strings.
/// </summary>
public sealed class BindableString
{
internal string RawValue { get; private set; }
/// <summary>
/// The name that maps to your binding data value.
/// </summary>
public string BindingName { get; set; }
/// <summary>
/// Initializes a new binding for a string value, with the required binding name. Do NOT include surrounding {} brackets.
/// </summary>
/// <param name="bindingName">The name that maps to your data binding value.</param>
public BindableString(string bindingName)
{
BindingName = bindingName;
}
/// <summary>
/// Private constructor used by the implicit converter to assign the raw value.
/// </summary>
private BindableString()
{
}
internal string ToXmlString()
{
if (BindingName != null)
{
return "{" + BindingName + "}";
}
return RawValue;
}
/// <summary>
/// Creates a <see cref="BindableString"/> that has a raw value assigned.
/// </summary>
/// <param name="d">The raw value</param>
public static implicit operator BindableString(string d)
{
return new BindableString()
{
RawValue = d
};
}
/// <summary>
/// Returns the raw value of the <see cref="BindableString"/>.
/// </summary>
/// <param name="b">The <see cref="BindableString"/> to obtain the raw value from.</param>
public static implicit operator string(BindableString b)
{
return b.RawValue;
}
}
#endif
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
{
[NotificationXmlElement("group")]
internal sealed class Element_AdaptiveGroup : IElement_TileBindingChild, IElement_ToastBindingChild, IElementWithDescendants
{
public IList<Element_AdaptiveSubgroup> Children { get; private set; } = new List<Element_AdaptiveSubgroup>();
public IEnumerable<object> Descendants()
{
foreach (Element_AdaptiveSubgroup subgroup in Children)
{
// Return the subgroup
yield return subgroup;
// And also return its descendants
foreach (object descendant in subgroup.Descendants())
{
yield return descendant;
}
}
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
{
[NotificationXmlElement("image")]
internal sealed class Element_AdaptiveImage : IElement_TileBindingChild, IElement_ToastBindingChild, IElement_AdaptiveSubgroupChild
{
internal const AdaptiveImagePlacement DEFAULT_PLACEMENT = AdaptiveImagePlacement.Inline;
internal const AdaptiveImageCrop DEFAULT_CROP = AdaptiveImageCrop.Default;
internal const AdaptiveImageAlign DEFAULT_ALIGN = AdaptiveImageAlign.Default;
[NotificationXmlAttribute("id")]
public int? Id { get; set; }
[NotificationXmlAttribute("src")]
public string Src { get; set; }
[NotificationXmlAttribute("alt")]
public string Alt { get; set; }
[NotificationXmlAttribute("addImageQuery")]
public bool? AddImageQuery { get; set; }
[NotificationXmlAttribute("placement", DEFAULT_PLACEMENT)]
public AdaptiveImagePlacement Placement { get; set; } = DEFAULT_PLACEMENT;
[NotificationXmlAttribute("hint-align", DEFAULT_ALIGN)]
public AdaptiveImageAlign Align { get; set; } = DEFAULT_ALIGN;
[NotificationXmlAttribute("hint-crop", DEFAULT_CROP)]
public AdaptiveImageCrop Crop { get; set; } = DEFAULT_CROP;
[NotificationXmlAttribute("hint-removeMargin")]
public bool? RemoveMargin { get; set; }
private int? _overlay;
[NotificationXmlAttribute("hint-overlay")]
public int? Overlay
{
get
{
return _overlay;
}
set
{
if (value != null)
{
Element_TileBinding.CheckOverlayValue(value.Value);
}
_overlay = value;
}
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
{
internal enum AdaptiveImagePlacement
{
[EnumString("inline")]
Inline,
[EnumString("background")]
Background,
[EnumString("peek")]
Peek,
[EnumString("hero")]
Hero,
[EnumString("appLogoOverride")]
AppLogoOverride
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
{
[NotificationXmlElement("progress")]
internal sealed class Element_AdaptiveProgressBar : IElement_ToastBindingChild
{
[NotificationXmlAttribute("value")]
public string Value { get; set; }
[NotificationXmlAttribute("title")]
public string Title { get; set; }
[NotificationXmlAttribute("valueStringOverride")]
public string ValueStringOverride { get; set; }
[NotificationXmlAttribute("status")]
public string Status { get; set; }
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
{
[NotificationXmlElement("subgroup")]
internal sealed class Element_AdaptiveSubgroup : IElementWithDescendants
{
internal const AdaptiveSubgroupTextStacking DEFAULT_TEXT_STACKING = AdaptiveSubgroupTextStacking.Default;
[NotificationXmlAttribute("hint-textStacking", DEFAULT_TEXT_STACKING)]
public AdaptiveSubgroupTextStacking TextStacking { get; set; } = DEFAULT_TEXT_STACKING;
private int? _weight;
[NotificationXmlAttribute("hint-weight")]
public int? Weight
{
get
{
return _weight;
}
set
{
CheckWeight(value);
_weight = value;
}
}
internal static void CheckWeight(int? weight)
{
if (weight != null && weight.Value < 1)
{
throw new ArgumentOutOfRangeException("Weight must be between 1 and int.MaxValue, inclusive (or null)");
}
}
public IList<IElement_AdaptiveSubgroupChild> Children { get; private set; } = new List<IElement_AdaptiveSubgroupChild>();
public IEnumerable<object> Descendants()
{
foreach (IElement_AdaptiveSubgroupChild child in Children)
{
// Return each child (we know there's no further descendants)
yield return child;
}
}
}
internal interface IElement_AdaptiveSubgroupChild
{
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements
{
[NotificationXmlElement("text")]
internal sealed class Element_AdaptiveText : IElement_TileBindingChild, IElement_AdaptiveSubgroupChild, IElement_ToastBindingChild
{
internal const AdaptiveTextStyle DEFAULT_STYLE = AdaptiveTextStyle.Default;
internal const AdaptiveTextAlign DEFAULT_ALIGN = AdaptiveTextAlign.Default;
internal const AdaptiveTextPlacement DEFAULT_PLACEMENT = AdaptiveTextPlacement.Inline;
[NotificationXmlContent]
public string Text { get; set; }
[NotificationXmlAttribute("id")]
public int? Id { get; set; }
[NotificationXmlAttribute("lang")]
public string Lang { get; set; }
[NotificationXmlAttribute("hint-align", DEFAULT_ALIGN)]
public AdaptiveTextAlign Align { get; set; } = DEFAULT_ALIGN;
private int? _maxLines;
[NotificationXmlAttribute("hint-maxLines")]
public int? MaxLines
{
get
{
return _maxLines;
}
set
{
if (value != null)
{
CheckMaxLinesValue(value.Value);
}
_maxLines = value;
}
}
internal static void CheckMaxLinesValue(int value)
{
if (value < 1)
{
throw new ArgumentOutOfRangeException("MaxLines must be between 1 and int.MaxValue, inclusive.");
}
}
private int? _minLines;
[NotificationXmlAttribute("hint-minLines")]
public int? MinLines
{
get
{
return _minLines;
}
set
{
if (value != null)
{
CheckMinLinesValue(value.Value);
}
_minLines = value;
}
}
internal static void CheckMinLinesValue(int value)
{
if (value < 1)
{
throw new ArgumentOutOfRangeException("MinLines must be between 1 and int.MaxValue, inclusive.");
}
}
[NotificationXmlAttribute("hint-style", DEFAULT_STYLE)]
public AdaptiveTextStyle Style { get; set; } = DEFAULT_STYLE;
[NotificationXmlAttribute("hint-wrap")]
public bool? Wrap { get; set; }
[NotificationXmlAttribute("placement", DEFAULT_PLACEMENT)]
public AdaptiveTextPlacement Placement { get; set; } = DEFAULT_PLACEMENT;
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Elements that can be direct children of adaptive content, including (<see cref="AdaptiveText"/>, <see cref="AdaptiveImage"/>, and <see cref="AdaptiveGroup"/>).
/// </summary>
public interface IAdaptiveChild
{
// Blank interface simply for compile-enforcing the child types in the list.
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Elements that can be direct children of an <see cref="AdaptiveSubgroup"/>, including (<see cref="AdaptiveText"/> and <see cref="AdaptiveImage"/>).
/// </summary>
public interface IAdaptiveSubgroupChild
{
// Blank interface simply for compile-enforcing the child types in the list.
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Contains the base properties that an image needs.
/// </summary>
public interface IBaseImage
{
/// <summary>
/// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size.
/// </summary>
string Source { get; set; }
/// <summary>
/// A description of the image, for users of assistive technologies.
/// </summary>
string AlternateText { get; set; }
/// <summary>
/// Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language.
/// </summary>
bool? AddImageQuery { get; set; }
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Defines the basic properties of a text element.
/// </summary>
public interface IBaseText
{
/// <summary>
/// The text to display.
/// </summary>
string Text { get; set; }
/// <summary>
/// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string.
/// </summary>
string Language { get; set; }
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
#if WINDOWS_UWP
using Windows.Data.Xml.Dom;
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Notification content object to display a glyph on a Tile's badge.
/// </summary>
public sealed class BadgeGlyphContent : INotificationContent
{
/// <summary>
/// Default constructor to create a glyph badge content object.
/// </summary>
public BadgeGlyphContent()
{
}
/// <summary>
/// Constructor to create a glyph badge content object with a glyph.
/// </summary>
/// <param name="glyph">The glyph to be displayed on the badge.</param>
public BadgeGlyphContent(BadgeGlyphValue glyph)
{
_glyph = glyph;
}
/// <summary>
/// The glyph to be displayed on the badge.
/// </summary>
public BadgeGlyphValue Glyph
{
get
{
return _glyph;
}
set
{
if (!Enum.IsDefined(typeof(BadgeGlyphValue), value))
{
throw new ArgumentOutOfRangeException(nameof(value));
}
_glyph = value;
}
}
/// <summary>
/// Retrieves the notification Xml content as a string.
/// </summary>
/// <returns>The notification Xml content as a string.</returns>
public string GetContent()
{
if (!Enum.IsDefined(typeof(BadgeGlyphValue), _glyph))
{
throw new NotificationContentValidationException("The badge glyph property was left unset.");
}
string glyphString = _glyph.ToString();
// lower case the first character of the enum value to match the Xml schema
glyphString = string.Format("{0}{1}", char.ToLowerInvariant(glyphString[0]), glyphString.Substring(1));
return string.Format("<badge value='{0}'/>", glyphString);
}
/// <summary>
/// Retrieves the notification XML content as a string.
/// </summary>
/// <returns>The notification XML content as a string.</returns>
public override string ToString()
{
return GetContent();
}
#if WINDOWS_UWP
/// <summary>
/// Retrieves the notification XML content as a WinRT Xml document.
/// </summary>
/// <returns>The notification XML content as a WinRT Xml document.</returns>
public XmlDocument GetXml()
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(GetContent());
return xml;
}
#endif
private BadgeGlyphValue _glyph = (BadgeGlyphValue)(-1);
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// The types of glyphs that can be placed on a badge.
/// </summary>
public enum BadgeGlyphValue
{
/// <summary>
/// No glyph. If there is a numeric badge, or a glyph currently on the badge,
/// it will be removed.
/// </summary>
None = 0,
/// <summary>
/// A glyph representing application activity.
/// </summary>
Activity,
/// <summary>
/// A glyph representing an alert.
/// </summary>
Alert,
/// <summary>
/// A glyph representing an alarm.
/// </summary>
Alarm,
/// <summary>
/// A glyph representing availability status.
/// </summary>
Available,
/// <summary>
/// A glyph representing away status
/// </summary>
Away,
/// <summary>
/// A glyph representing busy status.
/// </summary>
Busy,
/// <summary>
/// A glyph representing that a new message is available.
/// </summary>
NewMessage,
/// <summary>
/// A glyph representing that media is paused.
/// </summary>
Paused,
/// <summary>
/// A glyph representing that media is playing.
/// </summary>
Playing,
/// <summary>
/// A glyph representing unavailable status.
/// </summary>
Unavailable,
/// <summary>
/// A glyph representing an error.
/// </summary>
Error,
/// <summary>
/// A glyph representing attention status.
/// </summary>
Attention
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
#if WINDOWS_UWP
using Windows.Data.Xml.Dom;
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Notification content object to display a number on a Tile's badge.
/// </summary>
public sealed class BadgeNumericContent : INotificationContent
{
/// <summary>
/// Default constructor to create a numeric badge content object.
/// </summary>
public BadgeNumericContent()
{
}
/// <summary>
/// Constructor to create a numeric badge content object with a number.
/// </summary>
/// <param name="number">
/// The number that will appear on the badge. If the number is 0, the badge
/// will be removed.
/// </param>
public BadgeNumericContent(uint number)
{
_number = number;
}
/// <summary>
/// The number that will appear on the badge. If the number is 0, the badge
/// will be removed.
/// </summary>
public uint Number
{
get { return _number; }
set { _number = value; }
}
/// <summary>
/// Retrieves the notification Xml content as a string.
/// </summary>
/// <returns>The notification Xml content as a string.</returns>
public string GetContent()
{
return string.Format("<badge value='{0}'/>", _number);
}
/// <summary>
/// Retrieves the notification Xml content as a string.
/// </summary>
/// <returns>The notification Xml content as a string.</returns>
public override string ToString()
{
return GetContent();
}
#if WINDOWS_UWP
/// <summary>
/// Retrieves the notification Xml content as a WinRT Xml document.
/// </summary>
/// <returns>The notification Xml content as a WinRT Xml document.</returns>
public XmlDocument GetXml()
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(GetContent());
return xml;
}
#endif
private uint _number = 0;
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal static class ArgumentValidator
{
public static void SetProperty<T>(ref T property, T value, string propertyName, ArgumentValidatorOptions options)
{
if (options.HasFlag(ArgumentValidatorOptions.NotNull))
{
if (value == null)
{
throw new ArgumentNullException(propertyName);
}
}
property = value;
}
}
[Flags]
internal enum ArgumentValidatorOptions
{
NotNull
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.IO;
using System.Text;
#if WINDOWS_UWP
using Windows.Data.Xml.Dom;
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal abstract class BaseElement
{
/// <summary>
/// Retrieves the notification XML content as a string.
/// </summary>
/// <returns>The notification XML content as a string.</returns>
public string GetContent()
{
using (MemoryStream stream = new MemoryStream())
{
using (System.Xml.XmlWriter writer = System.Xml.XmlWriter.Create(stream, new System.Xml.XmlWriterSettings()
{
Encoding = Encoding.UTF8, // Use UTF-8 encoding to save space (it defaults to UTF-16 which is 2x the size)
Indent = false,
NewLineOnAttributes = false
}))
{
XmlWriterHelper.Write(writer, this);
}
stream.Position = 0;
using (StreamReader reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
#if WINDOWS_UWP
/// <summary>
/// Retrieves the notification XML content as a WinRT XML document.
/// </summary>
/// <returns>The notification XML content as a WinRT XML document.</returns>
public XmlDocument GetXml()
{
XmlDocument xml = new XmlDocument();
xml.LoadXml(GetContent());
return xml;
}
#endif
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal sealed class EnumStringAttribute : Attribute
{
public string String { get; }
public EnumStringAttribute(string s)
{
if (s == null)
{
throw new ArgumentNullException(nameof(s));
}
String = s;
}
public override string ToString()
{
return String;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
#if WINDOWS_UWP
using Windows.Data.Xml.Dom;
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Base notification content interface to retrieve notification Xml as a string.
/// </summary>
public interface INotificationContent
{
/// <summary>
/// Retrieves the notification Xml content as a string.
/// </summary>
/// <returns>The notification Xml content as a string.</returns>
string GetContent();
#if WINDOWS_UWP
/// <summary>
/// Retrieves the notification Xml content as a WinRT Xml document.
/// </summary>
/// <returns>The notification Xml content as a WinRT Xml document.</returns>
XmlDocument GetXml();
#endif
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections;
using System.Collections.Generic;
#if WINDOWS_UWP
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal sealed class LimitedList<T> : IList<T>
{
private List<T> _list;
public int Limit { get; private set; }
public LimitedList(int limit)
{
_list = new List<T>(limit);
Limit = limit;
}
public T this[int index]
{
get
{
return _list[index];
}
set
{
_list[index] = value;
}
}
public int Count
{
get
{
return _list.Count;
}
}
public bool IsReadOnly
{
get
{
return false;
}
}
public void Add(T item)
{
if (_list.Count >= Limit)
{
throw new Exception("This list is limited to " + Limit + " items. You cannot add more items.");
}
_list.Add(item);
}
public void Clear()
{
_list.Clear();
}
public bool Contains(T item)
{
return _list.Contains(item);
}
public void CopyTo(T[] array, int arrayIndex)
{
_list.CopyTo(array, arrayIndex);
}
public IEnumerator<T> GetEnumerator()
{
return _list.GetEnumerator();
}
public int IndexOf(T item)
{
return _list.IndexOf(item);
}
public void Insert(int index, T item)
{
_list.Insert(index, item);
}
public bool Remove(T item)
{
return _list.Remove(item);
}
public void RemoveAt(int index)
{
_list.RemoveAt(index);
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
internal interface IElementWithDescendants
{
IEnumerable<object> Descendants();
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
#if WINDOWS_UWP
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Exception returned when invalid notification content is provided.
/// </summary>
internal sealed class NotificationContentValidationException : Exception
{
public NotificationContentValidationException(string message)
: base(message)
{
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
#if WINDOWS_UWP
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal sealed class NotificationXmlAttributeAttribute : Attribute
{
public string Name { get; private set; }
public object DefaultValue { get; private set; }
public NotificationXmlAttributeAttribute(string name, object defaultValue = null)
{
Name = name;
DefaultValue = defaultValue;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
#if WINDOWS_UWP
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// This attribute should be specified at most one time on an Element class. The property's value will be written as a string in the element's body.
/// </summary>
internal sealed class NotificationXmlContentAttribute : Attribute
{
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
#if WINDOWS_UWP
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal sealed class NotificationXmlElementAttribute : Attribute
{
public string Name { get; private set; }
public NotificationXmlElementAttribute(string name)
{
if (string.IsNullOrWhiteSpace(name))
{
throw new ArgumentNullException("name cannot be null or whitespace");
}
Name = name;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
#if WINDOWS_UWP
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal static class XmlWriterHelper
{
public static void Write(System.Xml.XmlWriter writer, object element)
{
NotificationXmlElementAttribute elAttr = GetElementAttribute(element.GetType());
// If it isn't an element attribute, don't write anything
if (elAttr == null)
{
return;
}
writer.WriteStartElement(elAttr.Name);
IEnumerable<PropertyInfo> properties = GetProperties(element.GetType());
List<object> elements = new List<object>();
object content = null;
// Write the attributes first
foreach (PropertyInfo p in properties)
{
IEnumerable<Attribute> attributes = GetCustomAttributes(p);
NotificationXmlAttributeAttribute attr = attributes.OfType<NotificationXmlAttributeAttribute>().FirstOrDefault();
object propertyValue = GetPropertyValue(p, element);
// If it's an attribute
if (attr != null)
{
object defaultValue = attr.DefaultValue;
// If the value is not the default value (and it's not null) we'll write it
if (!object.Equals(propertyValue, defaultValue) && propertyValue != null)
{
writer.WriteAttributeString(attr.Name, PropertyValueToString(propertyValue));
}
}
// If it's a content attribute
else if (attributes.OfType<NotificationXmlContentAttribute>().Any())
{
content = propertyValue;
}
// Otherwise it's an element or collection of elements
else
{
if (propertyValue != null)
{
elements.Add(propertyValue);
}
}
}
// Then write children
foreach (object el in elements)
{
// If it's a collection of children
if (el is IEnumerable)
{
foreach (object child in el as IEnumerable)
{
Write(writer, child);
}
continue;
}
// Otherwise just write the single element
Write(writer, el);
}
// Then write any content if there is content
if (content != null)
{
string contentString = content.ToString();
if (!string.IsNullOrWhiteSpace(contentString))
{
writer.WriteString(contentString);
}
}
writer.WriteEndElement();
}
private static object GetPropertyValue(PropertyInfo propertyInfo, object obj)
{
#if NETFX_CORE
return propertyInfo.GetValue(obj);
#else
return propertyInfo.GetValue(obj, null);
#endif
}
private static string PropertyValueToString(object propertyValue)
{
Type type = propertyValue.GetType();
if (IsEnum(type))
{
EnumStringAttribute enumStringAttr = GetEnumStringAttribute(propertyValue as Enum);
if (enumStringAttr != null)
{
return enumStringAttr.String;
}
}
else if (propertyValue is bool)
{
if ((bool)propertyValue)
{
return "true";
}
return "false";
}
else if (propertyValue is DateTimeOffset?)
{
DateTimeOffset? dateTime = propertyValue as DateTimeOffset?;
if (dateTime.HasValue)
{
// ISO 8601 format
return System.Xml.XmlConvert.ToString(dateTime.Value);
}
else
{
return null;
}
}
return propertyValue.ToString();
}
private static EnumStringAttribute GetEnumStringAttribute(Enum enumValue)
{
#if NETFX_CORE
return enumValue.GetType().GetTypeInfo().GetDeclaredField(enumValue.ToString()).GetCustomAttribute<EnumStringAttribute>();
#else
MemberInfo[] memberInfo = enumValue.GetType().GetMember(enumValue.ToString());
if (memberInfo != null && memberInfo.Length > 0)
{
object[] attrs = memberInfo[0].GetCustomAttributes(typeof(EnumStringAttribute), false);
if (attrs != null && attrs.Length > 0)
return attrs[0] as EnumStringAttribute;
}
return null;
#endif
}
private static bool IsEnum(Type type)
{
#if NETFX_CORE
return type.GetTypeInfo().IsEnum;
#else
return type.IsEnum;
#endif
}
private static IEnumerable<PropertyInfo> GetProperties(Type type)
{
#if NETFX_CORE
return type.GetTypeInfo().DeclaredProperties;
#else
return type.GetProperties();
#endif
}
private static NotificationXmlElementAttribute GetElementAttribute(Type type)
{
return GetCustomAttributes(type).OfType<NotificationXmlElementAttribute>().FirstOrDefault();
}
private static IEnumerable<Attribute> GetCustomAttributes(Type type)
{
#if NETFX_CORE
return type.GetTypeInfo().GetCustomAttributes();
#else
return type.GetCustomAttributes(true).OfType<Attribute>();
#endif
}
private static IEnumerable<Attribute> GetCustomAttributes(PropertyInfo propertyInfo)
{
#if NETFX_CORE
return propertyInfo.GetCustomAttributes();
#else
return propertyInfo.GetCustomAttributes(true).OfType<Attribute>();
#endif
}
/// <summary>
/// Gets the provided binding value, if it exists. Otherwise, falls back to the absolute value.
/// </summary>
/// <typeparam name="T">The type of the enum of the class properties.</typeparam>
/// <param name="bindings">The collection of data-bound values.</param>
/// <param name="bindableProperty">The property to obtain.</param>
/// <param name="absoluteValue">The absolute value, if any.</param>
/// <returns>The provided binding value, if it exists. Otherwise, falls back to the absolute value.</returns>
internal static string GetBindingOrAbsoluteXmlValue<T>(IDictionary<T, string> bindings, T bindableProperty, string absoluteValue)
{
// If a binding is provided, use the binding value
string bindingValue;
if (bindings.TryGetValue(bindableProperty, out bindingValue))
{
return "{" + bindingValue + "}";
}
// Otherwise fallback to the absolute value
return absoluteValue;
}
}
}
\ No newline at end of file
@echo off
set files=..\Microsoft.Windows.Toolkit.Notifications.Portable\bin\Release\Microsoft.Windows.Toolkit.Notifications.dll
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.Portable\bin\Release\Microsoft.Windows.Toolkit.Notifications.pdb
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.Portable\bin\Release\Microsoft.Windows.Toolkit.Notifications.xml
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.WinRT\bin\Release\Microsoft.Windows.Toolkit.Notifications.winmd
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.WinRT\bin\Release\Microsoft.Windows.Toolkit.Notifications.pri
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.WinRT\bin\Release\Microsoft.Windows.Toolkit.Notifications.pdb
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.WinRT\bin\Release\Microsoft.Windows.Toolkit.Notifications.xml
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.NETStandard\bin\Release\Microsoft.Windows.Toolkit.Notifications.dll
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.NETStandard\bin\Release\Microsoft.Windows.Toolkit.Notifications.pdb
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.NETStandard\bin\Release\Microsoft.Windows.Toolkit.Notifications.xml
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.UWP\bin\Release\Microsoft.Windows.Toolkit.Notifications.dll
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.UWP\bin\Release\Microsoft.Windows.Toolkit.Notifications.pdb
set files=%files% ..\Microsoft.Windows.Toolkit.Notifications.UWP\bin\Release\Microsoft.Windows.Toolkit.Notifications.xml
FOR %%f IN (%files%) DO IF NOT EXIST %%f call :file_not_found %%f
echo Here are the current timestamps on the DLL's...
echo.
FOR %%f IN (%files%) DO ECHO %%~tf %%f
echo.
PAUSE
echo Welcome, let's create a new NuGet package for Notifications!
echo.
set /p version="Enter Version Number (ex. 10240.0.0): "
if not exist "NugetPackages" mkdir "NugetPackages"
"C:\Program Files (x86)\NuGet\nuget.exe" pack Microsoft.Windows.Toolkit.Notifications.nuspec -Version %version% -OutputDirectory "NugetPackages"
"C:\Program Files (x86)\NuGet\nuget.exe" pack Microsoft.Windows.Toolkit.Notifications.JavaScript.nuspec -Version %version% -OutputDirectory "NugetPackages"
PAUSE
explorer NugetPackages
exit
:file_not_found
echo File not found: %1
PAUSE
exit
<?xml version="1.0" encoding="utf-8"?>
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<MSBuildAllProjects>$(MSBuildAllProjects);$(MSBuildThisFileFullPath)</MSBuildAllProjects>
<HasSharedItems>true</HasSharedItems>
<SharedGUID>8bacd7a9-b205-4adf-bda9-763b30a66576</SharedGUID>
</PropertyGroup>
<PropertyGroup Label="Configuration">
<Import_RootNamespace>Microsoft.Toolkit.Uwp.Notifications</Import_RootNamespace>
</PropertyGroup>
<ItemGroup>
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveGroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveImage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveImageEnums.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveProgressBar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveProgressBarBindableProperty.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveProgressBarValue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveSubgroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveSubgroupEnums.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveText.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveTextBindableProperty.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\AdaptiveTextEnums.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\BaseImageHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\BaseTextHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\BindableValues\BindableProgressBarValue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\BindableValues\BindableString.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\Elements\Element_AdaptiveProgressBar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\IAdaptiveSubgroupChild.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\Elements\Element_AdaptiveGroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\Elements\Element_AdaptiveImage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\Elements\Element_AdaptiveImageEnums.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\Elements\Element_AdaptiveSubgroup.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\Elements\Element_AdaptiveText.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\IAdaptiveChild.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\IBaseImage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Adaptive\IBaseText.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Badges\BadgeGlyphContent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Badges\BadgeGlyphValue.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Badges\BadgeNumericContent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\ArgumentValidator.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\BaseElement.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\INotificationContent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\EnumStringAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\LimitedList{T}.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\NotificationContentValidationException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\NotificationXmlAttributeAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\NotificationXmlContentAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\NotificationXmlElementAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Common\XmlWriterHelper.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\ITileBindingContentAdaptiveChild.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileBackgroundImage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileBasicImage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileCommon.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\Elements\TileElementsCommon.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\Elements\Element_Tile.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\Elements\Element_TileBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\Elements\Element_TileVisual.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileImages.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\SpecialTemplates\TileBindingContentContact.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\SpecialTemplates\TileBindingContentIconic.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\SpecialTemplates\TileBindingContentPeople.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\SpecialTemplates\TileBindingContentPhotos.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileBasicText.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileBindingContentAdaptive.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileBranding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileContent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TilePeekImage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileSizeToAdaptiveTemplateConverter.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileTemplateNameV3.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileTextStacking.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Tiles\TileVisual.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastHeader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\IElement_ToastActivatable.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastActivationOptions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\IToastBindingGenericChild.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\IToastButton.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\IToastInput.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastActionsCustom.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastActionsSnoozeAndDismiss.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastButtonDismiss.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastButtonSnooze.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastCommon.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_Toast.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastAction.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastActions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastAudio.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastBinding.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastImage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastInput.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastSelection.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastText.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\Elements\Element_ToastVisual.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\IToastActions.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastAudio.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastBindingGeneric.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastButton.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastContent.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastContextMenuItem.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastGenericAppLogo.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastGenericAppLogoEnums.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastGenericAttributionText.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastGenericHeroImage.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastHeader.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastSelectionBox.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastSelectionBoxItem.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastTextBox.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Toasts\ToastVisual.cs" />
</ItemGroup>
<ItemGroup>
<None Include="$(MSBuildThisFileDirectory)readme.md" />
</ItemGroup>
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup Label="Globals">
<ProjectGuid>8bacd7a9-b205-4adf-bda9-763b30a66576</ProjectGuid>
<MinimumVisualStudioVersion>14.0</MinimumVisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.Default.props" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.Common.props" />
<PropertyGroup />
<Import Project="Microsoft.Toolkit.Uwp.Notifications.Shared.projitems" Label="Shared" />
<Import Project="$(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion)\CodeSharing\Microsoft.CodeSharing.CSharp.targets" />
</Project>
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("tile")]
internal sealed class Element_Tile : BaseElement
{
public Element_TileVisual Visual { get; set; }
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("binding")]
internal sealed class Element_TileBinding : IElementWithDescendants
{
internal const TileBranding DEFAULT_BRANDING = TileBranding.Auto;
internal const TileTextStacking DEFAULT_TEXT_STACKING = TileTextStacking.Top;
internal const int DEFAULT_OVERLAY = 20;
public Element_TileBinding(TileTemplateNameV3 template)
{
Template = template;
}
[NotificationXmlAttribute("template")]
public TileTemplateNameV3 Template { get; private set; }
/// <summary>
/// Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of
///
/// "www.website.com/images/hello.png"
///
/// included in the notification becomes
///
/// "www.website.com/images/hello.png?ms-scale=100&amp;ms-contrast=standard&amp;ms-lang=en-us"
/// </summary>
[NotificationXmlAttribute("addImageQuery")]
public bool? AddImageQuery { get; set; }
/// <summary>
/// A default base URI that is combined with relative URIs in image source attributes.
/// </summary>
[NotificationXmlAttribute("baseUri")]
public Uri BaseUri { get; set; }
/// <summary>
/// The form that the Tile should use to display the app's brand.
/// </summary>
[NotificationXmlAttribute("branding", DEFAULT_BRANDING)]
public TileBranding Branding { get; set; } = DEFAULT_BRANDING;
/// <summary>
/// Set to a sender-defined string that uniquely identifies the content of the notification. This prevents duplicates in the situation where a large Tile template is displaying the last three wide Tile notifications.
///
/// Required: NO
/// </summary>
[NotificationXmlAttribute("contentId")]
public string ContentId { get; set; }
/// <summary>
/// An optional string to override the Tile's display name while showing this notification.
/// </summary>
[NotificationXmlAttribute("displayName")]
public string DisplayName { get; set; }
/// <summary>
/// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides that in visual, but can be overriden by that in text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. See Remarks for when this value isn't specified.
/// </summary>
[NotificationXmlAttribute("lang")]
public string Language { get; set; }
[NotificationXmlAttribute("hint-lockDetailedStatus1")]
public string LockDetailedStatus1 { get; set; }
[NotificationXmlAttribute("hint-lockDetailedStatus2")]
public string LockDetailedStatus2 { get; set; }
[NotificationXmlAttribute("hint-lockDetailedStatus3")]
public string LockDetailedStatus3 { get; set; }
[NotificationXmlAttribute("arguments")]
public string Arguments { get; set; }
/// <summary>
/// Throws exception if value is invalid
/// </summary>
/// <param name="value">Overlay value (0-100)</param>
internal static void CheckOverlayValue(int value)
{
if (value < 0 || value > 100)
{
throw new ArgumentOutOfRangeException("Overlay must be between 0 and 100, inclusive.");
}
}
[NotificationXmlAttribute("hint-presentation")]
public TilePresentation? Presentation { get; set; }
[NotificationXmlAttribute("hint-textStacking", DEFAULT_TEXT_STACKING)]
public TileTextStacking TextStacking { get; set; } = DEFAULT_TEXT_STACKING;
public IList<IElement_TileBindingChild> Children { get; private set; } = new List<IElement_TileBindingChild>();
/// <summary>
/// Generates an enumerable collection of children and all those children's children
/// </summary>
/// <returns>Enumerable collection of children and all those children's children.</returns>
public IEnumerable<object> Descendants()
{
foreach (IElement_TileBindingChild child in Children)
{
// Return the child
yield return child;
// And if it has descendants, return the descendants
if (child is IElementWithDescendants)
{
foreach (object descendant in (child as IElementWithDescendants).Descendants())
{
yield return descendant;
}
}
}
}
}
internal interface IElement_TileBindingChild
{
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("visual")]
internal sealed class Element_TileVisual
{
internal const TileBranding DEFAULT_BRANDING = TileBranding.Auto;
internal const bool DEFAULT_ADD_IMAGE_QUERY = false;
[NotificationXmlAttribute("addImageQuery")]
public bool? AddImageQuery { get; set; }
[NotificationXmlAttribute("baseUri")]
public Uri BaseUri { get; set; }
[NotificationXmlAttribute("branding", DEFAULT_BRANDING)]
public TileBranding Branding { get; set; } = DEFAULT_BRANDING;
[NotificationXmlAttribute("contentId")]
public string ContentId { get; set; }
[NotificationXmlAttribute("displayName")]
public string DisplayName { get; set; }
[NotificationXmlAttribute("lang")]
public string Language { get; set; }
[NotificationXmlAttribute("arguments")]
public string Arguments { get; set; }
public IList<Element_TileBinding> Bindings { get; private set; } = new List<Element_TileBinding>();
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal enum TilePresentation
{
[EnumString("people")]
People,
[EnumString("photos")]
Photos,
[EnumString("contact")]
Contact
}
internal enum TileImagePlacement
{
[EnumString("inline")]
Inline,
[EnumString("background")]
Background,
[EnumString("peek")]
Peek
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Elements that can be direct children of <see cref="TileBindingContentAdaptive"/>, including (<see cref="AdaptiveText"/>, <see cref="AdaptiveImage"/>, and <see cref="AdaptiveGroup"/>).
/// </summary>
public interface ITileBindingContentAdaptiveChild
{
// Blank interface simply for compile-enforcing the child types in the list.
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Phone-only. Supported on Small, Medium, and Wide.
/// </summary>
public sealed class TileBindingContentContact : ITileBindingContent
{
/// <summary>
/// The image to display.
/// </summary>
public TileBasicImage Image { get; set; }
/// <summary>
/// A line of text that is displayed. Not displayed on Small Tile.
/// </summary>
public TileBasicText Text { get; set; }
internal TileTemplateNameV3 GetTemplateName(TileSize size)
{
return TileSizeToAdaptiveTemplateConverter.Convert(size);
}
internal void PopulateElement(Element_TileBinding binding, TileSize size)
{
binding.Presentation = TilePresentation.Contact;
// Small size doesn't display the text, so no reason to include it in the payload
if (Text != null && size != TileSize.Small)
{
binding.Children.Add(Text.ConvertToElement());
}
if (Image != null)
{
binding.Children.Add(Image.ConvertToElement());
}
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Supported on Small and Medium. Enables an iconic Tile template, where you can have an icon and badge display next to each other on the Tile, in true classic Windows Phone style. The number next to the icon is achieved through a separate badge notification.
/// </summary>
public sealed class TileBindingContentIconic : ITileBindingContent
{
/// <summary>
/// At minimum, to support both Desktop and Phone, Small and Medium tiles, provide a square aspect ratio image with a resolution of 200x200, PNG format, with transparency and no color other than white. For more info see: http://blogs.msdn.com/b/tiles_and_toasts/archive/2015/07/31/iconic-tile-template-for-windows-10.aspx
/// </summary>
public TileBasicImage Icon { get; set; }
internal TileTemplateNameV3 GetTemplateName(TileSize size)
{
switch (size)
{
case TileSize.Small:
return TileTemplateNameV3.TileSquare71x71IconWithBadge;
case TileSize.Medium:
return TileTemplateNameV3.TileSquare150x150IconWithBadge;
default:
throw new ArgumentException("The Iconic template is only supported on Small and Medium tiles.");
}
}
internal void PopulateElement(Element_TileBinding binding, TileSize size)
{
if (Icon != null)
{
var element = Icon.ConvertToElement();
element.Id = 1;
binding.Children.Add(element);
}
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// New in 1511: Supported on Medium, Wide, and Large (Desktop and Mobile).
/// Previously for RTM: Phone-only. Supported on Medium and Wide.
/// </summary>
public sealed class TileBindingContentPeople : ITileBindingContent
{
/// <summary>
/// Images that will roll around as circles.
/// </summary>
public IList<TileBasicImage> Images { get; private set; } = new List<TileBasicImage>();
internal TileTemplateNameV3 GetTemplateName(TileSize size)
{
return TileSizeToAdaptiveTemplateConverter.Convert(size);
}
internal void PopulateElement(Element_TileBinding binding, TileSize size)
{
binding.Presentation = TilePresentation.People;
foreach (var img in Images)
{
binding.Children.Add(img.ConvertToElement());
}
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Animates through a slideshow of photos. Supported on all sizes.
/// </summary>
public sealed class TileBindingContentPhotos : ITileBindingContent
{
/// <summary>
/// Up to 12 images can be provided (Mobile will only display up to 9), which will be used for the slideshow. Adding more than 12 will throw an exception.
/// </summary>
public IList<TileBasicImage> Images { get; private set; } = new LimitedList<TileBasicImage>(12);
internal TileTemplateNameV3 GetTemplateName(TileSize size)
{
return TileSizeToAdaptiveTemplateConverter.Convert(size);
}
internal void PopulateElement(Element_TileBinding binding, TileSize size)
{
binding.Presentation = TilePresentation.Photos;
foreach (var img in Images)
{
binding.Children.Add(img.ConvertToElement());
}
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A full-bleed background image that appears beneath the Tile content.
/// </summary>
public sealed class TileBackgroundImage : IBaseImage
{
private string _source;
/// <summary>
/// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size.
/// </summary>
public string Source
{
get { return _source; }
set { BaseImageHelper.SetSource(ref _source, value); }
}
/// <summary>
/// A description of the image, for users of assistive technologies.
/// </summary>
public string AlternateText { get; set; }
/// <summary>
/// Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language.
/// </summary>
public bool? AddImageQuery { get; set; }
private int? _hintOverlay;
/// <summary>
/// A black overlay on the background image. This value controls the opacity of the black overlay, with 0 being no overlay and 100 being completely black. Defaults to 20.
/// </summary>
public int? HintOverlay
{
get
{
return _hintOverlay;
}
set
{
if (value != null)
{
Element_TileBinding.CheckOverlayValue(value.Value);
}
_hintOverlay = value;
}
}
/// <summary>
/// New in 1511: Control the desired cropping of the image.
/// Previously for RTM: Did not exist, value will be ignored and background image will be displayed without any cropping.
/// </summary>
public TileBackgroundImageCrop HintCrop { get; set; }
internal Element_AdaptiveImage ConvertToElement()
{
Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this);
image.Placement = AdaptiveImagePlacement.Background;
image.Crop = GetAdaptiveImageCrop();
image.Overlay = HintOverlay;
return image;
}
private AdaptiveImageCrop GetAdaptiveImageCrop()
{
switch (HintCrop)
{
case TileBackgroundImageCrop.Circle:
return AdaptiveImageCrop.Circle;
case TileBackgroundImageCrop.None:
return AdaptiveImageCrop.None;
default:
return AdaptiveImageCrop.Default;
}
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// An image used on various special templates for the Tile.
/// </summary>
public sealed class TileBasicImage : IBaseImage
{
private string _source;
/// <summary>
/// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size.
/// </summary>
public string Source
{
get { return _source; }
set { BaseImageHelper.SetSource(ref _source, value); }
}
/// <summary>
/// A description of the image, for users of assistive technologies.
/// </summary>
public string AlternateText { get; set; }
/// <summary>
/// Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language.
/// </summary>
public bool? AddImageQuery { get; set; }
internal Element_AdaptiveImage ConvertToElement()
{
Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this);
return image;
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A text element on the Tile.
/// </summary>
public sealed class TileBasicText
{
/// <summary>
/// The text value that will be shown in the text field.
/// </summary>
public string Text { get; set; }
/// <summary>
/// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string.
/// </summary>
public string Lang { get; set; }
internal Element_AdaptiveText ConvertToElement()
{
return new Element_AdaptiveText()
{
Text = Text,
Lang = Lang
};
}
/// <summary>
/// Returns the Text property's value.
/// </summary>
/// <returns>The Text property's value.</returns>
public override string ToString()
{
return Text;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// The binding element contains the visual content for a specific Tile size.
/// </summary>
public sealed class TileBinding
{
/// <summary>
/// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides that in visual, but can be overriden by that in text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. See Remarks for when this value isn't specified.
/// </summary>
public string Language { get; set; }
/// <summary>
/// A default base URI that is combined with relative URIs in image source attributes. Defaults to null.
/// </summary>
public Uri BaseUri { get; set; }
/// <summary>
/// The form that the Tile should use to display the app's brand..
/// </summary>
public TileBranding Branding { get; set; } = Element_TileBinding.DEFAULT_BRANDING;
/// <summary>
/// Defaults to false. Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of
///
/// "www.website.com/images/hello.png"
///
/// included in the notification becomes
///
/// "www.website.com/images/hello.png?ms-scale=100&amp;ms-contrast=standard&amp;ms-lang=en-us"
/// </summary>
public bool? AddImageQuery { get; set; }
/// <summary>
/// Set to a sender-defined string that uniquely identifies the content of the notification. This prevents duplicates in the situation where a large Tile template is displaying the last three wide Tile notifications.
/// </summary>
public string ContentId { get; set; }
/// <summary>
/// An optional string to override the Tile's display name while showing this notification.
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// New in Anniversary Update: App-defined data that is passed back to your app via the TileActivatedInfo property on LaunchActivatedEventArgs when the user launches your app from the Live Tile. This allows you to know which Tile notifications your user saw when they tapped your Live Tile. On devices without the Anniversary Update, this will simply be ignored.
/// </summary>
public string Arguments { get; set; }
/// <summary>
/// The actual content to be displayed. One of <see cref="TileBindingContentAdaptive"/>, <see cref="TileBindingContentIconic"/>, <see cref="TileBindingContentContact"/>, <see cref="TileBindingContentPeople"/>, or <see cref="TileBindingContentPhotos"/>
/// </summary>
public ITileBindingContent Content { get; set; }
internal Element_TileBinding ConvertToElement(TileSize size)
{
TileTemplateNameV3 templateName = GetTemplateName(Content, size);
Element_TileBinding binding = new Element_TileBinding(templateName)
{
Language = Language,
BaseUri = BaseUri,
Branding = Branding,
AddImageQuery = AddImageQuery,
DisplayName = DisplayName,
ContentId = ContentId,
Arguments = Arguments
// LockDetailedStatus gets populated by TileVisual
};
PopulateElement(Content, binding, size);
return binding;
}
private static void PopulateElement(ITileBindingContent bindingContent, Element_TileBinding binding, TileSize size)
{
if (bindingContent == null)
{
return;
}
if (bindingContent is TileBindingContentAdaptive)
{
(bindingContent as TileBindingContentAdaptive).PopulateElement(binding, size);
}
else if (bindingContent is TileBindingContentContact)
{
(bindingContent as TileBindingContentContact).PopulateElement(binding, size);
}
else if (bindingContent is TileBindingContentIconic)
{
(bindingContent as TileBindingContentIconic).PopulateElement(binding, size);
}
else if (bindingContent is TileBindingContentPeople)
{
(bindingContent as TileBindingContentPeople).PopulateElement(binding, size);
}
else if (bindingContent is TileBindingContentPhotos)
{
(bindingContent as TileBindingContentPhotos).PopulateElement(binding, size);
}
else
{
throw new NotImplementedException("Unknown binding content type: " + bindingContent.GetType());
}
}
private static TileTemplateNameV3 GetTemplateName(ITileBindingContent bindingContent, TileSize size)
{
if (bindingContent == null)
{
return TileSizeToAdaptiveTemplateConverter.Convert(size);
}
if (bindingContent is TileBindingContentAdaptive)
{
return (bindingContent as TileBindingContentAdaptive).GetTemplateName(size);
}
if (bindingContent is TileBindingContentContact)
{
return (bindingContent as TileBindingContentContact).GetTemplateName(size);
}
if (bindingContent is TileBindingContentIconic)
{
return (bindingContent as TileBindingContentIconic).GetTemplateName(size);
}
if (bindingContent is TileBindingContentPeople)
{
return (bindingContent as TileBindingContentPeople).GetTemplateName(size);
}
if (bindingContent is TileBindingContentPhotos)
{
return (bindingContent as TileBindingContentPhotos).GetTemplateName(size);
}
throw new NotImplementedException("Unknown binding content type: " + bindingContent.GetType());
}
}
/// <summary>
/// Visual Tile content. One of <see cref="TileBindingContentAdaptive"/>, <see cref="TileBindingContentIconic"/>, <see cref="TileBindingContentPhotos"/>, <see cref="TileBindingContentPeople"/>, or <see cref="TileBindingContentContact"/>.
/// </summary>
public interface ITileBindingContent
{
}
internal enum TileTemplate
{
TileSmall,
TileMedium,
TileWide,
TileLarge
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Collections.Generic;
using Microsoft.Toolkit.Uwp.Notifications.Adaptive;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Supported on all sizes. This is the recommended way of specifying your Tile content. Adaptive Tile templates are the de-facto choice for Windows 10, and you can create a wide variety of custom Tiles through adaptive.
/// </summary>
public sealed class TileBindingContentAdaptive : ITileBindingContent
{
/// <summary>
/// <see cref="AdaptiveText"/>, <see cref="AdaptiveImage"/>, and <see cref="AdaptiveGroup"/> objects can be added as children. The children are displayed in a vertical StackPanel fashion.
/// </summary>
public IList<ITileBindingContentAdaptiveChild> Children { get; private set; } = new List<ITileBindingContentAdaptiveChild>();
/// <summary>
/// An optional background image that gets displayed behind all the Tile content, full bleed.
/// </summary>
public TileBackgroundImage BackgroundImage { get; set; }
/// <summary>
/// An optional peek image that animates in from the top of the Tile.
/// </summary>
public TilePeekImage PeekImage { get; set; }
/// <summary>
/// Controls the text stacking (vertical alignment) of the entire binding element.
/// </summary>
public TileTextStacking TextStacking { get; set; } = Element_TileBinding.DEFAULT_TEXT_STACKING;
internal TileTemplateNameV3 GetTemplateName(TileSize size)
{
return TileSizeToAdaptiveTemplateConverter.Convert(size);
}
internal void PopulateElement(Element_TileBinding binding, TileSize size)
{
// Assign properties
binding.TextStacking = TextStacking;
// Add the background image if there's one
if (BackgroundImage != null)
{
// And add it as a child
binding.Children.Add(BackgroundImage.ConvertToElement());
}
// Add the peek image if there's one
if (PeekImage != null)
{
var el = PeekImage.ConvertToElement();
binding.Children.Add(el);
}
// And then add all the children
foreach (var child in Children)
{
binding.Children.Add(ConvertToBindingChildElement(child));
}
}
private static IElement_TileBindingChild ConvertToBindingChildElement(ITileBindingContentAdaptiveChild child)
{
return (IElement_TileBindingChild)AdaptiveHelper.ConvertToElement(child);
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// The form that the Tile should use to display the app's brand.
/// </summary>
public enum TileBranding
{
/// <summary>
/// The default choice. If ShowNameOn___ is true for the Tile size being displayed, then branding will be "Name". Otherwise it will be "None".
/// </summary>
Auto,
/// <summary>
/// No branding will be displayed.
/// </summary>
[EnumString("none")]
None,
/// <summary>
/// The DisplayName will be shown.
/// </summary>
[EnumString("name")]
Name,
/// <summary>
/// Desktop-only. The Square44x44Logo will be shown. On Mobile, this will fallback to Name.
/// </summary>
[EnumString("logo")]
Logo,
/// <summary>
/// Desktop-only. Both the DisplayName and Square44x44Logo will be shown. On Mobile, this will fallback to Name.
/// </summary>
[EnumString("nameAndLogo")]
NameAndLogo
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal enum TileSize
{
Small,
Medium,
Wide,
Large
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
#if WINDOWS_UWP
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Base Tile element, which contains a single visual element.
/// </summary>
public sealed class TileContent
{
/// <summary>
/// The visual element is required.
/// </summary>
public TileVisual Visual { get; set; }
/// <summary>
/// Retrieves the notification XML content as a string, so that it can be sent with a HTTP POST in a push notification.
/// </summary>
/// <returns>The notification XML content as a string.</returns>
public string GetContent()
{
return ConvertToElement().GetContent();
}
#if WINDOWS_UWP
/// <summary>
/// Retrieves the notification XML content as a WinRT XmlDocument, so that it can be used with a local Tile notification's constructor on either <see cref="TileNotification"/> or <see cref="ScheduledTileNotification"/>.
/// </summary>
/// <returns>The notification XML content as a WinRT XmlDocument.</returns>
public XmlDocument GetXml()
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(GetContent());
return doc;
}
#endif
internal Element_Tile ConvertToElement()
{
var tile = new Element_Tile();
if (Visual != null)
{
tile.Visual = Visual.ConvertToElement();
}
return tile;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Specify the desired cropping of the image.
/// </summary>
public enum TileBackgroundImageCrop
{
/// <summary>
/// Cropping style automatically determined by renderer.
/// </summary>
Default,
/// <summary>
/// Default value. Image is not cropped.
/// </summary>
[EnumString("none")]
None,
/// <summary>
/// Image is cropped to a circle shape.
/// </summary>
[EnumString("circle")]
Circle
}
/// <summary>
/// Specify the desired cropping of the image.
/// </summary>
public enum TilePeekImageCrop
{
/// <summary>
/// Cropping style automatically determined by renderer.
/// </summary>
Default,
/// <summary>
/// Default value. Image is not cropped.
/// </summary>
[EnumString("none")]
None,
/// <summary>
/// Image is cropped to a circle shape.
/// </summary>
[EnumString("circle")]
Circle
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A peek image that animates in from the top of the Tile.
/// </summary>
public sealed class TilePeekImage : IBaseImage
{
private string _source;
/// <summary>
/// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size.
/// </summary>
public string Source
{
get { return _source; }
set { BaseImageHelper.SetSource(ref _source, value); }
}
/// <summary>
/// A description of the image, for users of assistive technologies.
/// </summary>
public string AlternateText { get; set; }
/// <summary>
/// Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language.
/// </summary>
public bool? AddImageQuery { get; set; }
private int? _hintOverlay;
/// <summary>
/// New in 1511: A black overlay on the peek image. This value controls the opacity of the black overlay, with 0 being no overlay and 100 being completely black. Defaults to 0.
/// Previously for RTM: Did not exist, value will be ignored and peek image will be displayed with 0 overlay.
/// </summary>
public int? HintOverlay
{
get
{
return _hintOverlay;
}
set
{
if (value != null)
{
Element_TileBinding.CheckOverlayValue(value.Value);
}
_hintOverlay = value;
}
}
/// <summary>
/// New in 1511: Control the desired cropping of the image.
/// Previously for RTM: Did not exist, value will be ignored and peek image will be displayed without any cropping.
/// </summary>
public TilePeekImageCrop HintCrop { get; set; }
internal Element_AdaptiveImage ConvertToElement()
{
Element_AdaptiveImage image = BaseImageHelper.CreateBaseElement(this);
image.Placement = AdaptiveImagePlacement.Peek;
image.Crop = GetAdaptiveImageCrop();
image.Overlay = HintOverlay;
return image;
}
private AdaptiveImageCrop GetAdaptiveImageCrop()
{
switch (HintCrop)
{
case TilePeekImageCrop.Circle:
return AdaptiveImageCrop.Circle;
case TilePeekImageCrop.None:
return AdaptiveImageCrop.None;
default:
return AdaptiveImageCrop.Default;
}
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal static class TileSizeToAdaptiveTemplateConverter
{
public static TileTemplateNameV3 Convert(TileSize size)
{
switch (size)
{
case TileSize.Small:
return TileTemplateNameV3.TileSmall;
case TileSize.Medium:
return TileTemplateNameV3.TileMedium;
case TileSize.Wide:
return TileTemplateNameV3.TileWide;
case TileSize.Large:
return TileTemplateNameV3.TileLarge;
default:
throw new NotImplementedException();
}
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal enum TileTemplateNameV3
{
TileMedium,
TileSmall,
TileWide,
TileLarge,
TileSquare150x150Block,
TileSquare150x150Image,
TileSquare150x150PeekImageAndText01,
TileSquare150x150PeekImageAndText02,
TileSquare150x150PeekImageAndText03,
TileSquare150x150PeekImageAndText04,
TileSquare150x150Text01,
TileSquare150x150Text02,
TileSquare150x150Text03,
TileSquare150x150Text04,
TileSquare310x310BlockAndText01,
TileSquare310x310BlockAndText02,
TileSquare310x310Image,
TileSquare310x310ImageAndText01,
TileSquare310x310ImageAndText02,
TileSquare310x310ImageAndTextOverlay01,
TileSquare310x310ImageAndTextOverlay02,
TileSquare310x310ImageAndTextOverlay03,
TileSquare310x310ImageCollection,
TileSquare310x310ImageCollectionAndText01,
TileSquare310x310ImageCollectionAndText02,
TileSquare310x310SmallImagesAndTextList01,
TileSquare310x310SmallImagesAndTextList02,
TileSquare310x310SmallImagesAndTextList03,
TileSquare310x310SmallImagesAndTextList04,
TileSquare310x310Text01,
TileSquare310x310Text02,
TileSquare310x310Text03,
TileSquare310x310Text04,
TileSquare310x310Text05,
TileSquare310x310Text06,
TileSquare310x310Text07,
TileSquare310x310Text08,
TileSquare310x310TextList01,
TileSquare310x310TextList02,
TileSquare310x310TextList03,
TileWide310x150BlockAndText01,
TileWide310x150BlockAndText02,
TileWide310x150Image,
TileWide310x150ImageAndText01,
TileWide310x150ImageAndText02,
TileWide310x150ImageCollection,
TileWide310x150PeekImage01,
TileWide310x150PeekImage02,
TileWide310x150PeekImage03,
TileWide310x150PeekImage04,
TileWide310x150PeekImage05,
TileWide310x150PeekImage06,
TileWide310x150PeekImageAndText01,
TileWide310x150PeekImageAndText02,
TileWide310x150PeekImageCollection01,
TileWide310x150PeekImageCollection02,
TileWide310x150PeekImageCollection03,
TileWide310x150PeekImageCollection04,
TileWide310x150PeekImageCollection05,
TileWide310x150PeekImageCollection06,
TileWide310x150SmallImageAndText01,
TileWide310x150SmallImageAndText02,
TileWide310x150SmallImageAndText03,
TileWide310x150SmallImageAndText04,
TileWide310x150SmallImageAndText05,
TileWide310x150Text01,
TileWide310x150Text02,
TileWide310x150Text03,
TileWide310x150Text04,
TileWide310x150Text05,
TileWide310x150Text06,
TileWide310x150Text07,
TileWide310x150Text08,
TileWide310x150Text09,
TileWide310x150Text10,
TileWide310x150Text11,
TileSquare71x71Image,
TileSquare71x71IconWithBadge,
TileSquare150x150IconWithBadge,
TileWide310x150IconWithBadgeAndText
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// TextStacking specifies the vertical alignment of content.
/// </summary>
public enum TileTextStacking
{
/// <summary>
/// Vertical align to the top.
/// </summary>
[EnumString("top")]
Top,
/// <summary>
/// Vertical align to the center.
/// </summary>
[EnumString("center")]
Center,
/// <summary>
/// Vertical align to the bottom.
/// </summary>
[EnumString("bottom")]
Bottom
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Linq;
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Contains multiple binding child elements, each of which defines a Tile.
/// </summary>
public sealed class TileVisual
{
/// <summary>
/// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string.
/// </summary>
public string Language { get; set; }
/// <summary>
/// A default base URI that is combined with relative URIs in image source attributes.
/// </summary>
public Uri BaseUri { get; set; }
/// <summary>
/// The form that the Tile should use to display the app's brand.
/// </summary>
public TileBranding Branding { get; set; } = Element_TileVisual.DEFAULT_BRANDING;
/// <summary>
/// Defaults to false. Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of
///
/// "www.website.com/images/hello.png"
///
/// included in the notification becomes
///
/// "www.website.com/images/hello.png?ms-scale=100&amp;ms-contrast=standard&amp;ms-lang=en-us"
/// </summary>
public bool? AddImageQuery { get; set; }
/// <summary>
/// Set to a sender-defined string that uniquely identifies the content of the notification. This prevents duplicates in the situation where a large Tile template is displaying the last three wide Tile notifications.
/// </summary>
public string ContentId { get; set; }
/// <summary>
/// An optional string to override the Tile's display name while showing this notification.
/// </summary>
public string DisplayName { get; set; }
/// <summary>
/// If you specify this, you must also provide a Wide Tile binding. This is the first line of text that will be displayed on the lock screen if the user has selected your Tile as their detailed status app.
/// </summary>
public string LockDetailedStatus1 { get; set; }
/// <summary>
/// If you specify this, you must also provide a Wide Tile binding. This is the second line of text that will be displayed on the lock screen if the user has selected your Tile as their detailed status app.
/// </summary>
public string LockDetailedStatus2 { get; set; }
/// <summary>
/// If you specify this, you must also provide a Wide Tile binding. This is the third line of text that will be displayed on the lock screen if the user has selected your Tile as their detailed status app.
/// </summary>
public string LockDetailedStatus3 { get; set; }
/// <summary>
/// New in Anniversary Update: App-defined data that is passed back to your app via the TileActivatedInfo property on LaunchActivatedEventArgs when the user launches your app from the Live Tile. This allows you to know which Tile notifications your user saw when they tapped your Live Tile. On devices without the Anniversary Update, this will simply be ignored.
/// </summary>
public string Arguments { get; set; }
/// <summary>
/// Provide an optional small binding to specify content for the small Tile size.
/// </summary>
public TileBinding TileSmall { get; set; }
/// <summary>
/// Provide an optional medium binding to specify content for the medium Tile size.
/// </summary>
public TileBinding TileMedium { get; set; }
/// <summary>
/// Provide an optional wide binding to specify content for the wide Tile size.
/// </summary>
public TileBinding TileWide { get; set; }
/// <summary>
/// Desktop-only. Provide an optional large binding to specify content for the large Tile size.
/// </summary>
public TileBinding TileLarge { get; set; }
/// <summary>
/// Attempts to find and re-use an existing text element inside the binding. Returns true if it could. Otherwise returns false, and the caller will have to specify the detailed status using the lock hint attribute.
/// </summary>
/// <param name="lineNumber">The lock screen line number.</param>
/// <param name="lockText">The lock screen line text.</param>
/// <param name="binding">The binding to look in for matches.</param>
/// <returns>True if could re-use existing text element, otherwise false.</returns>
private static bool TryReuseTextElementForLockDetailedText(int lineNumber, string lockText, Element_TileBinding binding)
{
if (lockText == null)
{
throw new ArgumentNullException("lockText cannot be null");
}
if (binding == null)
{
throw new ArgumentNullException("binding cannot be null");
}
// If a text element already has an id with the line number (only look at immediate children, since the lockscreen will ignore things under groups/subgroups)
Element_AdaptiveText matchingIdTextElement = binding.Children.OfType<Element_AdaptiveText>().FirstOrDefault(i => i.Id != null && i.Id.Equals(lineNumber.ToString()));
if (matchingIdTextElement != null)
{
// If the text in the element matches the lock text, then we're good, don't need to assign anything else!
if (matchingIdTextElement.Text != null && matchingIdTextElement.Text.Equals(lockText))
{
return true;
}
// Otherwise, we need to specify the lock text in the hint attribute, so we return false
return false;
}
// Otherwise no text elements use that ID, so we could assign one if we find a text element that doesn't have an ID assigned and matches the lock text
Element_AdaptiveText matchingTextTextElement = binding.Children.OfType<Element_AdaptiveText>().FirstOrDefault(i => i.Id == null && i.Text != null && i.Text.Equals(lockText));
// If we found text that matched, we'll assign the id so it gets re-used for lock!
if (matchingTextTextElement != null)
{
matchingTextTextElement.Id = lineNumber;
return true;
}
// Otherwise we'll need to specify lock text in hint attribute, so return false
return false;
}
internal Element_TileVisual ConvertToElement()
{
var visual = new Element_TileVisual()
{
Language = Language,
BaseUri = BaseUri,
Branding = Branding,
AddImageQuery = AddImageQuery,
ContentId = ContentId,
DisplayName = DisplayName,
Arguments = Arguments
};
if (TileSmall != null)
{
visual.Bindings.Add(TileSmall.ConvertToElement(TileSize.Small));
}
if (TileMedium != null)
{
visual.Bindings.Add(TileMedium.ConvertToElement(TileSize.Medium));
}
if (TileWide != null)
{
Element_TileBinding wideBindingElement = TileWide.ConvertToElement(TileSize.Wide);
// If lock detailed status was specified, add them
if (LockDetailedStatus1 != null)
{
// If we can't reuse existing text element, we'll have to use the hints
if (!TryReuseTextElementForLockDetailedText(1, LockDetailedStatus1, wideBindingElement))
{
wideBindingElement.LockDetailedStatus1 = LockDetailedStatus1;
}
}
if (LockDetailedStatus2 != null)
{
if (!TryReuseTextElementForLockDetailedText(2, LockDetailedStatus2, wideBindingElement))
{
wideBindingElement.LockDetailedStatus2 = LockDetailedStatus2;
}
}
if (LockDetailedStatus3 != null)
{
if (!TryReuseTextElementForLockDetailedText(3, LockDetailedStatus3, wideBindingElement))
{
wideBindingElement.LockDetailedStatus3 = LockDetailedStatus3;
}
}
visual.Bindings.Add(wideBindingElement);
}
// Otherwise if they specified lock values, throw an exception since lock values require wide
else if (HasLockDetailedStatusValues())
{
throw new Exception("To provide lock detailed status text strings, you must also provide a TileWide binding. Either provide a TileWide binding, or leave the detailed status values null.");
}
if (TileLarge != null)
{
visual.Bindings.Add(TileLarge.ConvertToElement(TileSize.Large));
}
// TODO: If a BaseUri wasn't provided, we can potentially optimize the payload size by calculating the best BaseUri
return visual;
}
private bool HasLockDetailedStatusValues()
{
return LockDetailedStatus1 != null && LockDetailedStatus2 != null && LockDetailedStatus3 != null;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("toast")]
internal sealed class Element_Toast : BaseElement, IElement_ToastActivatable
{
internal const ToastScenario DEFAULT_SCENARIO = ToastScenario.Default;
internal const Element_ToastActivationType DEFAULT_ACTIVATION_TYPE = Element_ToastActivationType.Foreground;
internal const ToastDuration DEFAULT_DURATION = ToastDuration.Short;
[NotificationXmlAttribute("activationType", DEFAULT_ACTIVATION_TYPE)]
public Element_ToastActivationType ActivationType { get; set; } = DEFAULT_ACTIVATION_TYPE;
[NotificationXmlAttribute("protocolActivationTargetApplicationPfn")]
public string ProtocolActivationTargetApplicationPfn { get; set; }
[NotificationXmlAttribute("afterActivationBehavior", ToastAfterActivationBehavior.Default)]
public ToastAfterActivationBehavior AfterActivationBehavior
{
get
{
return ToastAfterActivationBehavior.Default;
}
set
{
if (value != ToastAfterActivationBehavior.Default)
{
throw new InvalidOperationException("AfterActivationBehavior on ToastContent only supports the Default value.");
}
}
}
[NotificationXmlAttribute("duration", DEFAULT_DURATION)]
public ToastDuration Duration { get; set; } = DEFAULT_DURATION;
[NotificationXmlAttribute("launch")]
public string Launch { get; set; }
[NotificationXmlAttribute("scenario", DEFAULT_SCENARIO)]
public ToastScenario Scenario { get; set; } = DEFAULT_SCENARIO;
[NotificationXmlAttribute("displayTimestamp")]
public DateTimeOffset? DisplayTimestamp { get; set; }
public Element_ToastVisual Visual { get; set; }
public Element_ToastAudio Audio { get; set; }
public Element_ToastActions Actions { get; set; }
public Element_ToastHeader Header { get; set; }
public static Element_ToastActivationType ConvertActivationType(ToastActivationType publicType)
{
switch (publicType)
{
case ToastActivationType.Foreground:
return Element_ToastActivationType.Foreground;
case ToastActivationType.Background:
return Element_ToastActivationType.Background;
case ToastActivationType.Protocol:
return Element_ToastActivationType.Protocol;
default:
throw new NotImplementedException();
}
}
}
/// <summary>
/// The amount of time the Toast should display.
/// </summary>
public enum ToastDuration
{
/// <summary>
/// Default value. Toast appears for a short while and then goes into Action Center.
/// </summary>
Short,
/// <summary>
/// Toast stays on-screen for longer, and then goes into Action Center.
/// </summary>
[EnumString("long")]
Long
}
/// <summary>
/// Specifies the scenario, controlling behaviors about the Toast.
/// </summary>
public enum ToastScenario
{
/// <summary>
/// The normal Toast behavior. The Toast appears for a short duration, and then automatically dismisses into Action Center.
/// </summary>
Default,
/// <summary>
/// Causes the Toast to stay on-screen and expanded until the user takes action. Also causes a looping alarm sound to be selected by default.
/// </summary>
[EnumString("alarm")]
Alarm,
/// <summary>
/// Causes the Toast to stay on-screen and expanded until the user takes action.
/// </summary>
[EnumString("reminder")]
Reminder,
/// <summary>
/// Causes the Toast to stay on-screen and expanded until the user takes action (on Mobile this expands to full screen). Also causes a looping incoming call sound to be selected by default.
/// </summary>
[EnumString("incomingCall")]
IncomingCall
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("action")]
internal sealed class Element_ToastAction : IElement_ToastActionsChild, IElement_ToastActivatable
{
internal const Element_ToastActivationType DEFAULT_ACTIVATION_TYPE = Element_ToastActivationType.Foreground;
internal const ToastAfterActivationBehavior DEFAULT_AFTER_ACTIVATION_BEHAVIOR = ToastAfterActivationBehavior.Default;
internal const Element_ToastActionPlacement DEFAULT_PLACEMENT = Element_ToastActionPlacement.Inline;
/// <summary>
/// The text to be displayed on the button.
/// </summary>
[NotificationXmlAttribute("content")]
public string Content { get; set; }
/// <summary>
/// The arguments attribute describes the app-defined data that the app can later retrieve once it is activated from user taking this action.
/// </summary>
[NotificationXmlAttribute("arguments")]
public string Arguments { get; set; }
[NotificationXmlAttribute("activationType", DEFAULT_ACTIVATION_TYPE)]
public Element_ToastActivationType ActivationType { get; set; } = DEFAULT_ACTIVATION_TYPE;
[NotificationXmlAttribute("protocolActivationTargetApplicationPfn")]
public string ProtocolActivationTargetApplicationPfn { get; set; }
[NotificationXmlAttribute("afterActivationBehavior", DEFAULT_AFTER_ACTIVATION_BEHAVIOR)]
public ToastAfterActivationBehavior AfterActivationBehavior { get; set; } = DEFAULT_AFTER_ACTIVATION_BEHAVIOR;
/// <summary>
/// imageUri is optional and is used to provide an image icon for this action to display inside the button alone with the text content.
/// </summary>
[NotificationXmlAttribute("imageUri")]
public string ImageUri { get; set; }
/// <summary>
/// This is specifically used for the quick reply scenario.
/// </summary>
[NotificationXmlAttribute("hint-inputId")]
public string InputId { get; set; }
[NotificationXmlAttribute("placement", DEFAULT_PLACEMENT)]
public Element_ToastActionPlacement Placement { get; set; } = DEFAULT_PLACEMENT;
}
internal enum Element_ToastActionPlacement
{
Inline,
[EnumString("contextMenu")]
ContextMenu
}
internal enum Element_ToastActivationType
{
/// <summary>
/// Default value. Your foreground app is launched.
/// </summary>
Foreground,
/// <summary>
/// Your corresponding background task (assuming you set everything up) is triggered, and you can execute code in the background (like sending the user's quick reply message) without interrupting the user.
/// </summary>
[EnumString("background")]
Background,
/// <summary>
/// Launch a different app using protocol activation.
/// </summary>
[EnumString("protocol")]
Protocol,
/// <summary>
/// System handles the activation.
/// </summary>
[EnumString("system")]
System
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("actions")]
internal sealed class Element_ToastActions
{
internal const ToastSystemCommand DEFAULT_SYSTEM_COMMAND = ToastSystemCommand.None;
[NotificationXmlAttribute("hint-systemCommands", DEFAULT_SYSTEM_COMMAND)]
public ToastSystemCommand SystemCommands { get; set; } = ToastSystemCommand.None;
public IList<IElement_ToastActionsChild> Children { get; private set; } = new List<IElement_ToastActionsChild>();
}
internal interface IElement_ToastActionsChild
{
}
internal enum ToastSystemCommand
{
None,
SnoozeAndDismiss
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("audio")]
internal sealed class Element_ToastAudio
{
internal const bool DEFAULT_LOOP = false;
internal const bool DEFAULT_SILENT = false;
/// <summary>
/// The media file to play in place of the default sound. This can either be a ms-winsoundevent value, or a custom ms-appx:/// or ms-appdata:/// file, or null for the default sound.
/// </summary>
[NotificationXmlAttribute("src")]
public Uri Src { get; set; }
[NotificationXmlAttribute("loop", DEFAULT_LOOP)]
public bool Loop { get; set; } = DEFAULT_LOOP;
/// <summary>
/// True to mute the sound; false to allow the Toast notification sound to play.
/// </summary>
[NotificationXmlAttribute("silent", DEFAULT_SILENT)]
public bool Silent { get; set; } = DEFAULT_SILENT;
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("binding")]
internal sealed class Element_ToastBinding
{
public Element_ToastBinding(ToastTemplateType template)
{
Template = template;
}
[NotificationXmlAttribute("template")]
public ToastTemplateType Template { get; private set; }
/// <summary>
/// Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language; for instance, a value of
///
/// "www.website.com/images/hello.png"
///
/// included in the notification becomes
///
/// "www.website.com/images/hello.png?ms-scale=100&amp;ms-contrast=standard&amp;ms-lang=en-us"
/// </summary>
[NotificationXmlAttribute("addImageQuery")]
public bool? AddImageQuery { get; set; }
/// <summary>
/// A default base URI that is combined with relative URIs in image source attributes.
/// </summary>
[NotificationXmlAttribute("baseUri")]
public Uri BaseUri { get; set; }
/// <summary>
/// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides that in visual, but can be overriden by that in text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string. See Remarks for when this value isn't specified.
/// </summary>
[NotificationXmlAttribute("lang")]
public string Language { get; set; }
public IList<IElement_ToastBindingChild> Children { get; private set; } = new List<IElement_ToastBindingChild>();
}
internal interface IElement_ToastBindingChild
{
}
internal enum ToastTemplateType
{
ToastGeneric,
ToastImageAndText01,
ToastImageAndText02,
ToastImageAndText03,
ToastImageAndText04,
ToastText01,
ToastText02,
ToastText03,
ToastText04
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("header")]
internal sealed class Element_ToastHeader : IElement_ToastActivatable
{
[NotificationXmlAttribute("id")]
public string Id { get; set; }
[NotificationXmlAttribute("title")]
public string Title { get; set; }
[NotificationXmlAttribute("arguments")]
public string Arguments { get; set; }
[NotificationXmlAttribute("activationType", Element_ToastActivationType.Foreground)]
public Element_ToastActivationType ActivationType { get; set; } = Element_ToastActivationType.Foreground;
[NotificationXmlAttribute("protocolActivationTargetApplicationPfn")]
public string ProtocolActivationTargetApplicationPfn { get; set; }
[NotificationXmlAttribute("afterActivationBehavior", ToastAfterActivationBehavior.Default)]
public ToastAfterActivationBehavior AfterActivationBehavior
{
get
{
return ToastAfterActivationBehavior.Default;
}
set
{
if (value != ToastAfterActivationBehavior.Default)
{
throw new InvalidOperationException("AfterActivationBehavior on ToastHeader only supports the Default value.");
}
}
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("image")]
internal sealed class Element_ToastImage : IElement_ToastBindingChild
{
internal const ToastImagePlacement DEFAULT_PLACEMENT = ToastImagePlacement.Inline;
internal const bool DEFAULT_ADD_IMAGE_QUERY = false;
internal const ToastImageCrop DEFAULT_CROP = ToastImageCrop.None;
[NotificationXmlAttribute("src")]
public string Src { get; set; }
[NotificationXmlAttribute("alt")]
public string Alt { get; set; }
[NotificationXmlAttribute("addImageQuery", DEFAULT_ADD_IMAGE_QUERY)]
public bool AddImageQuery { get; set; } = DEFAULT_ADD_IMAGE_QUERY;
[NotificationXmlAttribute("placement", DEFAULT_PLACEMENT)]
public ToastImagePlacement Placement { get; set; } = DEFAULT_PLACEMENT;
[NotificationXmlAttribute("hint-crop", DEFAULT_CROP)]
public ToastImageCrop Crop { get; set; } = DEFAULT_CROP;
}
/// <summary>
/// Specify the desired cropping of the image.
/// </summary>
public enum ToastImageCrop
{
/// <summary>
/// Default value. Image is not cropped.
/// </summary>
None,
/// <summary>
/// Image is cropped to a circle shape.
/// </summary>
[EnumString("circle")]
Circle
}
internal enum ToastImagePlacement
{
Inline,
[EnumString("appLogoOverride")]
AppLogoOverride,
[EnumString("hero")]
Hero
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("input")]
internal sealed class Element_ToastInput : IElement_ToastActionsChild
{
/// <summary>
/// The id attribute is required and is for developers to retrieve user inputs once the app is activated (in the foreground or background).
/// </summary>
[NotificationXmlAttribute("id")]
public string Id { get; set; }
[NotificationXmlAttribute("type")]
public ToastInputType Type { get; set; }
/// <summary>
/// The title attribute is optional and is for developers to specify a title for the input for shells to render when there is affordance.
/// </summary>
[NotificationXmlAttribute("title")]
public string Title { get; set; }
/// <summary>
/// The placeholderContent attribute is optional and is the grey-out hint text for text input type. This attribute is ignored when the input type is not �text�.
/// </summary>
[NotificationXmlAttribute("placeHolderContent")]
public string PlaceholderContent { get; set; }
/// <summary>
/// The defaultInput attribute is optional and it allows developer to provide a default input value.
/// </summary>
[NotificationXmlAttribute("defaultInput")]
public string DefaultInput { get; set; }
public IList<IElement_ToastInputChild> Children { get; private set; } = new List<IElement_ToastInputChild>();
}
internal interface IElement_ToastInputChild
{
}
internal enum ToastInputType
{
[EnumString("text")]
Text,
[EnumString("selection")]
Selection
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("selection")]
internal sealed class Element_ToastSelection : IElement_ToastInputChild
{
/// <summary>
/// The id attribute is required and it is for apps to retrieve back the user selected input after the app is activated.
/// </summary>
[NotificationXmlAttribute("id")]
public string Id { get; set; }
/// <summary>
/// The text to display for this selection element.
/// </summary>
[NotificationXmlAttribute("content")]
public string Content { get; set; }
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("text")]
internal sealed class Element_ToastText : IElement_ToastBindingChild
{
internal const ToastTextPlacement DEFAULT_PLACEMENT = ToastTextPlacement.Inline;
[NotificationXmlContent]
public string Text { get; set; }
[NotificationXmlAttribute("lang")]
public string Lang { get; set; }
[NotificationXmlAttribute("placement", DEFAULT_PLACEMENT)]
public ToastTextPlacement Placement { get; set; } = DEFAULT_PLACEMENT;
}
internal enum ToastTextPlacement
{
Inline,
[EnumString("attribution")]
Attribution
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
[NotificationXmlElement("visual")]
internal sealed class Element_ToastVisual
{
internal const bool DEFAULT_ADD_IMAGE_QUERY = false;
[NotificationXmlAttribute("addImageQuery")]
public bool? AddImageQuery { get; set; }
[NotificationXmlAttribute("baseUri")]
public Uri BaseUri { get; set; }
[NotificationXmlAttribute("lang")]
public string Language { get; set; }
[NotificationXmlAttribute("version")]
public int? Version { get; set; }
public IList<Element_ToastBinding> Bindings { get; private set; } = new List<Element_ToastBinding>();
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
internal interface IElement_ToastActivatable
{
Element_ToastActivationType ActivationType { get; set; }
string ProtocolActivationTargetApplicationPfn { get; set; }
ToastAfterActivationBehavior AfterActivationBehavior { get; set; }
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Actions to display on a Toast notification. One of <see cref="ToastActionsCustom"/> or <see cref="ToastActionsSnoozeAndDismiss"/>.
/// </summary>
public interface IToastActions
{
/// <summary>
/// New in Anniversary Update: Custom context menu items, providing additional actions when the user right clicks the Toast notification.
/// </summary>
IList<ToastContextMenuItem> ContextMenuItems { get; }
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Elements that can be direct children of <see cref="ToastBindingGeneric"/>, including (<see cref="AdaptiveText"/>, <see cref="AdaptiveImage"/>, and <see cref="AdaptiveGroup"/>).
/// </summary>
public interface IToastBindingGenericChild
{
// Blank interface simply for compile-enforcing the child types in the list.
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// One of <see cref="ToastButton"/>, <see cref="ToastButtonSnooze"/>, or <see cref="ToastButtonDismiss"/>.
/// </summary>
public interface IToastButton
{
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// An input element on a Toast notification. One of <see cref="ToastTextBox"/> or <see cref="ToastSelectionBox"/>.
/// </summary>
public interface IToastInput
{
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Create your own custom actions, using controls like <see cref="ToastButton"/>, <see cref="ToastTextBox"/>, and <see cref="ToastSelectionBox"/>.
/// </summary>
public sealed class ToastActionsCustom : IToastActions
{
/// <summary>
/// Inputs like <see cref="ToastTextBox"/> and <see cref="ToastSelectionBox"/> can be added to the Toast. Only up to 5 inputs can be added; after that, an exception is thrown.
/// </summary>
public IList<IToastInput> Inputs { get; private set; } = new LimitedList<IToastInput>(5);
/// <summary>
/// Buttons are displayed after all the inputs (or adjacent to inputs if used as quick reply buttons). Only up to 5 buttons can be added (or fewer if you are also including context menu items). After that, an exception is thrown. You can add <see cref="ToastButton"/>, <see cref="ToastButtonSnooze"/>, or <see cref="ToastButtonDismiss"/>
/// </summary>
public IList<IToastButton> Buttons { get; private set; } = new LimitedList<IToastButton>(5);
/// <summary>
/// New in Anniversary Update: Custom context menu items, providing additional actions when the user right clicks the Toast notification. You can only have up to 5 buttons and context menu items *combined*. Thus, if you have one context menu item, you can only have four buttons, etc.
/// </summary>
public IList<ToastContextMenuItem> ContextMenuItems { get; private set; } = new List<ToastContextMenuItem>();
internal Element_ToastActions ConvertToElement()
{
if (Buttons.Count + ContextMenuItems.Count > 5)
{
throw new InvalidOperationException("You have too many buttons/context menu items. You can only have up to 5 total.");
}
var el = new Element_ToastActions();
foreach (var input in Inputs)
{
el.Children.Add(ConvertToInputElement(input));
}
foreach (var button in this.Buttons)
{
el.Children.Add(ConvertToActionElement(button));
}
foreach (var item in ContextMenuItems)
{
el.Children.Add(item.ConvertToElement());
}
return el;
}
private static Element_ToastAction ConvertToActionElement(IToastButton button)
{
if (button is ToastButton)
{
return (button as ToastButton).ConvertToElement();
}
if (button is ToastButtonDismiss)
{
return (button as ToastButtonDismiss).ConvertToElement();
}
if (button is ToastButtonSnooze)
{
return (button as ToastButtonSnooze).ConvertToElement();
}
throw new NotImplementedException("Unknown button child: " + button.GetType());
}
private static Element_ToastInput ConvertToInputElement(IToastInput input)
{
if (input is ToastTextBox)
{
return (input as ToastTextBox).ConvertToElement();
}
if (input is ToastSelectionBox)
{
return (input as ToastSelectionBox).ConvertToElement();
}
throw new NotImplementedException("Unknown input child: " + input.GetType());
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Automatically constructs a selection box for snooze intervals, and snooze/dismiss buttons, all automatically localized, and snoozing logic is automatically handled by the system.
/// </summary>
public sealed class ToastActionsSnoozeAndDismiss : IToastActions
{
/// <summary>
/// New in Anniversary Update: Custom context menu items, providing additional actions when the user right clicks the Toast notification. You can only have up to 5 items.
/// </summary>
public IList<ToastContextMenuItem> ContextMenuItems { get; private set; } = new List<ToastContextMenuItem>();
internal Element_ToastActions ConvertToElement()
{
if (ContextMenuItems.Count > 5)
{
throw new InvalidOperationException("You have too many context menu items. You can only have up to 5.");
}
var el = new Element_ToastActions()
{
SystemCommands = ToastSystemCommand.SnoozeAndDismiss
};
foreach (var item in ContextMenuItems)
{
el.Children.Add(item.ConvertToElement());
}
return el;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// New in Creators Update: Additional options relating to activation.
/// </summary>
public sealed class ToastActivationOptions
{
/// <summary>
/// If you are using <see cref="ToastActivationType.Protocol"/>, you can optionally specify the target PFN, so that regardless of whether multiple apps are registered to handle the same protocol uri, your desired app will always be launched.
/// </summary>
public string ProtocolActivationTargetApplicationPfn { get; set; }
/// <summary>
/// Not supported on Windows: Specifies the behavior that the toast should use when the user invokes this action. Note that this option only works on <see cref="ToastButton"/> and <see cref="ToastContextMenuItem"/>.
/// </summary>
[Obsolete("Windows does not support AfterActivationBehavior. If a future version of Windows supports this, we will undeprecate the property when support is added.")]
public ToastAfterActivationBehavior AfterActivationBehavior { get; set; } = ToastAfterActivationBehavior.Default;
internal void PopulateElement(IElement_ToastActivatable el)
{
// If protocol PFN is specified but protocol activation isn't used, throw exception
if (ProtocolActivationTargetApplicationPfn != null && el.ActivationType != Element_ToastActivationType.Protocol)
{
throw new InvalidOperationException($"You cannot specify {nameof(ProtocolActivationTargetApplicationPfn)} without using ActivationType of Protocol.");
}
el.ProtocolActivationTargetApplicationPfn = ProtocolActivationTargetApplicationPfn;
#pragma warning disable 618
el.AfterActivationBehavior = AfterActivationBehavior;
#pragma warning restore 618
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Specify audio to be played when the Toast notification is received.
/// </summary>
public sealed class ToastAudio
{
/// <summary>
/// The media file to play in place of the default sound.
/// </summary>
public Uri Src { get; set; }
/// <summary>
/// Set to true if the sound should repeat as long as the Toast is shown; false to play only once (default).
/// </summary>
public bool Loop { get; set; } = Element_ToastAudio.DEFAULT_LOOP;
/// <summary>
/// True to mute the sound; false to allow the Toast notification sound to play (default).
/// </summary>
public bool Silent { get; set; } = Element_ToastAudio.DEFAULT_SILENT;
internal Element_ToastAudio ConvertToElement()
{
return new Element_ToastAudio()
{
Src = Src,
Loop = Loop,
Silent = Silent
};
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
using Microsoft.Toolkit.Uwp.Notifications.Adaptive;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Generic Toast binding, where you provide text, images, and other visual elements for your Toast notification.
/// </summary>
public sealed class ToastBindingGeneric
{
/// <summary>
/// The contents of the body of the Toast, which can include <see cref="AdaptiveText"/>, <see cref="AdaptiveImage"/>, and <see cref="AdaptiveGroup"/> (added in Anniversary Update). Also, <see cref="AdaptiveText"/> elements must come before any other elements. If an <see cref="AdaptiveText"/> element is placed after any other element, an exception will be thrown when you try to retrieve the Toast XML content. And finally, certain <see cref="AdaptiveText"/> properties like HintStyle aren't supported on the root children text elements, and only work inside an <see cref="AdaptiveGroup"/>. If you use <see cref="AdaptiveGroup"/> on devices without the Anniversary Update, the group content will simply be dropped.
/// </summary>
public IList<IToastBindingGenericChild> Children { get; private set; } = new List<IToastBindingGenericChild>();
/// <summary>
/// An optional override of the logo displayed on the Toast notification.
/// </summary>
public ToastGenericAppLogo AppLogoOverride { get; set; }
/// <summary>
/// New in Anniversary Update: An optional hero image (a visually impactful image displayed on the Toast notification). On devices without the Anniversary Update, the hero image will simply be ignored.
/// </summary>
public ToastGenericHeroImage HeroImage { get; set; }
/// <summary>
/// New in Anniversary Update: An optional text element that is displayed as attribution text. On devices without the Anniversary Update, this text will appear as if it's another <see cref="AdaptiveText"/> element at the end of your Children list.
/// </summary>
public ToastGenericAttributionText Attribution { get; set; }
/// <summary>
/// The target locale of the XML payload, specified as BCP-47 language tags such as "en-US" or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string.
/// </summary>
public string Language { get; set; }
/// <summary>
/// A default base URI that is combined with relative URIs in image source attributes.
/// </summary>
public Uri BaseUri { get; set; }
/// <summary>
/// Set to "true" to allow Windows to append a query string to the image URI supplied in the Toast notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language.
/// </summary>
public bool? AddImageQuery { get; set; }
internal Element_ToastBinding ConvertToElement()
{
Element_ToastBinding binding = new Element_ToastBinding(ToastTemplateType.ToastGeneric)
{
BaseUri = BaseUri,
AddImageQuery = AddImageQuery,
Language = Language
};
// Add children
foreach (var child in Children)
{
var el = (IElement_ToastBindingChild)AdaptiveHelper.ConvertToElement(child);
binding.Children.Add(el);
}
// Add attribution
if (Attribution != null)
{
binding.Children.Add(Attribution.ConvertToElement());
}
// If there's hero, add it
if (HeroImage != null)
{
binding.Children.Add(HeroImage.ConvertToElement());
}
// If there's app logo, add it
if (AppLogoOverride != null)
{
binding.Children.Add(AppLogoOverride.ConvertToElement());
}
return binding;
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A button that the user can click on a Toast notification.
/// </summary>
public sealed class ToastButton : IToastButton
{
/// <summary>
/// Initializes a Toast button with the required properties.
/// </summary>
/// <param name="content">The text to display on the button.</param>
/// <param name="arguments">App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button.</param>
public ToastButton(string content, string arguments)
{
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
if (arguments == null)
{
throw new ArgumentNullException(nameof(arguments));
}
Content = content;
Arguments = arguments;
}
/// <summary>
/// Required. The text to display on the button.
/// </summary>
public string Content { get; private set; }
/// <summary>
/// Required. App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the button.
/// </summary>
public string Arguments { get; private set; }
/// <summary>
/// Controls what type of activation this button will use when clicked. Defaults to Foreground.
/// </summary>
public ToastActivationType ActivationType { get; set; } = ToastActivationType.Foreground;
/// <summary>
/// New in Creators Update: Additional options relating to activation of the toast button.
/// </summary>
public ToastActivationOptions ActivationOptions { get; set; }
/// <summary>
/// An optional image icon for the button to display (required for buttons adjacent to inputs like quick reply).
/// </summary>
public string ImageUri { get; set; }
/// <summary>
/// Specify the ID of an existing <see cref="ToastTextBox"/> in order to have this button display to the right of the input, achieving a quick reply scenario.
/// </summary>
public string TextBoxId { get; set; }
internal Element_ToastAction ConvertToElement()
{
var el = new Element_ToastAction()
{
Content = Content,
Arguments = Arguments,
ActivationType = Element_Toast.ConvertActivationType(ActivationType),
ImageUri = ImageUri,
InputId = TextBoxId
};
ActivationOptions?.PopulateElement(el);
return el;
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A button that, when clicked, is interpreted as a "dismiss" by the system, and the Toast is dismissed just like if the user swiped the Toast away.
/// </summary>
public sealed class ToastButtonDismiss : IToastButton
{
/// <summary>
/// Custom text displayed on the button that overrides the default localized "Dismiss" text.
/// </summary>
public string CustomContent { get; private set; }
/// <summary>
/// An optional image icon for the button to display.
/// </summary>
public string ImageUri { get; set; }
/// <summary>
/// Initializes a system-handled dismiss button that displays localized "Dismiss" text on the button.
/// </summary>
public ToastButtonDismiss()
{
}
/// <summary>
/// Constructs a system-handled dismiss button that displays your text on the button.
/// </summary>
/// <param name="customContent">The text you want displayed on the button.</param>
public ToastButtonDismiss(string customContent)
{
if (customContent == null)
{
throw new ArgumentNullException(nameof(customContent));
}
CustomContent = customContent;
}
internal Element_ToastAction ConvertToElement()
{
return new Element_ToastAction()
{
Content = this.CustomContent == null ? string.Empty : this.CustomContent, // If not using custom content, we need to provide empty string, otherwise Toast doesn't get displayed
Arguments = "dismiss",
ActivationType = Element_ToastActivationType.System,
ImageUri = ImageUri
// InputId is useless since dismiss button can't be placed to the right of text box (shell doesn't display it)
};
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A system-handled snooze button that automatically handles snoozing of a Toast notification.
/// </summary>
public sealed class ToastButtonSnooze : IToastButton
{
/// <summary>
/// Custom text displayed on the button that overrides the default localized "Snooze" text.
/// </summary>
public string CustomContent { get; private set; }
/// <summary>
/// An optional image icon for the button to display.
/// </summary>
public string ImageUri { get; set; }
/// <summary>
/// Optionally specify the ID of an existing <see cref="ToastSelectionBox"/> in order to allow the user to pick a custom snooze time. The ID's of the <see cref="ToastSelectionBoxItem"/>s inside the selection box must represent the snooze interval in minutes. For example, if the user selects an item that has an ID of "120", then the notification will be snoozed for 2 hours. When the user clicks this button, if you specified a SelectionBoxId, the system will parse the ID of the selected item and snooze by that amount of minutes. If you didn't specify a SelectionBoxId, the system will snooze by the default system snooze time.
/// </summary>
public string SelectionBoxId { get; set; }
/// <summary>
/// Initializes a system-handled snooze button that displays localized "Snooze" text on the button and automatically handles snoozing.
/// </summary>
public ToastButtonSnooze()
{
}
/// <summary>
/// Initializes a system-handled snooze button that displays your text on the button and automatically handles snoozing.
/// </summary>
/// <param name="customContent">The text you want displayed on the button.</param>
public ToastButtonSnooze(string customContent)
{
if (customContent == null)
{
throw new ArgumentNullException(nameof(customContent));
}
CustomContent = customContent;
}
internal Element_ToastAction ConvertToElement()
{
return new Element_ToastAction()
{
Content = CustomContent ?? string.Empty, // If not using custom content, we need to provide empty string, otherwise Toast doesn't get displayed
Arguments = "snooze",
ActivationType = Element_ToastActivationType.System,
InputId = SelectionBoxId,
ImageUri = ImageUri
};
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Decides the type of activation that will be used when the user interacts with the Toast notification.
/// </summary>
public enum ToastActivationType
{
/// <summary>
/// Default value. Your foreground app is launched.
/// </summary>
Foreground,
/// <summary>
/// Your corresponding background task (assuming you set everything up) is triggered, and you can execute code in the background (like sending the user's quick reply message) without interrupting the user.
/// </summary>
[EnumString("background")]
Background,
/// <summary>
/// Launch a different app using protocol activation.
/// </summary>
[EnumString("protocol")]
Protocol
}
/// <summary>
/// Specifies the behavior that the toast should use when the user takes action on the toast.
/// </summary>
public enum ToastAfterActivationBehavior
{
/// <summary>
/// Default behavior. The toast will be dismissed when the user takes action on the toast.
/// </summary>
Default,
/// <summary>
/// After the user clicks a button on your toast, the notification will remain present, in a "pending update" visual state. You should immediately update your toast from a background task so that the user does not see this "pending update" visual state for too long.
/// </summary>
[EnumString("pendingUpdate")]
PendingUpdate
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
#if WINDOWS_UWP
using Windows.Data.Xml.Dom;
using Windows.UI.Notifications;
#endif
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Base Toast element, which contains at least a visual element.
/// </summary>
public sealed class ToastContent : INotificationContent
{
/// <summary>
/// The visual element is required.
/// </summary>
public ToastVisual Visual { get; set; }
/// <summary>
/// Specify custom audio options.
/// </summary>
public ToastAudio Audio { get; set; }
/// <summary>
/// Optionally create custom actions with buttons and inputs (using <see cref="ToastActionsCustom"/>) or optionally use the system-default snooze/dismiss controls (with <see cref="ToastActionsSnoozeAndDismiss"/>).
/// </summary>
public IToastActions Actions { get; set; }
/// <summary>
/// New in Creators Update: Gets or sets an optional header for the toast notification.
/// </summary>
public ToastHeader Header { get; set; }
/// <summary>
/// Specify the scenario, to make the Toast behave like an alarm, reminder, or more.
/// </summary>
public ToastScenario Scenario { get; set; }
/// <summary>
/// The amount of time the Toast should display. You typically should use the Scenario attribute instead, which impacts how long a Toast stays on screen.
/// </summary>
public ToastDuration Duration { get; set; }
/// <summary>
/// A string that is passed to the application when it is activated by the Toast. The format and contents of this string are defined by the app for its own use. When the user taps or clicks the Toast to launch its associated app, the launch string provides the context to the app that allows it to show the user a view relevant to the Toast content, rather than launching in its default way.
/// </summary>
public string Launch { get; set; }
/// <summary>
/// Specifies what activation type will be used when the user clicks the body of this Toast.
/// </summary>
public ToastActivationType ActivationType { get; set; }
/// <summary>
/// New in Creators Update: Additional options relating to activation of the toast notification.
/// </summary>
public ToastActivationOptions ActivationOptions { get; set; }
/// <summary>
/// New in Creators Update: An optional custom time to use for the notification's timestamp, visible within Action Center. If provided, this date/time will be used on the notification instead of the date/time that the notification was received.
/// </summary>
public DateTimeOffset? DisplayTimestamp { get; set; }
/// <summary>
/// Retrieves the notification XML content as a string, so that it can be sent with a HTTP POST in a push notification.
/// </summary>
/// <returns>The notification XML content as a string.</returns>
public string GetContent()
{
return ConvertToElement().GetContent();
}
#if WINDOWS_UWP
/// <summary>
/// Retrieves the notification XML content as a WinRT XmlDocument, so that it can be used with a local Toast notification's constructor on either <see cref="ToastNotification"/> or <see cref="ScheduledToastNotification"/>.
/// </summary>
/// <returns>The notification XML content as a WinRT XmlDocument.</returns>
public XmlDocument GetXml()
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(GetContent());
return doc;
}
#endif
internal Element_Toast ConvertToElement()
{
if (ActivationOptions != null)
{
#pragma warning disable 618
if (ActivationOptions.AfterActivationBehavior != ToastAfterActivationBehavior.Default)
#pragma warning restore 618
{
throw new InvalidOperationException("ToastContent does not support a custom AfterActivationBehavior. Please ensure ActivationOptions.AfterActivationBehavior is set to Default.");
}
}
DateTimeOffset? strippedDisplayTimestamp = null;
if (DisplayTimestamp != null)
{
// We need to make sure we don't include more than 3 decimal points on seconds
// The Millisecond value itself is limited to 3 decimal points, thus by doing the following
// we bypass the more granular value that can come from Ticks and ensure we only have 3 decimals at most.
var val = DisplayTimestamp.Value;
strippedDisplayTimestamp = new DateTimeOffset(val.Year, val.Month, val.Day, val.Hour, val.Minute, val.Second, val.Millisecond, val.Offset);
}
var toast = new Element_Toast()
{
ActivationType = Element_Toast.ConvertActivationType(ActivationType),
Duration = Duration,
Launch = Launch,
Scenario = Scenario,
DisplayTimestamp = strippedDisplayTimestamp
};
ActivationOptions?.PopulateElement(toast);
if (Visual != null)
{
toast.Visual = Visual.ConvertToElement();
}
if (Audio != null)
{
toast.Audio = Audio.ConvertToElement();
}
if (Actions != null)
{
toast.Actions = ConvertToActionsElement(Actions);
}
if (Header != null)
{
toast.Header = Header.ConvertToElement();
}
return toast;
}
private static Element_ToastActions ConvertToActionsElement(IToastActions actions)
{
if (actions is ToastActionsCustom)
{
return (actions as ToastActionsCustom).ConvertToElement();
}
if (actions is ToastActionsSnoozeAndDismiss)
{
return (actions as ToastActionsSnoozeAndDismiss).ConvertToElement();
}
throw new NotImplementedException("Unknown actions type: " + actions.GetType());
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A Toast context menu item.
/// </summary>
public sealed class ToastContextMenuItem
{
/// <summary>
/// Initializes a Toast context menu item with the required properties.
/// </summary>
/// <param name="content">The text to display on the menu item.</param>
/// <param name="arguments">App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the menu item.</param>
public ToastContextMenuItem(string content, string arguments)
{
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
if (arguments == null)
{
throw new ArgumentNullException(nameof(arguments));
}
Content = content;
Arguments = arguments;
}
/// <summary>
/// Required. The text to display on the menu item.
/// </summary>
public string Content { get; private set; }
/// <summary>
/// Required. App-defined string of arguments that the app can later retrieve once it is activated when the user clicks the menu item.
/// </summary>
public string Arguments { get; private set; }
/// <summary>
/// Controls what type of activation this menu item will use when clicked. Defaults to Foreground.
/// </summary>
public ToastActivationType ActivationType { get; set; } = ToastActivationType.Foreground;
/// <summary>
/// New in Creators Update: Additional options relating to activation of the toast context menu item.
/// </summary>
public ToastActivationOptions ActivationOptions { get; set; }
internal Element_ToastAction ConvertToElement()
{
var el = new Element_ToastAction
{
Content = Content,
Arguments = Arguments,
ActivationType = Element_Toast.ConvertActivationType(ActivationType),
Placement = Element_ToastActionPlacement.ContextMenu
};
ActivationOptions?.PopulateElement(el);
return el;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// The logo that is displayed on your Toast notification.
/// </summary>
public sealed class ToastGenericAppLogo : IBaseImage
{
/// <summary>
/// Initializes a logo that is displayed on your Toast notification.
/// </summary>
public ToastGenericAppLogo()
{
}
private string _source;
/// <summary>
/// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size.
/// </summary>
public string Source
{
get { return _source; }
set { BaseImageHelper.SetSource(ref _source, value); }
}
/// <summary>
/// A description of the image, for users of assistive technologies.
/// </summary>
public string AlternateText { get; set; }
/// <summary>
/// Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language.
/// </summary>
public bool? AddImageQuery { get; set; }
/// <summary>
/// Specify how you would like the image to be cropped.
/// </summary>
public ToastGenericAppLogoCrop HintCrop { get; set; }
internal Element_AdaptiveImage ConvertToElement()
{
Element_AdaptiveImage el = BaseImageHelper.CreateBaseElement(this);
el.Placement = AdaptiveImagePlacement.AppLogoOverride;
el.Crop = GetAdaptiveImageCrop();
return el;
}
private AdaptiveImageCrop GetAdaptiveImageCrop()
{
switch (HintCrop)
{
case ToastGenericAppLogoCrop.Circle:
return AdaptiveImageCrop.Circle;
case ToastGenericAppLogoCrop.None:
return AdaptiveImageCrop.None;
default:
return AdaptiveImageCrop.Default;
}
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Specify the desired cropping of the image.
/// </summary>
public enum ToastGenericAppLogoCrop
{
/// <summary>
/// Cropping uses the default behavior of the renderer.
/// </summary>
Default,
/// <summary>
/// Image is not cropped.
/// </summary>
[EnumString("none")]
None,
/// <summary>
/// Image is cropped to a circle shape.
/// </summary>
[EnumString("circle")]
Circle
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Defines an attribution text element to be displayed on the Toast notification.
/// </summary>
public sealed class ToastGenericAttributionText : IBaseText
{
/// <summary>
/// Initializes an attribution text element to be displayed on the Toast notification.
/// </summary>
public ToastGenericAttributionText()
{
}
/// <summary>
/// The text to display.
/// </summary>
public string Text { get; set; }
/// <summary>
/// The target locale of the XML payload, specified as a BCP-47 language tags such as "en-US" or "fr-FR". The locale specified here overrides any other specified locale, such as that in binding or visual. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string.
/// </summary>
public string Language { get; set; }
internal Element_AdaptiveText ConvertToElement()
{
var el = BaseTextHelper.CreateBaseElement(this);
el.Placement = AdaptiveTextPlacement.Attribution;
return el;
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using Microsoft.Toolkit.Uwp.Notifications.Adaptive.Elements;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A hero image for the Toast notification.
/// </summary>
public sealed class ToastGenericHeroImage : IBaseImage
{
/// <summary>
/// Initializes a hero image for the Toast notification.
/// </summary>
public ToastGenericHeroImage()
{
}
private string _source;
/// <summary>
/// The URI of the image. Can be from your application package, application data, or the internet. Internet images must be less than 200 KB in size.
/// </summary>
public string Source
{
get { return _source; }
set { BaseImageHelper.SetSource(ref _source, value); }
}
/// <summary>
/// A description of the image, for users of assistive technologies.
/// </summary>
public string AlternateText { get; set; }
/// <summary>
/// Set to true to allow Windows to append a query string to the image URI supplied in the Tile notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language.
/// </summary>
public bool? AddImageQuery { get; set; }
internal Element_AdaptiveImage ConvertToElement()
{
Element_AdaptiveImage el = BaseImageHelper.CreateBaseElement(this);
el.Placement = AdaptiveImagePlacement.Hero;
return el;
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Defines a visual header for the toast notification.
/// </summary>
public sealed class ToastHeader
{
/// <summary>
/// Constructs a toast header with all the required properties.
/// </summary>
/// <param name="id">A developer-created identifier that uniquely identifies this header. If two notifications have the same header id, they will be displayed underneath the same header in Action Center.</param>
/// <param name="title">A title for the header.</param>
/// <param name="arguments">A developer-defined string of arguments that is returned to the app when the user clicks this header.</param>
public ToastHeader(string id, string title, string arguments)
{
Id = id;
Title = title;
Arguments = arguments;
}
private string _id;
/// <summary>
/// Gets or sets a developer-created identifier that uniquely identifies this header. If two notifications have the same header id, they will be displayed underneath the same header in Action Center. Cannot be null.
/// </summary>
public string Id
{
get { return _id; }
set { ArgumentValidator.SetProperty(ref _id, value, nameof(Id), ArgumentValidatorOptions.NotNull); }
}
private string _title;
/// <summary>
/// Gets or sets a title for the header. Cannot be null.
/// </summary>
public string Title
{
get { return _title; }
set { ArgumentValidator.SetProperty(ref _title, value, nameof(Title), ArgumentValidatorOptions.NotNull); }
}
private string _arguments;
/// <summary>
/// Gets or sets a developer-defined string of arguments that is returned to the app when the user clicks this header. Cannot be null.
/// </summary>
public string Arguments
{
get { return _arguments; }
set { ArgumentValidator.SetProperty(ref _arguments, value, nameof(Arguments), ArgumentValidatorOptions.NotNull); }
}
private ToastActivationType _activationType = ToastActivationType.Foreground;
/// <summary>
/// Gets or sets the type of activation this header will use when clicked. Defaults to Foreground. Note that only Foreground and Protocol are supported.
/// </summary>
public ToastActivationType ActivationType
{
get
{
return _activationType;
}
set
{
switch (value)
{
case ToastActivationType.Foreground:
case ToastActivationType.Protocol:
_activationType = value;
break;
default:
throw new ArgumentException($"ActivationType of {value} is not supported on ToastHeader.");
}
}
}
/// <summary>
/// New in Creators Update: Additional options relating to activation of the toast header.
/// </summary>
public ToastActivationOptions ActivationOptions { get; set; }
internal Element_ToastHeader ConvertToElement()
{
if (ActivationOptions != null)
{
#pragma warning disable 618
if (ActivationOptions.AfterActivationBehavior != ToastAfterActivationBehavior.Default)
#pragma warning restore 618
{
throw new InvalidOperationException("ToastHeader does not support a custom AfterActivationBehavior. Please ensure ActivationOptions.AfterActivationBehavior is set to Default.");
}
}
var el = new Element_ToastHeader()
{
Id = Id,
Title = Title,
Arguments = Arguments,
ActivationType = Element_Toast.ConvertActivationType(ActivationType)
};
ActivationOptions?.PopulateElement(el);
return el;
}
}
}
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
using System.Collections.Generic;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A selection box control, which lets users pick from a dropdown list of options.
/// </summary>
public sealed class ToastSelectionBox : IToastInput
{
/// <summary>
/// Initializes a new Toast SelectionBox input control with the required elements.
/// </summary>
/// <param name="id">Developer-provided ID that the developer uses later to retrieve input when the Toast is interacted with.</param>
public ToastSelectionBox(string id)
{
if (id == null)
{
throw new ArgumentNullException(nameof(id));
}
Id = id;
}
/// <summary>
/// The ID property is required, and is used so that developers can retrieve user input once the app is activated.
/// </summary>
public string Id { get; private set; }
/// <summary>
/// Title text to display above the SelectionBox.
/// </summary>
public string Title { get; set; }
/// <summary>
/// This controls which item is selected by default, and refers to the Id property of <see cref="ToastSelectionBoxItem"/>. If you do not provide this, the default selection will be empty (user sees nothing).
/// </summary>
public string DefaultSelectionBoxItemId { get; set; }
/// <summary>
/// The selection items that the user can pick from in this SelectionBox. Only 5 items can be added.
/// </summary>
public IList<ToastSelectionBoxItem> Items { get; private set; } = new LimitedList<ToastSelectionBoxItem>(5);
internal Element_ToastInput ConvertToElement()
{
var input = new Element_ToastInput()
{
Type = ToastInputType.Selection,
Id = Id,
DefaultInput = DefaultSelectionBoxItemId,
Title = Title
};
foreach (var item in Items)
{
input.Children.Add(item.ConvertToElement());
}
return input;
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A selection box item (an item that the user can select from the drop down list).
/// </summary>
public sealed class ToastSelectionBoxItem
{
/// <summary>
/// Constructs a new Toast SelectionBoxItem with the required elements.
/// </summary>
/// <param name="id">Developer-provided ID that the developer uses later to retrieve input when the Toast is interacted with.</param>
/// <param name="content">String that is displayed on the selection item. This is what the user sees.</param>
public ToastSelectionBoxItem(string id, string content)
{
if (id == null)
{
throw new ArgumentNullException(nameof(id));
}
if (content == null)
{
throw new ArgumentNullException(nameof(content));
}
Id = id;
Content = content;
}
/// <summary>
/// The ID property is required, and is used so that developers can retrieve user input once the app is activated.
/// </summary>
public string Id { get; private set; }
/// <summary>
/// The Content property is required, and is a string that is displayed on the selection item.
/// </summary>
public string Content { get; private set; }
internal Element_ToastSelection ConvertToElement()
{
return new Element_ToastSelection()
{
Id = Id,
Content = Content
};
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// A text box control on the Toast that a user can type text into.
/// </summary>
public sealed class ToastTextBox : IToastInput
{
/// <summary>
/// Initializes a new Toast TextBox input control with the required elements.
/// </summary>
/// <param name="id">Developer-provided ID that the developer uses later to retrieve input when the Toast is interacted with.</param>
public ToastTextBox(string id)
{
if (id == null)
{
throw new ArgumentNullException(nameof(id));
}
Id = id;
}
/// <summary>
/// The ID property is required, and is used so that developers can retrieve user input once the app is activated.
/// </summary>
public string Id { get; private set; }
/// <summary>
/// Title text to display above the text box.
/// </summary>
public string Title { get; set; }
/// <summary>
/// Placeholder text to be displayed on the text box when the user hasn't typed any text yet.
/// </summary>
public string PlaceholderContent { get; set; }
/// <summary>
/// The initial text to place in the text box. Leave this null for a blank text box.
/// </summary>
public string DefaultInput { get; set; }
internal Element_ToastInput ConvertToElement()
{
return new Element_ToastInput()
{
Id = Id,
Type = ToastInputType.Text,
DefaultInput = DefaultInput,
PlaceholderContent = PlaceholderContent,
Title = Title
};
}
}
}
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System;
namespace Microsoft.Toolkit.Uwp.Notifications
{
/// <summary>
/// Defines the visual aspects of a Toast notification.
/// </summary>
public sealed class ToastVisual
{
/// <summary>
/// The target locale of the XML payload, specified as BCP-47 language tags such as "en-US" or "fr-FR". This locale is overridden by any locale specified in binding or text. If this value is a literal string, this attribute defaults to the user's UI language. If this value is a string reference, this attribute defaults to the locale chosen by Windows Runtime in resolving the string.
/// </summary>
public string Language { get; set; }
/// <summary>
/// A default base URI that is combined with relative URIs in image source attributes.
/// </summary>
public Uri BaseUri { get; set; }
/// <summary>
/// Set to "true" to allow Windows to append a query string to the image URI supplied in the Toast notification. Use this attribute if your server hosts images and can handle query strings, either by retrieving an image variant based on the query strings or by ignoring the query string and returning the image as specified without the query string. This query string specifies scale, contrast setting, and language.
/// </summary>
public bool? AddImageQuery { get; set; }
/// <summary>
/// The generic Toast binding, which can be rendered on all devices. This binding is required and cannot be null.
/// </summary>
public ToastBindingGeneric BindingGeneric { get; set; }
internal Element_ToastVisual ConvertToElement()
{
var visual = new Element_ToastVisual()
{
Language = Language,
BaseUri = BaseUri,
AddImageQuery = AddImageQuery
};
Element_ToastBinding binding = BindingGeneric.ConvertToElement();
// TODO: If a BaseUri wasn't provided, we can potentially optimize the payload size by calculating the best BaseUri
visual.Bindings.Add(binding);
return visual;
}
}
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{FB381278-F4AD-4703-A12A-C43EE0B231BD}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Microsoft.Toolkit.Uwp.Notifications</RootNamespace>
<AssemblyName>Microsoft.Toolkit.Uwp.Notifications</AssemblyName>
<DefaultLanguage>en-US</DefaultLanguage>
<TargetPlatformIdentifier>UAP</TargetPlatformIdentifier>
<TargetPlatformVersion>10.0.15063.0</TargetPlatformVersion>
<TargetPlatformMinVersion>10.0.10240.0</TargetPlatformMinVersion>
<MinimumVisualStudioVersion>14</MinimumVisualStudioVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<CodeAnalysisRuleSet>microsoft.toolkit.uwp.notifications.uwp.ruleset</CodeAnalysisRuleSet>
<DocumentationFile>bin\Debug\Microsoft.Toolkit.Uwp.Notifications.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP;ANNIVERSARY_UPDATE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Microsoft.Toolkit.Uwp.Notifications.xml</DocumentationFile>
<CodeAnalysisRuleSet>microsoft.toolkit.uwp.notifications.uwp.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Publish|AnyCPU'">
<OutputPath>bin\Publish\</OutputPath>
<DefineConstants>TRACE;NETFX_CORE;WINDOWS_UWP;ANNIVERSARY_UPDATE</DefineConstants>
<DocumentationFile>bin\Release\Microsoft.Toolkit.Uwp.Notifications.xml</DocumentationFile>
<Optimize>true</Optimize>
<NoStdLib>true</NoStdLib>
<DebugType>pdbonly</DebugType>
<PlatformTarget>AnyCPU</PlatformTarget>
<UseVSHostingProcess>false</UseVSHostingProcess>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>microsoft.toolkit.uwp.notifications.uwp.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<ItemGroup>
<!-- A reference to the entire .Net Framework and Windows SDK are automatically included -->
<None Include="Microsoft.Toolkit.Uwp.Notifications.UWP.ruleset" />
<None Include="project.json" />
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs" />
<EmbeddedResource Include="Properties\Microsoft.Toolkit.Uwp.Notifications.rd.xml">
<SubType>Designer</SubType>
</EmbeddedResource>
</ItemGroup>
<Import Project="..\Microsoft.Toolkit.Uwp.Notifications.Shared\Microsoft.Toolkit.Uwp.Notifications.Shared.projitems" Label="Shared" />
<PropertyGroup Condition=" '$(VisualStudioVersion)' == '' or '$(VisualStudioVersion)' &lt; '14.0' ">
<VisualStudioVersion>14.0</VisualStudioVersion>
</PropertyGroup>
<Import Project="$(MSBuildExtensionsPath)\Microsoft\WindowsXaml\v$(VisualStudioVersion)\Microsoft.Windows.UI.Xaml.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<RuleSet Name="Microsoft Managed Recommended Rules" Description="These rules focus on the most critical problems in your code, including potential security holes, application crashes, and other important logic and design errors. It is recommended to include this rule set in any custom rule set you create for your projects." ToolsVersion="14.0">
<Localization ResourceAssembly="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.dll" ResourceBaseName="Microsoft.VisualStudio.CodeAnalysis.RuleSets.Strings.Localized">
<Name Resource="MinimumRecommendedRules_Name" />
<Description Resource="MinimumRecommendedRules_Description" />
</Localization>
<Rules AnalyzerId="Microsoft.Analyzers.ManagedCodeAnalysis" RuleNamespace="Microsoft.Rules.Managed">
<Rule Id="CA1001" Action="Warning" />
<Rule Id="CA1009" Action="Warning" />
<Rule Id="CA1016" Action="Warning" />
<Rule Id="CA1033" Action="Warning" />
<Rule Id="CA1049" Action="Warning" />
<Rule Id="CA1060" Action="Warning" />
<Rule Id="CA1061" Action="Warning" />
<Rule Id="CA1063" Action="Warning" />
<Rule Id="CA1065" Action="Warning" />
<Rule Id="CA1301" Action="Warning" />
<Rule Id="CA1400" Action="Warning" />
<Rule Id="CA1401" Action="Warning" />
<Rule Id="CA1403" Action="Warning" />
<Rule Id="CA1404" Action="Warning" />
<Rule Id="CA1405" Action="Warning" />
<Rule Id="CA1410" Action="Warning" />
<Rule Id="CA1415" Action="Warning" />
<Rule Id="CA1821" Action="Warning" />
<Rule Id="CA1900" Action="Warning" />
<Rule Id="CA1901" Action="Warning" />
<Rule Id="CA2002" Action="Warning" />
<Rule Id="CA2100" Action="Warning" />
<Rule Id="CA2101" Action="Warning" />
<Rule Id="CA2108" Action="Warning" />
<Rule Id="CA2111" Action="Warning" />
<Rule Id="CA2112" Action="Warning" />
<Rule Id="CA2114" Action="Warning" />
<Rule Id="CA2116" Action="Warning" />
<Rule Id="CA2117" Action="Warning" />
<Rule Id="CA2122" Action="Warning" />
<Rule Id="CA2123" Action="Warning" />
<Rule Id="CA2124" Action="Warning" />
<Rule Id="CA2126" Action="Warning" />
<Rule Id="CA2131" Action="Warning" />
<Rule Id="CA2132" Action="Warning" />
<Rule Id="CA2133" Action="Warning" />
<Rule Id="CA2134" Action="Warning" />
<Rule Id="CA2137" Action="Warning" />
<Rule Id="CA2138" Action="Warning" />
<Rule Id="CA2140" Action="Warning" />
<Rule Id="CA2141" Action="Warning" />
<Rule Id="CA2146" Action="Warning" />
<Rule Id="CA2147" Action="Warning" />
<Rule Id="CA2149" Action="Warning" />
<Rule Id="CA2200" Action="Warning" />
<Rule Id="CA2202" Action="Warning" />
<Rule Id="CA2207" Action="Warning" />
<Rule Id="CA2212" Action="Warning" />
<Rule Id="CA2213" Action="Warning" />
<Rule Id="CA2214" Action="Warning" />
<Rule Id="CA2216" Action="Warning" />
<Rule Id="CA2220" Action="Warning" />
<Rule Id="CA2229" Action="Warning" />
<Rule Id="CA2231" Action="Warning" />
<Rule Id="CA2232" Action="Warning" />
<Rule Id="CA2235" Action="Warning" />
<Rule Id="CA2236" Action="Warning" />
<Rule Id="CA2237" Action="Warning" />
<Rule Id="CA2238" Action="Warning" />
<Rule Id="CA2240" Action="Warning" />
<Rule Id="CA2241" Action="Warning" />
<Rule Id="CA2242" Action="Warning" />
</Rules>
<Rules AnalyzerId="Microsoft.CodeAnalysis.CSharp" RuleNamespace="Microsoft.CodeAnalysis.CSharp">
<Rule Id="CS1574" Action="None" />
</Rules>
<Rules AnalyzerId="StyleCop.Analyzers" RuleNamespace="StyleCop.Analyzers">
<Rule Id="SA1101" Action="None" />
<Rule Id="SA1118" Action="None" />
<Rule Id="SA1200" Action="None" />
<Rule Id="SA1201" Action="None" />
<Rule Id="SA1202" Action="None" />
<Rule Id="SA1309" Action="None" />
<Rule Id="SA1310" Action="None" />
<Rule Id="SA1602" Action="None" />
<Rule Id="SA1623" Action="None" />
<Rule Id="SA1633" Action="None" />
<Rule Id="SA1642" Action="None" />
<Rule Id="SA1600" Action="None" />
</Rules>
</RuleSet>
\ No newline at end of file
// ******************************************************************
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THE CODE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
// IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
// DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH
// THE CODE OR THE USE OR OTHER DEALINGS IN THE CODE.
// ******************************************************************
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Microsoft.Toolkit.Uwp.Notifications")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("Microsoft.Toolkit.Uwp.Notifications")]
[assembly: AssemblyCopyright("Copyright © 2016")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
[assembly: ComVisible(false)]
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<Directives xmlns="http://schemas.microsoft.com/netfx/2013/01/metadata">
<Library Name="Microsoft.Toolkit.Uwp.Notifications">
</Library>
</Directives>
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Debug\Microsoft.Toolkit.Uwp.Notifications.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Debug\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Debug\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Debug\Microsoft.Toolkit.Uwp.Notifications.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\priconfig.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\priconfig.xml.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\layout.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\layout.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\resources.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\resources.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\pri.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\pri.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\qualifiers.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\qualifiers.txt.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\MultipleQualifiersPerDimensionFound.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Debug\Microsoft.Toolkit.Uwp.Notifications.UWP.csprojResolveAssemblyReference.cache
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Debug\layout.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Debug\resources.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESJSON" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Debug\pri.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Debug" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Debug\layout.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Debug\resources.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESJSON" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Debug\pri.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Debug" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Publish\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Publish\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Publish\Microsoft.Toolkit.Uwp.Notifications.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Publish\Microsoft.Toolkit.Uwp.Notifications.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\Microsoft.Toolkit.Uwp.Notifications.UWP.csprojResolveAssemblyReference.cache
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\priconfig.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\priconfig.xml.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\layout.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\layout.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\resources.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\resources.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\pri.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\pri.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\qualifiers.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\qualifiers.txt.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Publish\MultipleQualifiersPerDimensionFound.txt
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Publish\layout.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Publish\resources.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESJSON" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Publish\pri.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Publish" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Publish\layout.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Publish\resources.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESJSON" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Publish\pri.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Publish" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Release\Microsoft.Toolkit.Uwp.Notifications.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Release\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Release\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\bin\Release\Microsoft.Toolkit.Uwp.Notifications.pri
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\Microsoft.Toolkit.Uwp.Notifications.dll
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\Microsoft.Toolkit.Uwp.Notifications.pdb
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\priconfig.xml
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\priconfig.xml.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\layout.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\layout.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\resources.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\resources.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\pri.resfiles
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\pri.resfiles.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\qualifiers.txt
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\qualifiers.txt.intermediate
Z:\Documents\github\cordova-plugin-local-notifications\src\windows\Microsoft.Toolkit.Uwp.Notifications.UWP\obj\Release\MultipleQualifiersPerDimensionFound.txt
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Release\layout.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Release\resources.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESJSON" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Release\pri.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<resources targetOsVersion="10.0.0" majorVersion="1">
<index root="\" startIndexAt="obj\Release\layout.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Release\resources.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESW" convertDotsToSlashes="true" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESJSON" initialPath="Microsoft.Toolkit.Uwp.Notifications" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="\" startIndexAt="obj\Release\pri.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="PRI" />
<indexer-config type="RESFILES" qualifierDelimiter="." />
</index>
<index root="obj\Release" startIndexAt="embed.resfiles">
<default>
<qualifier name="Language" value="en-US" />
<qualifier name="Contrast" value="standard" />
<qualifier name="Scale" value="200" />
<qualifier name="HomeRegion" value="001" />
<qualifier name="TargetSize" value="256" />
<qualifier name="LayoutDirection" value="LTR" />
<qualifier name="DXFeatureLevel" value="DX9" />
<qualifier name="Configuration" value="" />
<qualifier name="AlternateForm" value="" />
<qualifier name="Platform" value="UAP" />
</default>
<indexer-config type="RESFILES" qualifierDelimiter="." />
<indexer-config type="EMBEDFILES" />
</index>
</resources>
\ No newline at end of file
{
"dependencies": {
"Microsoft.NETCore.UniversalWindowsPlatform": "5.2.3",
"StyleCop.Analyzers": "1.0.0"
},
"frameworks": {
"uap10.0": {}
},
"runtimes": {
"win10-arm": {},
"win10-arm-aot": {},
"win10-x86": {},
"win10-x86-aot": {},
"win10-x64": {},
"win10-x64-aot": {}
}
}
\ No newline at end of file
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
var exec = require('cordova/exec');
/**
* Check permission to show notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.hasPermission = function (callback, scope) {
var fn = this.createCallbackFn(callback, scope);
exec(fn, null, 'LocalNotification', 'check', []);
};
/**
* Request permission to show notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.requestPermission = function (callback, scope) {
var fn = this.createCallbackFn(callback, scope);
exec(fn, null, 'LocalNotification', 'request', []);
};
/**
* Schedule notifications.
*
* @param [ Array ] notifications The notifications to schedule.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
* @param [ Object ] args Optional flags how to schedule.
*
* @return [ Void ]
*/
exports.schedule = function (msgs, callback, scope, args) {
var fn = function (granted) {
if (!granted) return;
var notifications = Array.isArray(msgs) ? msgs : [msgs];
for (var i = 0; i < notifications.length; i++) {
var notification = notifications[i];
this.mergeWithDefaults(notification);
this.convertProperties(notification);
}
this.exec('schedule', notifications, callback, scope);
};
if (args && args.skipPermission) {
fn.call(this, true);
} else {
this.requestPermission(fn, this);
}
};
// /**
// * Update existing notifications specified by IDs in options.
// *
// * @param {Object} notifications
// * The notification properties to update
// * @param {Function} callback
// * A function to be called after the notification has been updated
// * @param {Object?} scope
// * The scope for the callback function
// * @param {Object?} args
// * skipPermission:true schedules the notifications immediatly without
// * registering or checking for permission
// */
// exports.update = function (msgs, callback, scope, args) {
// var fn = function(granted) {
// if (!granted) return;
// var notifications = Array.isArray(msgs) ? msgs : [msgs];
// for (var i = 0; i < notifications.length; i++) {
// var notification = notifications[i];
// this.convertProperties(notification);
// }
// this.exec('update', notifications, callback, scope);
// };
// if (args && args.skipPermission) {
// fn.call(this, true);
// } else {
// this.registerPermission(fn, this);
// }
// };
/**
* Clear the specified notifications by id.
*
* @param [ Array<Int> ] ids The IDs of the notifications.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.clear = function (ids, callback, scope) {
ids = Array.isArray(ids) ? ids : [ids];
ids = this.convertIds(ids);
this.exec('clear', ids, callback, scope);
};
/**
* Clear all triggered notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.clearAll = function (callback, scope) {
this.exec('clearAll', null, callback, scope);
};
/**
* Clear the specified notifications by id.
*
* @param [ Array<Int> ] ids The IDs of the notifications.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.cancel = function (ids, callback, scope) {
ids = Array.isArray(ids) ? ids : [ids];
ids = this.convertIds(ids);
this.exec('cancel', ids, callback, scope);
};
/**
* Cancel all scheduled notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.cancelAll = function (callback, scope) {
this.exec('cancelAll', null, callback, scope);
};
/**
* Check if a notification is present.
*
* @param [ Int ] id The ID of the notification.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.isPresent = function (id, callback, scope) {
var fn = this.createCallbackFn(callback, scope);
this.getType(id, function (type) {
fn(type != 'unknown');
});
};
/**
* Check if a notification has a given type.
*
* @param [ Int ] id The ID of the notification.
* @param [ String ] type The type of the notification.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.hasType = function (id, type, callback, scope) {
var fn = this.createCallbackFn(callback, scope);
this.getType(id, function (type2) {
fn(type == type2);
});
};
/**
* Get the type (triggered, scheduled) for the notification.
*
* @param [ Int ] id The ID of the notification.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getType = function (id, callback, scope) {
this.exec('type', id, callback, scope);
};
/**
* List of all notification ids.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getIds = function (callback, scope) {
this.exec('ids', null, callback, scope);
};
/**
* List of all scheduled notification IDs.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getScheduledIds = function (callback, scope) {
this.exec('scheduledIds', null, callback, scope);
};
/**
* List of all triggered notification IDs.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getTriggeredIds = function (callback, scope) {
this.exec('triggeredIds', null, callback, scope);
};
/**
* List of local notifications specified by id.
* If called without IDs, all notification will be returned.
*
* @param [ Array<Int> ] ids The IDs of the notifications.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.get = function () {
var args = Array.apply(null, arguments);
if (typeof args[0] == 'function') {
args.unshift([]);
}
var ids = args[0],
callback = args[1],
scope = args[2];
if (!Array.isArray(ids)) {
this.exec('notification', Number(ids), callback, scope);
return;
}
ids = this.convertIds(ids);
this.exec('notifications', ids, callback, scope);
};
/**
* List for all notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getAll = function (callback, scope) {
this.exec('notifications', null, callback, scope);
};
/**
* List of all scheduled notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*/
exports.getScheduled = function (callback, scope) {
this.exec('scheduledNotifications', null, callback, scope);
};
/**
* List of all triggered notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*/
exports.getTriggered = function (callback, scope) {
this.exec('triggeredNotifications', null, callback, scope);
};
/**
* Register an group of actions by id.
*
* @param [ String ] id The Id of the group.
* @param [ Array] actions The action config settings.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.addActionGroup = function (id, actions, callback, scope) {
var config = { actionGroupId: id, actions: actions };
this.exec('registerCategory', config, callback, scope);
};
/**
* The (platform specific) default settings.
*
* @return [ Object ]
*/
exports.getDefaults = function () {
return this._defaults;
};
/**
* Overwrite default settings.
*
* @param [ Object ] newDefaults New default values.
*
* @return [ Void ]
*/
exports.setDefaults = function (newDefaults) {
var defaults = this.getDefaults();
for (var key in defaults) {
if (newDefaults.hasOwnProperty(key)) {
defaults[key] = newDefaults[key];
}
}
};
/**
* Register callback for given event.
*
* @param [ String ] event The name of the event.
* @param [ Function ] callback The function to be exec as callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.on = function (event, callback, scope) {
if (typeof callback !== "function")
return;
if (!this._listener[event]) {
this._listener[event] = [];
}
var item = [callback, scope || window];
this._listener[event].push(item);
};
/**
* Unregister callback for given event.
*
* @param [ String ] event The name of the event.
* @param [ Function ] callback The function to be exec as callback.
*
* @return [ Void ]
*/
exports.un = function (event, callback) {
var listener = this._listener[event];
if (!listener)
return;
for (var i = 0; i < listener.length; i++) {
var fn = listener[i][0];
if (fn == callback) {
listener.splice(i, 1);
break;
}
}
};
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
var exec = require('cordova/exec'),
channel = require('cordova/channel');
// Default values
exports._defaults = {
id: 0,
text: '',
title: '',
sound: 'res://platform_default',
trigger: 'date',
badge: undefined,
data: undefined,
every: undefined,
at: undefined,
actions: [],
actionGroupId: undefined,
attachments: []
};
// Listener
exports._listener = {};
/**
* Merge platform specific properties into the default ones.
*
* @return [ Void ]
*/
exports.applyPlatformSpecificOptions = function () {
var defaults = this._defaults;
switch (device.platform) {
case 'Android':
defaults.icon = 'res://ic_popup_reminder';
defaults.smallIcon = undefined;
defaults.ongoing = false;
defaults.autoClear = true;
defaults.led = undefined;
defaults.color = undefined;
break;
case 'iOS':
defaults.region = undefined;
defaults.radius = undefined;
defaults.notifyOnEntry = true;
defaults.notifyOnExit = false;
break;
}
};
/**
* Merge custom properties with the default values.
*
* @param [ Object ] options Set of custom values.
*
* @retrun [ Object ]
*/
exports.mergeWithDefaults = function (options) {
var defaults = this.getDefaults();
options.at = this.getValueFor(options, 'at', 'firstAt', 'date');
options.text = this.getValueFor(options, 'text', 'message');
options.data = this.getValueFor(options, 'data', 'json');
if (defaults.hasOwnProperty('autoClear')) {
options.autoClear = this.getValueFor(options, 'autoClear', 'autoCancel');
}
if (options.autoClear !== true && options.ongoing) {
options.autoClear = false;
}
if (options.at === undefined || options.at === null) {
options.at = new Date();
}
for (var key in defaults) {
if (options[key] === null || options[key] === undefined) {
if (options.hasOwnProperty(key) && ['data','sound'].indexOf(key) > -1) {
options[key] = undefined;
} else {
options[key] = defaults[key];
}
}
}
for (key in options) {
if (!defaults.hasOwnProperty(key)) {
delete options[key];
console.warn('Unknown property: ' + key);
}
}
return options;
};
/**
* Convert the passed values to their required type.
*
* @param [ Object ] options Properties to convert for.
*
* @return [ Object ] The converted property list
*/
exports.convertProperties = function (options) {
if (options.id) {
if (isNaN(options.id)) {
options.id = this.getDefaults().id;
console.warn('Id is not a number: ' + options.id);
} else {
options.id = Number(options.id);
}
}
if (options.title) {
options.title = options.title.toString();
}
if (options.text) {
options.text = options.text.toString();
}
if (options.badge) {
if (isNaN(options.badge)) {
options.badge = this.getDefaults().badge;
console.warn('Badge number is not a number: ' + options.id);
} else {
options.badge = Number(options.badge);
}
}
if (options.at) {
if (typeof options.at == 'object') {
options.at = options.at.getTime();
}
options.at = Math.round(options.at/1000);
}
if (typeof options.data == 'object') {
options.data = JSON.stringify(options.data);
}
if (options.actions) {
this.convertActions(options);
}
return options;
};
/**
* Convert the passed values to their required type, modifying them
* directly for Android and passing the converted list back for iOS.
*
* @param [ Map ] options Set of custom values.
*
* @return [ Map ] Interaction object with category & actions.
*/
exports.convertActions = function (options) {
if (!options.actions)
return null;
var actions = [];
for (var i = 0, action; i < options.actions.length; i++) {
action = options.actions[i];
if (!action.id) {
console.warn(
'Action with title ' + action.title + ' has no id and will not be added.');
continue;
}
action.id = action.id.toString();
actions.push(action);
}
options.category = (options.category || 'DEFAULT_GROUP').toString();
options.actions = actions;
};
/**
* Create a callback function to get executed within a specific scope.
*
* @param [ Function ] fn The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Function ]
*/
exports.createCallbackFn = function (fn, scope) {
if (typeof fn != 'function')
return;
return function () {
fn.apply(scope || this, arguments);
};
};
/**
* Convert the IDs to numbers.
*
* @param [ Array ] ids
*
* @return [ Array<Number> ]
*/
exports.convertIds = function (ids) {
var convertedIds = [];
for (var i = 0; i < ids.length; i++) {
convertedIds.push(Number(ids[i]));
}
return convertedIds;
};
/**
* First found value for the given keys.
*
* @param [ Object ] options Object with key-value properties.
* @param [ *Array<String> ] keys List of keys.
*
* @return [ Object ]
*/
exports.getValueFor = function (options) {
var keys = Array.apply(null, arguments).slice(1);
for (var i = 0; i < keys.length; i++) {
var key = keys[i];
if (options.hasOwnProperty(key)) {
return options[key];
}
}
};
/**
* Fire the event with given arguments.
*
* @param [ String ] event The event's name.
* @param [ *Array] args The callback's arguments.
*
* @return [ Void]
*/
exports.fireEvent = function (event) {
var args = Array.apply(null, arguments).slice(1),
listener = this._listener[event];
if (!listener)
return;
for (var i = 0; i < listener.length; i++) {
var fn = listener[i][0],
scope = listener[i][1];
fn.apply(scope, args);
}
};
/**
* Execute the native counterpart.
*
* @param [ String ] action The name of the action.
* @param [ Array ] args Array of arguments.
* @param [ Function] callback The callback function.
* @param [ Object ] scope The scope for the function.
*
* @return [ Void ]
*/
exports.exec = function (action, args, callback, scope) {
var fn = this.createCallbackFn(callback, scope),
params = [];
if (Array.isArray(args)) {
params = args;
} else if (args) {
params.push(args);
}
exec(fn, null, 'LocalNotification', action, params);
};
// Called after 'deviceready' event
channel.deviceready.subscribe(function () {
// Device is ready now, the listeners are registered
// and all queued events can be executed.
exports.exec('deviceready');
});
// Called before 'deviceready' event
channel.onCordovaReady.subscribe(function () {
// Set launchDetails object
exports.exec('launchDetails');
// Device plugin is ready now
channel.onCordovaInfoReady.subscribe(function () {
// Merge platform specifics into defaults
exports.applyPlatformSpecificOptions();
});
});
/*
* Apache 2.0 License
*
* Copyright (c) Sebastian Katzer 2017
*
* This file contains Original Code and/or Modifications of Original Code
* as defined in and that are subject to the Apache License
* Version 2.0 (the 'License'). You may not use this file except in
* compliance with the License. Please obtain a copy of the License at
* http://opensource.org/licenses/Apache-2.0/ and read it before using this
* file.
*
* The Original Code and all software distributed under the License are
* distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
* Please see the License for the specific language governing rights and
* limitations under the License.
*/
/**
* Request permission to show notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.hasPermission = function (callback, scope) {
this.core.hasPermission(callback, scope);
};
/**
* Request permission to show notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.requestPermission = function (callback, scope) {
this.core.requestPermission(callback, scope);
};
/**
* Schedule notifications.
*
* @param [ Array ] notifications The notifications to schedule.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
* @param [ Object ] args Optional flags how to schedule.
*
* @return [ Void ]
*/
exports.schedule = function (notifications, callback, scope, args) {
this.core.schedule(notifications, callback, scope, args);
};
// /**
// * Update existing notifications specified by IDs in options.
// *
// * @param {Object} notifications
// * The notification properties to update
// * @param {Function} callback
// * A function to be called after the notification has been updated
// * @param {Object?} scope
// * The scope for the callback function
// * @param {Object?} args
// * skipPermission:true schedules the notifications immediatly without
// * registering or checking for permission
// */
// exports.update = function (notifications, callback, scope, args) {
// this.core.update(notifications, callback, scope, args);
// };
/**
* Clear the specified notifications by id.
*
* @param [ Array<Int> ] ids The IDs of the notifications.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.clear = function (ids, callback, scope) {
this.core.clear(ids, callback, scope);
};
/**
* Clear all triggered notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.clearAll = function (callback, scope) {
this.core.clearAll(callback, scope);
};
/**
* Cancel the specified notifications by id.
*
* @param [ Array<Int> ] ids The IDs of the notifications.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.cancel = function (ids, callback, scope) {
this.core.cancel(ids, callback, scope);
};
/**
* Cancel all scheduled notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.cancelAll = function (callback, scope) {
this.core.cancelAll(callback, scope);
};
/**
* Check if a notification is present.
*
* @param [ Int ] id The ID of the notification.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.isPresent = function (id, callback, scope) {
this.core.isPresent(id, callback, scope);
};
/**
* Check if a notification is scheduled.
*
* @param [ Int ] id The ID of the notification.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.isScheduled = function (id, callback, scope) {
this.core.hasType(id, 'scheduled', callback, scope);
};
/**
* Check if a notification was triggered.
*
* @param [ Int ] id The ID of the notification.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.isTriggered = function (id, callback, scope) {
this.core.hasType(id, 'triggered', callback, scope);
};
/**
* Get the type (triggered, scheduled) for the notification.
*
* @param [ Int ] id The ID of the notification.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getType = function (id, callback, scope) {
this.core.getType(id, callback, scope);
};
/**
* List of all notification ids.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getIds = function (callback, scope) {
this.core.getIds(callback, scope);
};
/**
* List of all scheduled notification IDs.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getScheduledIds = function (callback, scope) {
this.core.getScheduledIds(callback, scope);
};
/**
* List of all triggered notification IDs.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getTriggeredIds = function (callback, scope) {
this.core.getTriggeredIds(callback, scope);
};
/**
* List of local notifications specified by id.
* If called without IDs, all notification will be returned.
*
* @param [ Array<Int> ] ids The IDs of the notifications.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.get = function (ids, callback, scope) {
this.core.get(ids, callback, scope);
};
/**
* List for all notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.getAll = function (callback, scope) {
this.core.getAll(callback, scope);
};
/**
* List of all scheduled notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*/
exports.getScheduled = function (callback, scope) {
this.core.getScheduled(callback, scope);
};
/**
* List of all triggered notifications.
*
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*/
exports.getTriggered = function (callback, scope) {
this.core.getTriggered(callback, scope);
};
/**
* Register an group of actions by id.
*
* @param [ String ] id The Id of the group.
* @param [ Array] actions The action config settings.
* @param [ Function ] callback The function to be exec as the callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.addActionGroup = function (id, actions, callback, scope) {
this.core.registerActionGroup(id, actions, callback, scope);
};
/**
* The (platform specific) default settings.
*
* @return [ Object ]
*/
exports.getDefaults = function () {
return this.core.getDefaults();
};
/**
* Overwrite default settings.
*
* @param [ Object ] newDefaults New default values.
*
* @return [ Void ]
*/
exports.setDefaults = function (defaults) {
this.core.setDefaults(defaults);
};
/**
* Register callback for given event.
*
* @param [ String ] event The name of the event.
* @param [ Function ] callback The function to be exec as callback.
* @param [ Object ] scope The callback function's scope.
*
* @return [ Void ]
*/
exports.on = function (event, callback, scope) {
this.core.on(event, callback, scope);
};
/**
* Unregister callback for given event.
*
* @param [ String ] event The name of the event.
* @param [ Function ] callback The function to be exec as callback.
*
* @return [ Void ]
*/
exports.un = function (event, callback) {
this.core.un(event, callback);
};
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment