├── .gitignore ├── CHANGELOG.md ├── ISSUE_TEMPLATE.md ├── LICENSE ├── README.md ├── images ├── android-actions.png ├── android-chat.png ├── android-inbox.png ├── android-progress.png ├── android-reply-2.png ├── android-reply.png ├── android-stack.png ├── ios-actions.png ├── ios-basic.png ├── ios-permission.png ├── logo.png └── windows-actions.png ├── package.json ├── plugin.xml ├── src ├── android │ ├── ClearReceiver.java │ ├── ClickReceiver.java │ ├── LocalNotification.java │ ├── RestoreReceiver.java │ ├── TriggerReceiver.java │ ├── build │ │ └── localnotification.gradle │ ├── notification │ │ ├── Builder.java │ │ ├── Manager.java │ │ ├── Notification.java │ │ ├── Options.java │ │ ├── Request.java │ │ ├── action │ │ │ ├── Action.java │ │ │ └── ActionGroup.java │ │ ├── receiver │ │ │ ├── AbstractClearReceiver.java │ │ │ ├── AbstractClickReceiver.java │ │ │ ├── AbstractRestoreReceiver.java │ │ │ └── AbstractTriggerReceiver.java │ │ ├── trigger │ │ │ ├── DateTrigger.java │ │ │ ├── IntervalTrigger.java │ │ │ └── MatchTrigger.java │ │ └── util │ │ │ ├── AssetProvider.java │ │ │ └── AssetUtil.java │ └── xml │ │ └── localnotification_provider_paths.xml ├── ios │ ├── APPLocalNotification.h │ ├── APPLocalNotification.m │ ├── APPNotificationCategory.h │ ├── APPNotificationCategory.m │ ├── APPNotificationContent.h │ ├── APPNotificationContent.m │ ├── APPNotificationOptions.h │ ├── APPNotificationOptions.m │ ├── UNNotificationRequest+APPLocalNotification.h │ ├── UNNotificationRequest+APPLocalNotification.m │ ├── UNUserNotificationCenter+APPLocalNotification.h │ └── UNUserNotificationCenter+APPLocalNotification.m └── windows │ ├── LocalNotificationProxy.js │ ├── LocalNotificationProxy │ ├── .vs │ │ └── LocalNotificationProxy │ │ │ └── v15 │ │ │ └── .suo │ ├── LocalNotificationProxy.sln │ └── LocalNotificationProxy │ │ ├── LocalNotification │ │ ├── ActionGroup.cs │ │ ├── Builder.cs │ │ ├── Manager.cs │ │ ├── Notification.cs │ │ ├── Options.cs │ │ ├── Request.cs │ │ ├── Toast │ │ │ ├── Button.cs │ │ │ ├── Every.cs │ │ │ ├── IAction.cs │ │ │ ├── Input.cs │ │ │ ├── ProgressBar.cs │ │ │ └── Trigger.cs │ │ └── Trigger │ │ │ ├── DateTrigger.cs │ │ │ ├── IntervalTrigger.cs │ │ │ └── MatchTrigger.cs │ │ ├── LocalNotificationProxy.cs │ │ ├── LocalNotificationProxy.csproj │ │ └── Properties │ │ └── AssemblyInfo.cs │ └── lib.UW │ ├── ARM │ ├── LocalNotificationProxy.winmd │ └── Microsoft.Toolkit.Uwp.Notifications.dll │ ├── x64 │ ├── LocalNotificationProxy.winmd │ └── Microsoft.Toolkit.Uwp.Notifications.dll │ └── x86 │ ├── LocalNotificationProxy.winmd │ └── Microsoft.Toolkit.Uwp.Notifications.dll └── www └── local-notification.js /.gitignore: -------------------------------------------------------------------------------- 1 | /src/windows.old 2 | /src/windows/Microsoft.Toolkit.Uwp.Notifications.* 3 | /src/windows/**/.vs 4 | /src/windows/**/bin 5 | /src/windows/**/obj 6 | .idea 7 | src/cordova-plugin-local-notifications.iml -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | Changelog 2 | --------- 3 | 4 | #### Version 0.9.3 (09.05.2019) 5 | - Add namespace to provider authority to prevent crashes on Android. 6 | 7 | #### Version 0.9.2 (20.12.2018) 8 | - Prevent progressbar timer from being reset when updating the progress value. 9 | 10 | #### Version 0.9.1 (13.12.2018) 11 | - Addedd support for mutliple channels 12 | - Added new property `channelDescription` to specify the name / description of the channel 13 | - Channels will now use the priority level based on the settings given to the notification 14 | - Fixed default notification sound (Android) 15 | - Fixed permission check (Android) 16 | - Fixed (silent) vibration (Android) 17 | 18 | #### Version 0.8.6 (11.09.2018) 19 | - Added support for Android 8+ (Oreo) 20 | - Add property `when` (Android) 21 | 22 | Old changelog below 23 | --------- 24 | 25 | #### Version 0.8.5 (22.05.2017) 26 | - iOS 10 27 | 28 | #### Version 0.8.4 (04.01.2016) 29 | - Bug fixes 30 | - SyntaxError: missing ) after argument list 31 | 32 | #### Version 0.8.3 (03.01.2016) 33 | - Platform enhancements 34 | - Support for the `Crosswalk Engine` 35 | - Support for `cordova-ios@4` and the `WKWebView Engine` 36 | - Support for `cordova-windows@4` and `Windows 10` without using hooks 37 | - Enhancements 38 | - New `color` attribute for Android (Thanks to @Eusebius1920) 39 | - New `quarter` intervall for iOS & Android 40 | - `smallIcon` is optional (Android) 41 | - `update` checks for permission like _schedule_ 42 | - Decreased time-frame for trigger event (iOS) 43 | - Force `every:` to be a string on iOS 44 | - Bug fixes 45 | - Fixed #634 option to skip permission check 46 | - Fixed #588 crash when basename & extension can't be extracted (Android) 47 | - Fixed #732 loop between update and trigger (Android) 48 | - Fixed #710 crash due to >500 notifications (Android) 49 | - Fixed #682 crash while resuming app from notification (Android 6) 50 | - Fixed #612 cannot update icon or sound (Android) 51 | - Fixed crashing get(ID) if notification doesn't exist 52 | - Fixed #569 getScheduled returns two items per notification 53 | - Fixed #700 notifications appears on bootup 54 | 55 | #### Version 0.8.2 (08.11.2015) 56 | - Submitted to npm 57 | - Initial support for the `windows` platform 58 | - Re-add autoCancel option on Android 59 | - Warn about unknown properties 60 | - Fix crash on iOS 9 61 | - Fixed webView-Problems with cordova-android 4.0 62 | - Fix get* with single id 63 | - Fix issue when passing data in milliseconds 64 | - Update device plugin id 65 | - Several other fixes 66 | 67 | #### Version 0.8.1 (08.03.2015) 68 | 69 | - Fix incompatibility with cordova version 3.5-3.0 70 | - Fire `clear` instead of `cancel` event when clicked on repeating notifications 71 | - Do not fire `clear` or `cancel` event when clicked on persistent notifications 72 | 73 | ### Version 0.8.0 (05.03.2015) 74 | 75 | - Support for iOS 8, Android 2 (SDK >= 7) and Android 5 76 | - Windows Phone 8.1 will be added soon 77 | - New interfaces to ask for / register permissions required to schedule local notifications 78 | - `hasPermission()` and `registerPermission()` 79 | - _schedule()_ will register the permission automatically and schedule the notification if granted. 80 | - New interface to update already scheduled|triggered local notifications 81 | - `update()` 82 | - New interfaces to clear the notification center 83 | - `clear()` and `clearAll()` 84 | - New interfaces to query for local notifications, their properties, their IDs and their existence depend on their state 85 | - `isPresent()`, `isScheduled()`, `isTriggered()` 86 | - `getIds()`, `getAllIds()`, `getScheduledIds()`, `getTriggeredIds()` 87 | - `get()`, `getAll()`, `getScheduled()`, `getTriggered()` 88 | - Schedule multiple local notifications at once 89 | - `schedule( [{...},{...}] )` 90 | - Update multiple local notifications at once 91 | - `update( [{...},{...}] )` 92 | - Clear multiple local notifications at once 93 | - `clear( [1, 2] )` 94 | - Cancel multiple local notifications at once 95 | - `cancel( [1, 2] )` 96 | - New URI format to specify sound and image resources 97 | - `http(s):` for remote resources _(Android)_ 98 | - `file:` for local resources relative to the _www_ folder 99 | - `res:` for native resources 100 | - New events 101 | - `schedule`, `update`, `clear`, `clearall` and `cancelall` 102 | - Enhanced event informations 103 | - Listener will get called with the local notification object instead of only the ID 104 | - Multiple listener for one event 105 | - `on(event, callback, scope)` 106 | - Unregister event listener 107 | - `un(event, callback)` 108 | - New Android specific properties 109 | - `led` properties 110 | - `sound` and `image` accepts remote resources 111 | - Callback function and scope for all interface methods 112 | - `schedule( notification, callback, scope )` 113 | - Renamed `add()` to `schedule()` 114 | - `autoCancel` property has been removed 115 | - Use `ongoing: true` for persistent local notifications on Android 116 | - Renamed repeat intervals 117 | - `second`, `minute`, `hour`, `day`, `week`, `month` and `year` 118 | - Renamed some local notification properties 119 | - `date`, `json`, `message` and `repeat` 120 | - Scheduling local notifications with the deprecated properties is still possible 121 | - [Kitchen Sink sample app](https://github.com/katzer/cordova-plugin-local-notifications/tree/example) 122 | - [Wiki](https://github.com/katzer/cordova-plugin-local-notifications/wiki) 123 | -------------------------------------------------------------------------------- /ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **WARNING: IF YOU IGNORE THIS TEMPLATE, WE'LL IGNORE YOUR ISSUE. YOU MUST FILL THIS IN!** 2 | 3 | Provide a general summary of the issue. 4 | 5 | ## Your Environment 6 | 7 | * Plugin version: 8 | * Platform: 9 | * OS version: 10 | * Device manufacturer / model: 11 | * Cordova version (```cordova -v```): 12 | * Cordova platform version (```cordova platform ls```): 13 | * Plugin config 14 | * Ionic Version (if using Ionic) 15 | 16 | ## Expected Behavior 17 | 18 | _Tell us what should happen_ 19 | 20 | ## Actual Behavior 21 | 22 | _Tell us what happens instead_ 23 | 24 | ## Steps to Reproduce 25 | 26 | _Reproduce this issue; include code to reproduce, if relevant_ 27 | 28 | 1. ... 29 | 2. ... 30 | 3. ... 31 | 4. .... 32 | 33 | ## Context 34 | 35 | _What were you trying to do?_ 36 | 37 | ## Debug logs 38 | 39 | _Include iOS / Android logs_ 40 | 41 | * ios XCode logs 42 | * Android: $ adb logcat 43 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | 2 | Apache License 3 | Version 2.0, January 2004 4 | http://www.apache.org/licenses/ 5 | 6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 7 | 8 | 1. Definitions. 9 | 10 | "License" shall mean the terms and conditions for use, reproduction, 11 | and distribution as defined by Sections 1 through 9 of this document. 12 | 13 | "Licensor" shall mean the copyright owner or entity authorized by 14 | the copyright owner that is granting the License. 15 | 16 | "Legal Entity" shall mean the union of the acting entity and all 17 | other entities that control, are controlled by, or are under common 18 | control with that entity. For the purposes of this definition, 19 | "control" means (i) the power, direct or indirect, to cause the 20 | direction or management of such entity, whether by contract or 21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 22 | outstanding shares, or (iii) beneficial ownership of such entity. 23 | 24 | "You" (or "Your") shall mean an individual or Legal Entity 25 | exercising permissions granted by this License. 26 | 27 | "Source" form shall mean the preferred form for making modifications, 28 | including but not limited to software source code, documentation 29 | source, and configuration files. 30 | 31 | "Object" form shall mean any form resulting from mechanical 32 | transformation or translation of a Source form, including but 33 | not limited to compiled object code, generated documentation, 34 | and conversions to other media types. 35 | 36 | "Work" shall mean the work of authorship, whether in Source or 37 | Object form, made available under the License, as indicated by a 38 | copyright notice that is included in or attached to the work 39 | (an example is provided in the Appendix below). 40 | 41 | "Derivative Works" shall mean any work, whether in Source or Object 42 | form, that is based on (or derived from) the Work and for which the 43 | editorial revisions, annotations, elaborations, or other modifications 44 | represent, as a whole, an original work of authorship. For the purposes 45 | of this License, Derivative Works shall not include works that remain 46 | separable from, or merely link (or bind by name) to the interfaces of, 47 | the Work and Derivative Works thereof. 48 | 49 | "Contribution" shall mean any work of authorship, including 50 | the original version of the Work and any modifications or additions 51 | to that Work or Derivative Works thereof, that is intentionally 52 | submitted to Licensor for inclusion in the Work by the copyright owner 53 | or by an individual or Legal Entity authorized to submit on behalf of 54 | the copyright owner. For the purposes of this definition, "submitted" 55 | means any form of electronic, verbal, or written communication sent 56 | to the Licensor or its representatives, including but not limited to 57 | communication on electronic mailing lists, source code control systems, 58 | and issue tracking systems that are managed by, or on behalf of, the 59 | Licensor for the purpose of discussing and improving the Work, but 60 | excluding communication that is conspicuously marked or otherwise 61 | designated in writing by the copyright owner as "Not a Contribution." 62 | 63 | "Contributor" shall mean Licensor and any individual or Legal Entity 64 | on behalf of whom a Contribution has been received by Licensor and 65 | subsequently incorporated within the Work. 66 | 67 | 2. Grant of Copyright License. Subject to the terms and conditions of 68 | this License, each Contributor hereby grants to You a perpetual, 69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 70 | copyright license to reproduce, prepare Derivative Works of, 71 | publicly display, publicly perform, sublicense, and distribute the 72 | Work and such Derivative Works in Source or Object form. 73 | 74 | 3. Grant of Patent License. Subject to the terms and conditions of 75 | this License, each Contributor hereby grants to You a perpetual, 76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 77 | (except as stated in this section) patent license to make, have made, 78 | use, offer to sell, sell, import, and otherwise transfer the Work, 79 | where such license applies only to those patent claims licensable 80 | by such Contributor that are necessarily infringed by their 81 | Contribution(s) alone or by combination of their Contribution(s) 82 | with the Work to which such Contribution(s) was submitted. If You 83 | institute patent litigation against any entity (including a 84 | cross-claim or counterclaim in a lawsuit) alleging that the Work 85 | or a Contribution incorporated within the Work constitutes direct 86 | or contributory patent infringement, then any patent licenses 87 | granted to You under this License for that Work shall terminate 88 | as of the date such litigation is filed. 89 | 90 | 4. Redistribution. You may reproduce and distribute copies of the 91 | Work or Derivative Works thereof in any medium, with or without 92 | modifications, and in Source or Object form, provided that You 93 | meet the following conditions: 94 | 95 | (a) You must give any other recipients of the Work or 96 | Derivative Works a copy of this License; and 97 | 98 | (b) You must cause any modified files to carry prominent notices 99 | stating that You changed the files; and 100 | 101 | (c) You must retain, in the Source form of any Derivative Works 102 | that You distribute, all copyright, patent, trademark, and 103 | attribution notices from the Source form of the Work, 104 | excluding those notices that do not pertain to any part of 105 | the Derivative Works; and 106 | 107 | (d) If the Work includes a "NOTICE" text file as part of its 108 | distribution, then any Derivative Works that You distribute must 109 | include a readable copy of the attribution notices contained 110 | within such NOTICE file, excluding those notices that do not 111 | pertain to any part of the Derivative Works, in at least one 112 | of the following places: within a NOTICE text file distributed 113 | as part of the Derivative Works; within the Source form or 114 | documentation, if provided along with the Derivative Works; or, 115 | within a display generated by the Derivative Works, if and 116 | wherever such third-party notices normally appear. The contents 117 | of the NOTICE file are for informational purposes only and 118 | do not modify the License. You may add Your own attribution 119 | notices within Derivative Works that You distribute, alongside 120 | or as an addendum to the NOTICE text from the Work, provided 121 | that such additional attribution notices cannot be construed 122 | as modifying the License. 123 | 124 | You may add Your own copyright statement to Your modifications and 125 | may provide additional or different license terms and conditions 126 | for use, reproduction, or distribution of Your modifications, or 127 | for any such Derivative Works as a whole, provided Your use, 128 | reproduction, and distribution of the Work otherwise complies with 129 | the conditions stated in this License. 130 | 131 | 5. Submission of Contributions. Unless You explicitly state otherwise, 132 | any Contribution intentionally submitted for inclusion in the Work 133 | by You to the Licensor shall be under the terms and conditions of 134 | this License, without any additional terms or conditions. 135 | Notwithstanding the above, nothing herein shall supersede or modify 136 | the terms of any separate license agreement you may have executed 137 | with Licensor regarding such Contributions. 138 | 139 | 6. Trademarks. This License does not grant permission to use the trade 140 | names, trademarks, service marks, or product names of the Licensor, 141 | except as required for reasonable and customary use in describing the 142 | origin of the Work and reproducing the content of the NOTICE file. 143 | 144 | 7. Disclaimer of Warranty. Unless required by applicable law or 145 | agreed to in writing, Licensor provides the Work (and each 146 | Contributor provides its Contributions) on an "AS IS" BASIS, 147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 148 | implied, including, without limitation, any warranties or conditions 149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 150 | PARTICULAR PURPOSE. You are solely responsible for determining the 151 | appropriateness of using or redistributing the Work and assume any 152 | risks associated with Your exercise of permissions under this License. 153 | 154 | 8. Limitation of Liability. In no event and under no legal theory, 155 | whether in tort (including negligence), contract, or otherwise, 156 | unless required by applicable law (such as deliberate and grossly 157 | negligent acts) or agreed to in writing, shall any Contributor be 158 | liable to You for damages, including any direct, indirect, special, 159 | incidental, or consequential damages of any character arising as a 160 | result of this License or out of the use or inability to use the 161 | Work (including but not limited to damages for loss of goodwill, 162 | work stoppage, computer failure or malfunction, or any and all 163 | other commercial damages or losses), even if such Contributor 164 | has been advised of the possibility of such damages. 165 | 166 | 9. Accepting Warranty or Additional Liability. While redistributing 167 | the Work or Derivative Works thereof, You may choose to offer, 168 | and charge a fee for, acceptance of support, warranty, indemnity, 169 | or other liability obligations and/or rights consistent with this 170 | License. However, in accepting such obligations, You may act only 171 | on Your own behalf and on Your sole responsibility, not on behalf 172 | of any other Contributor, and only if You agree to indemnify, 173 | defend, and hold each Contributor harmless for any liability 174 | incurred by, or claims asserted against, such Contributor by reason 175 | of your accepting any such warranty or additional liability. 176 | 177 | END OF TERMS AND CONDITIONS 178 | 179 | APPENDIX: How to apply the Apache License to your work. 180 | 181 | To apply the Apache License to your work, attach the following 182 | boilerplate notice, with the fields enclosed by brackets "[]" 183 | replaced with your own identifying information. (Don't include 184 | the brackets!) The text should be enclosed in the appropriate 185 | comment syntax for the file format. We also recommend that a 186 | file or class name and description of purpose be included on the 187 | same "printed page" as the copyright notice for easier 188 | identification within third-party archives. 189 | 190 | Copyright 2013 appPlant GmbH 191 | 192 | Licensed under the Apache License, Version 2.0 (the "License"); 193 | you may not use this file except in compliance with the License. 194 | You may obtain a copy of the License at 195 | 196 | http://www.apache.org/licenses/LICENSE-2.0 197 | 198 | Unless required by applicable law or agreed to in writing, software 199 | distributed under the License is distributed on an "AS IS" BASIS, 200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 201 | See the License for the specific language governing permissions and 202 | limitations under the License. -------------------------------------------------------------------------------- /images/android-actions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/android-actions.png -------------------------------------------------------------------------------- /images/android-chat.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/android-chat.png -------------------------------------------------------------------------------- /images/android-inbox.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/android-inbox.png -------------------------------------------------------------------------------- /images/android-progress.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/android-progress.png -------------------------------------------------------------------------------- /images/android-reply-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/android-reply-2.png -------------------------------------------------------------------------------- /images/android-reply.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/android-reply.png -------------------------------------------------------------------------------- /images/android-stack.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/android-stack.png -------------------------------------------------------------------------------- /images/ios-actions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/ios-actions.png -------------------------------------------------------------------------------- /images/ios-basic.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/ios-basic.png -------------------------------------------------------------------------------- /images/ios-permission.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/ios-permission.png -------------------------------------------------------------------------------- /images/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/logo.png -------------------------------------------------------------------------------- /images/windows-actions.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/images/windows-actions.png -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "cordova-plugin-local-notification", 3 | "version": "0.9.3", 4 | "description": "Schedules and queries for local notifications", 5 | "cordova": { 6 | "id": "cordova-plugin-local-notification", 7 | "platforms": [ 8 | "android", 9 | "ios", 10 | "windows" 11 | ] 12 | }, 13 | "repository": { 14 | "type": "git", 15 | "url": "git+https://github.com/Steffaan/cordova-plugin-local-notifications.git" 16 | }, 17 | "keywords": [ 18 | "appplant", 19 | "notification", 20 | "local notification", 21 | "user notification", 22 | "ecosystem:cordova", 23 | "cordova-ios", 24 | "cordova-android", 25 | "cordova-windows" 26 | ], 27 | "engines": [ 28 | { 29 | "name": "cordova", 30 | "version": ">=3.6.0" 31 | }, 32 | { 33 | "name": "cordova-android", 34 | "version": ">=6.0.0" 35 | }, 36 | { 37 | "name": "cordova-windows", 38 | "version": ">=4.2.0" 39 | }, 40 | { 41 | "name": "android-sdk", 42 | "version": ">=26" 43 | }, 44 | { 45 | "name": "apple-ios", 46 | "version": ">=10.0.0" 47 | } 48 | ], 49 | "author": "Sebastián Katzer", 50 | "license": "Apache 2.0", 51 | "bugs": { 52 | "url": "https://github.com/Steffaan/cordova-plugin-local-notifications/issues" 53 | }, 54 | "homepage": "https://github.com/Steffaan/cordova-plugin-local-notifications#readme" 55 | } 56 | -------------------------------------------------------------------------------- /plugin.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 23 | 24 | 28 | 29 | LocalNotification 30 | 31 | Schedules and queries for local notifications 32 | 33 | https://github.com/Steffaan/cordova-plugin-local-notifications.git 34 | 35 | appplant, notification, local notification, user notification 36 | 37 | Apache 2.0 38 | 39 | Sebastián Katzer 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 109 | 112 | 113 | 114 | 117 | 118 | 121 | 122 | 125 | 126 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 145 | 146 | 149 | 150 | 153 | 154 | 157 | 158 | 161 | 162 | 165 | 166 | 169 | 170 | 173 | 174 | 177 | 178 | 181 | 182 | 185 | 186 | 189 | 190 | 193 | 194 | 197 | 198 | 201 | 202 | 205 | 206 | 209 | 210 | 213 | 214 | 217 | 218 | 221 | 222 | 225 | 226 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | -------------------------------------------------------------------------------- /src/android/ClearReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.localnotification; 23 | 24 | import android.os.Bundle; 25 | 26 | import de.appplant.cordova.plugin.notification.Notification; 27 | import de.appplant.cordova.plugin.notification.receiver.AbstractClearReceiver; 28 | 29 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.fireEvent; 30 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.isAppRunning; 31 | import static de.appplant.cordova.plugin.notification.Request.EXTRA_LAST; 32 | 33 | /** 34 | * The clear intent receiver is triggered when the user clears a 35 | * notification manually. It un-persists the cleared notification from the 36 | * shared preferences. 37 | */ 38 | public class ClearReceiver extends AbstractClearReceiver { 39 | 40 | /** 41 | * Called when a local notification was cleared from outside of the app. 42 | * 43 | * @param notification Wrapper around the local notification. 44 | * @param bundle The bundled extras. 45 | */ 46 | @Override 47 | public void onClear (Notification notification, Bundle bundle) { 48 | boolean isLast = bundle.getBoolean(EXTRA_LAST, false); 49 | 50 | if (isLast) { 51 | notification.cancel(); 52 | } else { 53 | notification.clear(); 54 | } 55 | 56 | if (isAppRunning()) { 57 | fireEvent("clear", notification); 58 | } 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /src/android/ClickReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.localnotification; 23 | 24 | import android.os.Bundle; 25 | import android.support.v4.app.RemoteInput; 26 | 27 | import org.json.JSONException; 28 | import org.json.JSONObject; 29 | 30 | import de.appplant.cordova.plugin.notification.Notification; 31 | import de.appplant.cordova.plugin.notification.receiver.AbstractClickReceiver; 32 | 33 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.fireEvent; 34 | import static de.appplant.cordova.plugin.notification.Options.EXTRA_LAUNCH; 35 | import static de.appplant.cordova.plugin.notification.Request.EXTRA_LAST; 36 | 37 | /** 38 | * The receiver activity is triggered when a notification is clicked by a user. 39 | * The activity calls the background callback and brings the launch intent 40 | * up to foreground. 41 | */ 42 | public class ClickReceiver extends AbstractClickReceiver { 43 | 44 | /** 45 | * Called when local notification was clicked by the user. 46 | * 47 | * @param notification Wrapper around the local notification. 48 | * @param bundle The bundled extras. 49 | */ 50 | @Override 51 | public void onClick(Notification notification, Bundle bundle) { 52 | String action = getAction(); 53 | JSONObject data = new JSONObject(); 54 | 55 | setTextInput(action, data); 56 | launchAppIf(); 57 | 58 | fireEvent(action, notification, data); 59 | 60 | if (notification.getOptions().isSticky()) 61 | return; 62 | 63 | if (isLast()) { 64 | notification.cancel(); 65 | } else { 66 | notification.clear(); 67 | } 68 | } 69 | 70 | /** 71 | * Set the text if any remote input is given. 72 | * 73 | * @param action The action where to look for. 74 | * @param data The object to extend. 75 | */ 76 | private void setTextInput(String action, JSONObject data) { 77 | Bundle input = RemoteInput.getResultsFromIntent(getIntent()); 78 | 79 | if (input == null) 80 | return; 81 | 82 | try { 83 | data.put("text", input.getCharSequence(action)); 84 | } catch (JSONException e) { 85 | e.printStackTrace(); 86 | } 87 | } 88 | 89 | /** 90 | * Launch app if requested by user. 91 | */ 92 | private void launchAppIf() { 93 | boolean doLaunch = getIntent().getBooleanExtra(EXTRA_LAUNCH, true); 94 | 95 | if (!doLaunch) 96 | return; 97 | 98 | launchApp(); 99 | } 100 | 101 | /** 102 | * If the notification was the last scheduled one by request. 103 | */ 104 | private boolean isLast() { 105 | return getIntent().getBooleanExtra(EXTRA_LAST, false); 106 | } 107 | 108 | } 109 | -------------------------------------------------------------------------------- /src/android/RestoreReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 by appPlant UG. All rights reserved. 3 | * 4 | * @APPPLANT_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPPLANT_LICENSE_HEADER_END@ 22 | */ 23 | 24 | package de.appplant.cordova.plugin.localnotification; 25 | 26 | import android.content.Context; 27 | import android.util.Log; 28 | 29 | import java.util.Date; 30 | 31 | import de.appplant.cordova.plugin.notification.Builder; 32 | import de.appplant.cordova.plugin.notification.Manager; 33 | import de.appplant.cordova.plugin.notification.Notification; 34 | import de.appplant.cordova.plugin.notification.Request; 35 | import de.appplant.cordova.plugin.notification.receiver.AbstractRestoreReceiver; 36 | 37 | /** 38 | * This class is triggered upon reboot of the device. It needs to re-register 39 | * the alarms with the AlarmManager since these alarms are lost in case of 40 | * reboot. 41 | */ 42 | public class RestoreReceiver extends AbstractRestoreReceiver { 43 | 44 | /** 45 | * Called when a local notification need to be restored. 46 | * 47 | * @param request Set of notification options. 48 | * @param toast Wrapper around the local notification. 49 | */ 50 | @Override 51 | public void onRestore (Request request, Notification toast) { 52 | Date date = request.getTriggerDate(); 53 | boolean after = date != null && date.after(new Date()); 54 | 55 | if (!after && toast.isHighPrio()) { 56 | toast.show(); 57 | } else { 58 | toast.clear(); 59 | } 60 | 61 | Context ctx = toast.getContext(); 62 | Manager mgr = Manager.getInstance(ctx); 63 | 64 | if (after || toast.isRepeating()) { 65 | mgr.schedule(request, TriggerReceiver.class); 66 | } 67 | } 68 | 69 | /** 70 | * Build notification specified by options. 71 | * 72 | * @param builder Notification builder. 73 | */ 74 | @Override 75 | public Notification buildNotification (Builder builder) { 76 | return builder 77 | .setClickActivity(ClickReceiver.class) 78 | .setClearReceiver(ClearReceiver.class) 79 | .build(); 80 | } 81 | 82 | } 83 | -------------------------------------------------------------------------------- /src/android/TriggerReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.localnotification; 23 | 24 | import android.content.Context; 25 | import android.os.Bundle; 26 | import android.os.PowerManager; 27 | 28 | import java.util.Calendar; 29 | 30 | import de.appplant.cordova.plugin.notification.Builder; 31 | import de.appplant.cordova.plugin.notification.Manager; 32 | import de.appplant.cordova.plugin.notification.Notification; 33 | import de.appplant.cordova.plugin.notification.Options; 34 | import de.appplant.cordova.plugin.notification.Request; 35 | import de.appplant.cordova.plugin.notification.receiver.AbstractTriggerReceiver; 36 | 37 | import static android.content.Context.POWER_SERVICE; 38 | import static android.os.Build.VERSION.SDK_INT; 39 | import static android.os.Build.VERSION_CODES.LOLLIPOP; 40 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.fireEvent; 41 | import static de.appplant.cordova.plugin.localnotification.LocalNotification.isAppRunning; 42 | import static java.util.Calendar.MINUTE; 43 | 44 | /** 45 | * The alarm receiver is triggered when a scheduled alarm is fired. This class 46 | * reads the information in the intent and displays this information in the 47 | * Android notification bar. The notification uses the default notification 48 | * sound and it vibrates the phone. 49 | */ 50 | public class TriggerReceiver extends AbstractTriggerReceiver { 51 | 52 | /** 53 | * Called when a local notification was triggered. Does present the local 54 | * notification, re-schedule the alarm if necessary and fire trigger event. 55 | * 56 | * @param notification Wrapper around the local notification. 57 | * @param bundle The bundled extras. 58 | */ 59 | @Override 60 | public void onTrigger (Notification notification, Bundle bundle) { 61 | boolean isUpdate = bundle.getBoolean(Notification.EXTRA_UPDATE, false); 62 | Context context = notification.getContext(); 63 | Options options = notification.getOptions(); 64 | Manager manager = Manager.getInstance(context); 65 | int badge = options.getBadgeNumber(); 66 | 67 | if (badge > 0) { 68 | manager.setBadge(badge); 69 | } 70 | 71 | if (options.shallWakeUp()) { 72 | wakeUp(context); 73 | } 74 | 75 | manager.createChannel(options); 76 | 77 | notification.show(); 78 | 79 | if (!isUpdate && isAppRunning()) { 80 | fireEvent("trigger", notification); 81 | } 82 | 83 | if (!options.isInfiniteTrigger()) 84 | return; 85 | 86 | Calendar cal = Calendar.getInstance(); 87 | cal.add(MINUTE, 1); 88 | Request req = new Request(options, cal.getTime()); 89 | 90 | manager.schedule(req, this.getClass()); 91 | } 92 | 93 | /** 94 | * Wakeup the device. 95 | * 96 | * @param context The application context. 97 | */ 98 | private void wakeUp (Context context) { 99 | PowerManager pm = (PowerManager) context.getSystemService(POWER_SERVICE); 100 | 101 | if (pm == null) 102 | return; 103 | 104 | int level = PowerManager.SCREEN_DIM_WAKE_LOCK 105 | | PowerManager.ACQUIRE_CAUSES_WAKEUP; 106 | 107 | PowerManager.WakeLock wakeLock = pm.newWakeLock( 108 | level, "LocalNotification"); 109 | 110 | wakeLock.setReferenceCounted(false); 111 | wakeLock.acquire(1000); 112 | 113 | if (SDK_INT >= LOLLIPOP) { 114 | wakeLock.release(PowerManager.RELEASE_FLAG_WAIT_FOR_NO_PROXIMITY); 115 | } else { 116 | wakeLock.release(); 117 | } 118 | } 119 | 120 | /** 121 | * Build notification specified by options. 122 | * 123 | * @param builder Notification builder. 124 | * @param bundle The bundled extras. 125 | */ 126 | @Override 127 | public Notification buildNotification (Builder builder, Bundle bundle) { 128 | return builder 129 | .setClickActivity(ClickReceiver.class) 130 | .setClearReceiver(ClearReceiver.class) 131 | .setExtras(bundle) 132 | .build(); 133 | } 134 | 135 | } 136 | -------------------------------------------------------------------------------- /src/android/build/localnotification.gradle: -------------------------------------------------------------------------------- 1 | /* 2 | * This file contains Original Code and/or Modifications of Original Code 3 | * as defined in and that are subject to the Apache License 4 | * Version 2.0 (the 'License'). You may not use this file except in 5 | * compliance with the License. Please obtain a copy of the License at 6 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 7 | * file. 8 | * 9 | * The Original Code and all software distributed under the License are 10 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 11 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 12 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 13 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 14 | * Please see the License for the specific language governing rights and 15 | * limitations under the License. 16 | */ 17 | 18 | repositories { 19 | mavenCentral() 20 | jcenter() 21 | maven { 22 | url "https://maven.google.com" 23 | } 24 | } 25 | 26 | if (!project.ext.has('appShortcutBadgerVersion')) { 27 | ext.appShortcutBadgerVersion = '1.1.19' 28 | } 29 | 30 | dependencies { 31 | compile "me.leolin:ShortcutBadger:${appShortcutBadgerVersion}@aar" 32 | } 33 | -------------------------------------------------------------------------------- /src/android/notification/Request.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 by appPlant UG. All rights reserved. 3 | * 4 | * @APPPLANT_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPPLANT_LICENSE_HEADER_END@ 22 | */ 23 | 24 | package de.appplant.cordova.plugin.notification; 25 | 26 | import org.json.JSONObject; 27 | 28 | import java.util.Arrays; 29 | import java.util.Calendar; 30 | import java.util.Date; 31 | import java.util.List; 32 | 33 | import de.appplant.cordova.plugin.notification.trigger.DateTrigger; 34 | import de.appplant.cordova.plugin.notification.trigger.IntervalTrigger; 35 | import de.appplant.cordova.plugin.notification.trigger.MatchTrigger; 36 | 37 | import static de.appplant.cordova.plugin.notification.trigger.IntervalTrigger.Unit; 38 | 39 | /** 40 | * An object you use to specify a notification’s content and the condition 41 | * that triggers its delivery. 42 | */ 43 | public final class Request { 44 | 45 | // Key name for bundled extras 46 | static final String EXTRA_OCCURRENCE = "NOTIFICATION_OCCURRENCE"; 47 | 48 | // Key name for bundled extras 49 | public static final String EXTRA_LAST = "NOTIFICATION_LAST"; 50 | 51 | // The options spec 52 | private final Options options; 53 | 54 | // The right trigger for the options 55 | private final DateTrigger trigger; 56 | 57 | // How often the trigger shall occur 58 | private final int count; 59 | 60 | // The trigger spec 61 | private final JSONObject spec; 62 | 63 | // The current trigger date 64 | private Date triggerDate; 65 | 66 | /** 67 | * Create a request with a base date specified through the passed options. 68 | * 69 | * @param options The options spec. 70 | */ 71 | public Request(Options options) { 72 | this.options = options; 73 | this.spec = options.getTrigger(); 74 | this.count = Math.max(spec.optInt("count"), 1); 75 | this.trigger = buildTrigger(); 76 | this.triggerDate = trigger.getNextTriggerDate(getBaseDate()); 77 | } 78 | 79 | /** 80 | * Create a request with a base date specified via base argument. 81 | * 82 | * @param options The options spec. 83 | * @param base The base date from where to calculate the next trigger. 84 | */ 85 | public Request(Options options, Date base) { 86 | this.options = options; 87 | this.spec = options.getTrigger(); 88 | this.count = Math.max(spec.optInt("count"), 1); 89 | this.trigger = buildTrigger(); 90 | this.triggerDate = trigger.getNextTriggerDate(base); 91 | } 92 | 93 | /** 94 | * Gets the options spec. 95 | */ 96 | public Options getOptions() { 97 | return options; 98 | } 99 | 100 | /** 101 | * The identifier for the request. 102 | * 103 | * @return The notification ID as the string 104 | */ 105 | String getIdentifier() { 106 | return options.getId().toString() + "-" + getOccurrence(); 107 | } 108 | 109 | /** 110 | * The value of the internal occurrence counter. 111 | */ 112 | int getOccurrence() { 113 | return trigger.getOccurrence(); 114 | } 115 | 116 | /** 117 | * If there's one more trigger date to calculate. 118 | */ 119 | private boolean hasNext() { 120 | return triggerDate != null && getOccurrence() <= count; 121 | } 122 | 123 | /** 124 | * Moves the internal occurrence counter by one. 125 | */ 126 | boolean moveNext() { 127 | if (hasNext()) { 128 | triggerDate = getNextTriggerDate(); 129 | } else { 130 | triggerDate = null; 131 | } 132 | 133 | return this.triggerDate != null; 134 | } 135 | 136 | /** 137 | * Gets the current trigger date. 138 | * 139 | * @return null if there's no trigger date. 140 | */ 141 | public Date getTriggerDate() { 142 | Calendar now = Calendar.getInstance(); 143 | 144 | if (triggerDate == null) 145 | return null; 146 | 147 | long time = triggerDate.getTime(); 148 | 149 | if ((now.getTimeInMillis() - time) > 60000) 150 | return null; 151 | 152 | if (time >= spec.optLong("before", time + 1)) 153 | return null; 154 | 155 | return triggerDate; 156 | } 157 | 158 | /** 159 | * Gets the next trigger date based on the current trigger date. 160 | */ 161 | private Date getNextTriggerDate() { 162 | return trigger.getNextTriggerDate(triggerDate); 163 | } 164 | 165 | /** 166 | * Build the trigger specified in options. 167 | */ 168 | private DateTrigger buildTrigger() { 169 | Object every = spec.opt("every"); 170 | 171 | if (every instanceof JSONObject) { 172 | List cmp1 = getMatchingComponents(); 173 | List cmp2 = getSpecialMatchingComponents(); 174 | 175 | return new MatchTrigger(cmp1, cmp2); 176 | } 177 | 178 | Unit unit = getUnit(); 179 | int ticks = getTicks(); 180 | 181 | return new IntervalTrigger(ticks, unit); 182 | } 183 | 184 | /** 185 | * Gets the unit value. 186 | */ 187 | private Unit getUnit() { 188 | Object every = spec.opt("every"); 189 | String unit = "SECOND"; 190 | 191 | if (spec.has("unit")) { 192 | unit = spec.optString("unit", "second"); 193 | } else 194 | if (every instanceof String) { 195 | unit = spec.optString("every", "second"); 196 | } 197 | 198 | return Unit.valueOf(unit.toUpperCase()); 199 | } 200 | 201 | /** 202 | * Gets the tick value. 203 | */ 204 | private int getTicks() { 205 | Object every = spec.opt("every"); 206 | int ticks = 0; 207 | 208 | if (spec.has("at")) { 209 | ticks = 0; 210 | } else 211 | if (spec.has("in")) { 212 | ticks = spec.optInt("in", 0); 213 | } else 214 | if (every instanceof String) { 215 | ticks = 1; 216 | } else 217 | if (!(every instanceof JSONObject)) { 218 | ticks = spec.optInt("every", 0); 219 | } 220 | 221 | return ticks; 222 | } 223 | 224 | /** 225 | * Gets an array of all date parts to construct a datetime instance. 226 | * 227 | * @return [min, hour, day, month, year] 228 | */ 229 | private List getMatchingComponents() { 230 | JSONObject every = spec.optJSONObject("every"); 231 | 232 | return Arrays.asList( 233 | (Integer) every.opt("minute"), 234 | (Integer) every.opt("hour"), 235 | (Integer) every.opt("day"), 236 | (Integer) every.opt("month"), 237 | (Integer) every.opt("year") 238 | ); 239 | } 240 | 241 | /** 242 | * Gets an array of all date parts to construct a datetime instance. 243 | * 244 | * @return [min, hour, day, month, year] 245 | */ 246 | private List getSpecialMatchingComponents() { 247 | JSONObject every = spec.optJSONObject("every"); 248 | 249 | return Arrays.asList( 250 | (Integer) every.opt("weekday"), 251 | (Integer) every.opt("weekdayOrdinal"), 252 | (Integer) every.opt("weekOfMonth"), 253 | (Integer) every.opt("quarter") 254 | ); 255 | } 256 | 257 | /** 258 | * Gets the base date from where to calculate the next trigger date. 259 | */ 260 | private Date getBaseDate() { 261 | if (spec.has("at")) { 262 | return new Date(spec.optLong("at", 0)); 263 | } else 264 | if (spec.has("firstAt")) { 265 | return new Date(spec.optLong("firstAt", 0)); 266 | } else 267 | if (spec.has("after")) { 268 | return new Date(spec.optLong("after", 0)); 269 | } else { 270 | return new Date(); 271 | } 272 | } 273 | 274 | } 275 | -------------------------------------------------------------------------------- /src/android/notification/action/Action.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.notification.action; 23 | 24 | import android.content.Context; 25 | import android.support.v4.app.RemoteInput; 26 | 27 | import org.json.JSONArray; 28 | import org.json.JSONObject; 29 | 30 | import de.appplant.cordova.plugin.notification.util.AssetUtil; 31 | 32 | /** 33 | * Holds the icon and title components that would be used in a 34 | * NotificationCompat.Action object. Does not include the PendingIntent so 35 | * that it may be generated each time the notification is built. Necessary to 36 | * compensate for missing functionality in the support library. 37 | */ 38 | public final class Action { 39 | 40 | // Key name for bundled extras 41 | public static final String EXTRA_ID = "NOTIFICATION_ACTION_ID"; 42 | 43 | // The id for the click action 44 | public static final String CLICK_ACTION_ID = "click"; 45 | 46 | // The application context 47 | private final Context context; 48 | 49 | // The action spec 50 | private final JSONObject options; 51 | 52 | /** 53 | * Structure to encapsulate a named action that can be shown as part of 54 | * this notification. 55 | * 56 | * @param context The application context. 57 | * @param options The action options. 58 | */ 59 | Action (Context context, JSONObject options) { 60 | this.context = context; 61 | this.options = options; 62 | } 63 | 64 | /** 65 | * Gets the ID for the action. 66 | */ 67 | public String getId() { 68 | return options.optString("id", getTitle()); 69 | } 70 | 71 | /** 72 | * Gets the Title for the action. 73 | */ 74 | public String getTitle() { 75 | return options.optString("title", "unknown"); 76 | } 77 | 78 | /** 79 | * Gets the icon for the action. 80 | */ 81 | public int getIcon() { 82 | AssetUtil assets = AssetUtil.getInstance(context); 83 | String resPath = options.optString("icon"); 84 | int resId = assets.getResId(resPath); 85 | 86 | if (resId == 0) { 87 | resId = android.R.drawable.screen_background_dark; 88 | } 89 | 90 | return resId; 91 | } 92 | 93 | /** 94 | * Gets the value of the launch flag. 95 | */ 96 | public boolean isLaunchingApp() { 97 | return options.optBoolean("launch", false); 98 | } 99 | 100 | /** 101 | * Gets the type for the action. 102 | */ 103 | public boolean isWithInput() { 104 | String type = options.optString("type"); 105 | return type.equals("input"); 106 | } 107 | 108 | /** 109 | * Gets the input config in case of the action is of type input. 110 | */ 111 | public RemoteInput getInput() { 112 | return new RemoteInput.Builder(getId()) 113 | .setLabel(options.optString("emptyText")) 114 | .setAllowFreeFormInput(options.optBoolean("editable", true)) 115 | .setChoices(getChoices()) 116 | .build(); 117 | } 118 | 119 | /** 120 | * List of possible choices for input actions. 121 | */ 122 | private String[] getChoices() { 123 | JSONArray opts = options.optJSONArray("choices"); 124 | 125 | if (opts == null) 126 | return null; 127 | 128 | String[] choices = new String[opts.length()]; 129 | 130 | for (int i = 0; i < choices.length; i++) { 131 | choices[i] = opts.optString(i); 132 | } 133 | 134 | return choices; 135 | } 136 | 137 | } -------------------------------------------------------------------------------- /src/android/notification/action/ActionGroup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.notification.action; 23 | 24 | import android.content.Context; 25 | import android.util.Log; 26 | 27 | import org.json.JSONArray; 28 | import org.json.JSONObject; 29 | 30 | import java.util.ArrayList; 31 | import java.util.HashMap; 32 | import java.util.List; 33 | import java.util.Map; 34 | 35 | import static android.os.Build.VERSION.SDK_INT; 36 | import static android.os.Build.VERSION_CODES.N; 37 | 38 | public final class ActionGroup { 39 | 40 | // Saves all groups for later lookup. 41 | private static final Map groups = new HashMap(); 42 | 43 | // The ID of the action group. 44 | private final String id; 45 | 46 | // List of actions 47 | private final Action[] actions; 48 | 49 | /** 50 | * Lookup the action groups with the specified group id. 51 | * 52 | * @param id The ID of the action group to find. 53 | * 54 | * @return Null if no group was found. 55 | */ 56 | public static ActionGroup lookup(String id) { 57 | return groups.get(id); 58 | } 59 | 60 | /** 61 | * Register the action group for later lookup. 62 | * 63 | * @param group The action group to register. 64 | */ 65 | public static void register (ActionGroup group) { 66 | groups.put(group.getId(), group); 67 | } 68 | 69 | /** 70 | * Unregister the action group. 71 | * 72 | * @param id The id of the action group to remove. 73 | */ 74 | public static void unregister (String id) { 75 | groups.remove(id); 76 | } 77 | 78 | /** 79 | * Check if a action group with that id is registered. 80 | * 81 | * @param id The id of the action group to check for. 82 | */ 83 | public static boolean isRegistered (String id) { 84 | return groups.containsKey(id); 85 | } 86 | 87 | /** 88 | * Creates an action group by parsing the specified action specs. 89 | * 90 | * @param list The list of actions. 91 | * 92 | * @return A new action group. 93 | */ 94 | public static ActionGroup parse (Context context, JSONArray list) { 95 | return parse(context, null, list); 96 | } 97 | 98 | /** 99 | * Creates an action group by parsing the specified action specs. 100 | * 101 | * @param id The id for the action group. 102 | * @param list The list of actions. 103 | * 104 | * @return A new action group. 105 | */ 106 | public static ActionGroup parse (Context context, String id, JSONArray list) { 107 | List actions = new ArrayList(list.length()); 108 | 109 | for (int i = 0; i < list.length(); i++) { 110 | JSONObject opts = list.optJSONObject(i); 111 | String type = opts.optString("type", "button"); 112 | 113 | if (type.equals("input") && SDK_INT < N) { 114 | Log.w("Action", "Type input is not supported"); 115 | continue; 116 | } 117 | 118 | if (!(type.equals("button") || type.equals("input"))) { 119 | Log.w("Action", "Unknown type: " + type); 120 | continue; 121 | } 122 | 123 | actions.add(new Action(context, opts)); 124 | } 125 | 126 | return new ActionGroup(id, actions.toArray(new Action[actions.size()])); 127 | } 128 | 129 | /** 130 | * Creates an action group. 131 | * 132 | * @param id The ID of the group. 133 | * @param actions The list of actions. 134 | */ 135 | private ActionGroup(String id, Action[] actions) { 136 | this.id = id; 137 | this.actions = actions; 138 | } 139 | 140 | /** 141 | * Gets the action group id. 142 | */ 143 | public String getId() { 144 | return id; 145 | } 146 | 147 | /** 148 | * Gets the action list. 149 | */ 150 | public Action[] getActions() { 151 | return actions; 152 | } 153 | 154 | } -------------------------------------------------------------------------------- /src/android/notification/receiver/AbstractClearReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.notification.receiver; 23 | 24 | import android.content.BroadcastReceiver; 25 | import android.content.Context; 26 | import android.content.Intent; 27 | import android.os.Bundle; 28 | 29 | import de.appplant.cordova.plugin.notification.Manager; 30 | import de.appplant.cordova.plugin.notification.Notification; 31 | 32 | /** 33 | * Abstract delete receiver for local notifications. Creates the local 34 | * notification and calls the event functions for further proceeding. 35 | */ 36 | abstract public class AbstractClearReceiver extends BroadcastReceiver { 37 | 38 | /** 39 | * Called when the notification was cleared from the notification center. 40 | * 41 | * @param context Application context 42 | * @param intent Received intent with content data 43 | */ 44 | @Override 45 | public void onReceive(Context context, Intent intent) { 46 | Bundle bundle = intent.getExtras(); 47 | 48 | if (bundle == null) 49 | return; 50 | 51 | int toastId = bundle.getInt(Notification.EXTRA_ID); 52 | Notification toast = Manager.getInstance(context).get(toastId); 53 | 54 | if (toast == null) 55 | return; 56 | 57 | onClear(toast, bundle); 58 | } 59 | 60 | /** 61 | * Called when a local notification was cleared from outside of the app. 62 | * 63 | * @param notification Wrapper around the local notification. 64 | * @param bundle The bundled extras. 65 | */ 66 | abstract public void onClear (Notification notification, Bundle bundle); 67 | 68 | } 69 | -------------------------------------------------------------------------------- /src/android/notification/receiver/AbstractClickReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.notification.receiver; 23 | 24 | import android.app.IntentService; 25 | import android.content.Context; 26 | import android.content.Intent; 27 | import android.os.Bundle; 28 | 29 | import de.appplant.cordova.plugin.notification.Manager; 30 | import de.appplant.cordova.plugin.notification.Notification; 31 | 32 | import static android.content.Intent.FLAG_ACTIVITY_REORDER_TO_FRONT; 33 | import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP; 34 | import static de.appplant.cordova.plugin.notification.action.Action.CLICK_ACTION_ID; 35 | import static de.appplant.cordova.plugin.notification.action.Action.EXTRA_ID; 36 | 37 | /** 38 | * Abstract content receiver activity for local notifications. Creates the 39 | * local notification and calls the event functions for further proceeding. 40 | */ 41 | abstract public class AbstractClickReceiver extends IntentService { 42 | 43 | // Holds a reference to the intent to handle. 44 | private Intent intent; 45 | 46 | public AbstractClickReceiver() { 47 | super("LocalNotificationClickReceiver"); 48 | } 49 | 50 | /** 51 | * Called when local notification was clicked to launch the main intent. 52 | */ 53 | @Override 54 | protected void onHandleIntent(Intent intent) { 55 | this.intent = intent; 56 | 57 | if (intent == null) 58 | return; 59 | 60 | Bundle bundle = intent.getExtras(); 61 | Context context = getApplicationContext(); 62 | 63 | if (bundle == null) 64 | return; 65 | 66 | int toastId = bundle.getInt(Notification.EXTRA_ID); 67 | Notification toast = Manager.getInstance(context).get(toastId); 68 | 69 | if (toast == null) 70 | return; 71 | 72 | onClick(toast, bundle); 73 | this.intent = null; 74 | } 75 | 76 | /** 77 | * Called when local notification was clicked by the user. 78 | * 79 | * @param notification Wrapper around the local notification. 80 | * @param bundle The bundled extras. 81 | */ 82 | abstract public void onClick (Notification notification, Bundle bundle); 83 | 84 | /** 85 | * The invoked action. 86 | */ 87 | protected String getAction() { 88 | return getIntent().getExtras().getString(EXTRA_ID, CLICK_ACTION_ID); 89 | } 90 | 91 | /** 92 | * Getter for the received intent. 93 | */ 94 | protected Intent getIntent() { 95 | return intent; 96 | } 97 | 98 | /** 99 | * Launch main intent from package. 100 | */ 101 | protected void launchApp() { 102 | Context context = getApplicationContext(); 103 | String pkgName = context.getPackageName(); 104 | 105 | Intent intent = context 106 | .getPackageManager() 107 | .getLaunchIntentForPackage(pkgName); 108 | 109 | if (intent == null) 110 | return; 111 | 112 | intent.addFlags( 113 | FLAG_ACTIVITY_REORDER_TO_FRONT 114 | | FLAG_ACTIVITY_SINGLE_TOP); 115 | 116 | context.startActivity(intent); 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/android/notification/receiver/AbstractRestoreReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2014-2015 by appPlant UG. All rights reserved. 3 | * 4 | * @APPPLANT_LICENSE_HEADER_START@ 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | * 21 | * @APPPLANT_LICENSE_HEADER_END@ 22 | */ 23 | 24 | package de.appplant.cordova.plugin.notification.receiver; 25 | 26 | import android.content.BroadcastReceiver; 27 | import android.content.Context; 28 | import android.content.Intent; 29 | import android.os.UserManager; 30 | 31 | import org.json.JSONObject; 32 | 33 | import java.util.List; 34 | 35 | import de.appplant.cordova.plugin.notification.Builder; 36 | import de.appplant.cordova.plugin.notification.Manager; 37 | import de.appplant.cordova.plugin.notification.Notification; 38 | import de.appplant.cordova.plugin.notification.Options; 39 | import de.appplant.cordova.plugin.notification.Request; 40 | 41 | import static android.content.Intent.ACTION_BOOT_COMPLETED; 42 | import static android.os.Build.VERSION.SDK_INT; 43 | 44 | /** 45 | * This class is triggered upon reboot of the device. It needs to re-register 46 | * the alarms with the AlarmManager since these alarms are lost in case of 47 | * reboot. 48 | */ 49 | abstract public class AbstractRestoreReceiver extends BroadcastReceiver { 50 | 51 | /** 52 | * Called on device reboot. 53 | * 54 | * @param context Application context 55 | * @param intent Received intent with content data 56 | */ 57 | @Override 58 | public void onReceive (Context context, Intent intent) { 59 | String action = intent.getAction(); 60 | 61 | if (SDK_INT >= 24) { 62 | UserManager um = (UserManager) context.getSystemService(UserManager.class); 63 | if (um == null || um.isUserUnlocked() == false) return; 64 | } 65 | 66 | Manager mgr = Manager.getInstance(context); 67 | List toasts = mgr.getOptions(); 68 | 69 | for (JSONObject data : toasts) { 70 | Options options = new Options(context, data); 71 | Request request = new Request(options); 72 | Builder builder = new Builder(options); 73 | Notification toast = buildNotification(builder); 74 | 75 | onRestore(request, toast); 76 | } 77 | } 78 | 79 | /** 80 | * Called when a local notification need to be restored. 81 | * 82 | * @param request Set of notification options. 83 | * @param toast Wrapper around the local notification. 84 | */ 85 | abstract public void onRestore (Request request, Notification toast); 86 | 87 | /** 88 | * Build notification specified by options. 89 | * 90 | * @param builder Notification builder. 91 | */ 92 | abstract public Notification buildNotification (Builder builder); 93 | 94 | } 95 | -------------------------------------------------------------------------------- /src/android/notification/receiver/AbstractTriggerReceiver.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.notification.receiver; 23 | 24 | import android.content.BroadcastReceiver; 25 | import android.content.Context; 26 | import android.content.Intent; 27 | import android.os.Bundle; 28 | 29 | import de.appplant.cordova.plugin.notification.Builder; 30 | import de.appplant.cordova.plugin.notification.Manager; 31 | import de.appplant.cordova.plugin.notification.Notification; 32 | import de.appplant.cordova.plugin.notification.Options; 33 | 34 | /** 35 | * Abstract broadcast receiver for local notifications. Creates the 36 | * notification options and calls the event functions for further proceeding. 37 | */ 38 | abstract public class AbstractTriggerReceiver extends BroadcastReceiver { 39 | 40 | /** 41 | * Called when an alarm was triggered. 42 | * 43 | * @param context Application context 44 | * @param intent Received intent with content data 45 | */ 46 | @Override 47 | public void onReceive(Context context, Intent intent) { 48 | Bundle bundle = intent.getExtras(); 49 | 50 | if (bundle == null) 51 | return; 52 | 53 | int toastId = bundle.getInt(Notification.EXTRA_ID, 0); 54 | Options options = Manager.getInstance(context).getOptions(toastId); 55 | 56 | if (options == null) 57 | return; 58 | 59 | Builder builder = new Builder(options); 60 | Notification toast = buildNotification(builder, bundle); 61 | 62 | if (toast == null) 63 | return; 64 | 65 | onTrigger(toast, bundle); 66 | } 67 | 68 | /** 69 | * Called when a local notification was triggered. 70 | * 71 | * @param notification Wrapper around the local notification. 72 | * @param bundle The bundled extras. 73 | */ 74 | abstract public void onTrigger (Notification notification, Bundle bundle); 75 | 76 | /** 77 | * Build notification specified by options. 78 | * 79 | * @param builder Notification builder. 80 | * @param bundle The bundled extras. 81 | */ 82 | abstract public Notification buildNotification (Builder builder, 83 | Bundle bundle); 84 | 85 | } 86 | -------------------------------------------------------------------------------- /src/android/notification/trigger/DateTrigger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.notification.trigger; 23 | 24 | import java.util.Calendar; 25 | import java.util.Date; 26 | 27 | abstract public class DateTrigger { 28 | 29 | // Default unit is SECOND 30 | public enum Unit { SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR } 31 | 32 | // Internal counter 33 | private int occurrence = 1; 34 | 35 | /** 36 | * Gets the next trigger date. 37 | * 38 | * @param base The date from where to calculate the trigger date. 39 | * 40 | * @return null if there's none next trigger date. 41 | */ 42 | abstract public Date getNextTriggerDate(Date base); 43 | 44 | /** 45 | * The value of the occurrence. 46 | */ 47 | public int getOccurrence() { 48 | return occurrence; 49 | } 50 | 51 | /** 52 | * Increase the occurrence by 1. 53 | */ 54 | void incOccurrence() { 55 | occurrence += 1; 56 | } 57 | 58 | /** 59 | * Gets a calendar instance pointing to the specified date. 60 | * 61 | * @param date The date to point. 62 | */ 63 | Calendar getCal (Date date) { 64 | Calendar cal = Calendar.getInstance(); 65 | cal.setTime(date); 66 | 67 | return cal; 68 | } 69 | 70 | } -------------------------------------------------------------------------------- /src/android/notification/trigger/IntervalTrigger.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.notification.trigger; 23 | 24 | import java.util.Calendar; 25 | import java.util.Date; 26 | 27 | /** 28 | * Trigger class for interval based notification. Trigger by a fixed interval 29 | * from now. 30 | */ 31 | public class IntervalTrigger extends DateTrigger { 32 | 33 | // The number of ticks per interval 34 | private final int ticks; 35 | 36 | // The unit of the ticks 37 | final Unit unit; 38 | 39 | /** 40 | * Interval trigger based from now. 41 | * 42 | * @param ticks The number of ticks per interval. 43 | * @param unit The unit of the ticks. 44 | */ 45 | public IntervalTrigger(int ticks, Unit unit) { 46 | this.ticks = ticks; 47 | this.unit = unit; 48 | } 49 | 50 | /** 51 | * Gets the next trigger date. 52 | * 53 | * @param base The date from where to calculate the trigger date. 54 | * 55 | * @return null if there's none next trigger date. 56 | */ 57 | @Override 58 | public Date getNextTriggerDate(Date base) { 59 | Calendar cal = getCal(base); 60 | 61 | addInterval(cal); 62 | incOccurrence(); 63 | 64 | return cal.getTime(); 65 | } 66 | 67 | /** 68 | * Adds the amount of ticks to the calendar. 69 | * 70 | * @param cal The calendar to manipulate. 71 | */ 72 | void addInterval(Calendar cal) { 73 | switch (unit) { 74 | case SECOND: 75 | cal.add(Calendar.SECOND, ticks); 76 | break; 77 | case MINUTE: 78 | cal.add(Calendar.MINUTE, ticks); 79 | break; 80 | case HOUR: 81 | cal.add(Calendar.HOUR_OF_DAY, ticks); 82 | break; 83 | case DAY: 84 | cal.add(Calendar.DAY_OF_YEAR, ticks); 85 | break; 86 | case WEEK: 87 | cal.add(Calendar.WEEK_OF_YEAR, ticks); 88 | break; 89 | case MONTH: 90 | cal.add(Calendar.MONTH, ticks); 91 | break; 92 | case QUARTER: 93 | cal.add(Calendar.MONTH, ticks * 3); 94 | break; 95 | case YEAR: 96 | cal.add(Calendar.YEAR, ticks); 97 | break; 98 | } 99 | } 100 | 101 | } -------------------------------------------------------------------------------- /src/android/notification/util/AssetProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | Licensed to the Apache Software Foundation (ASF) under one 3 | or more contributor license agreements. See the NOTICE file 4 | distributed with this work for additional information 5 | regarding copyright ownership. The ASF licenses this file 6 | to you under the Apache License, Version 2.0 (the 7 | "License"); you may not use this file except in compliance 8 | with the License. You may obtain a copy of the License at 9 | 10 | http://www.apache.org/licenses/LICENSE-2.0 11 | 12 | Unless required by applicable law or agreed to in writing, 13 | software distributed under the License is distributed on an 14 | "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | KIND, either express or implied. See the License for the 16 | specific language governing permissions and limitations 17 | under the License. 18 | */ 19 | 20 | package de.appplant.cordova.plugin.notification.util; 21 | 22 | import android.support.v4.content.FileProvider; 23 | 24 | public class AssetProvider extends FileProvider { 25 | // Nothing to do here 26 | } -------------------------------------------------------------------------------- /src/android/notification/util/AssetUtil.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | package de.appplant.cordova.plugin.notification.util; 23 | 24 | import android.content.ContentResolver; 25 | import android.content.Context; 26 | import android.content.res.AssetManager; 27 | import android.content.res.Resources; 28 | import android.graphics.Bitmap; 29 | import android.graphics.BitmapFactory; 30 | import android.net.Uri; 31 | import android.os.StrictMode; 32 | import android.util.Log; 33 | 34 | import java.io.File; 35 | import java.io.FileNotFoundException; 36 | import java.io.FileOutputStream; 37 | import java.io.IOException; 38 | import java.io.InputStream; 39 | import java.net.HttpURLConnection; 40 | import java.net.MalformedURLException; 41 | import java.net.URL; 42 | import java.util.UUID; 43 | 44 | /** 45 | * Util class to map unified asset URIs to native URIs. URIs like file:/// 46 | * map to absolute paths while file:// point relatively to the www folder 47 | * within the asset resources. And res:// means a resource from the native 48 | * res folder. Remote assets are accessible via http:// for example. 49 | */ 50 | public final class AssetUtil { 51 | 52 | // Name of the storage folder 53 | private static final String STORAGE_FOLDER = "/localnotification"; 54 | 55 | // Ref to the context passed through the constructor to access the 56 | // resources and app directory. 57 | private final Context context; 58 | 59 | /** 60 | * Constructor 61 | * 62 | * @param context Application context. 63 | */ 64 | private AssetUtil(Context context) { 65 | this.context = context; 66 | } 67 | 68 | /** 69 | * Static method to retrieve class instance. 70 | * 71 | * @param context Application context. 72 | */ 73 | public static AssetUtil getInstance(Context context) { 74 | return new AssetUtil(context); 75 | } 76 | 77 | /** 78 | * The URI for a path. 79 | * 80 | * @param path The given path. 81 | */ 82 | public Uri parse (String path) { 83 | if (path == null || path.isEmpty()) { 84 | return Uri.EMPTY; 85 | } else if (path.startsWith("res:")) { 86 | return getUriForResourcePath(path); 87 | } else if (path.startsWith("file:///")) { 88 | return getUriFromPath(path); 89 | } else if (path.startsWith("file://")) { 90 | return getUriFromAsset(path); 91 | } else if (path.startsWith("http")){ 92 | return getUriFromRemote(path); 93 | } else if (path.startsWith("content://")){ 94 | return Uri.parse(path); 95 | } 96 | 97 | return Uri.EMPTY; 98 | } 99 | 100 | /** 101 | * URI for a file. 102 | * 103 | * @param path Absolute path like file:///... 104 | * 105 | * @return URI pointing to the given path. 106 | */ 107 | private Uri getUriFromPath(String path) { 108 | String absPath = path.replaceFirst("file://", "") 109 | .replaceFirst("\\?.*$", ""); 110 | File file = new File(absPath); 111 | 112 | if (!file.exists()) { 113 | Log.e("Asset", "File not found: " + file.getAbsolutePath()); 114 | return Uri.EMPTY; 115 | } 116 | 117 | return getUriFromFile(file); 118 | } 119 | 120 | /** 121 | * URI for an asset. 122 | * 123 | * @param path Asset path like file://... 124 | * 125 | * @return URI pointing to the given path. 126 | */ 127 | private Uri getUriFromAsset(String path) { 128 | String resPath = path.replaceFirst("file:/", "www") 129 | .replaceFirst("\\?.*$", ""); 130 | String fileName = resPath.substring(resPath.lastIndexOf('/') + 1); 131 | File file = getTmpFile(fileName); 132 | 133 | if (file == null) 134 | return Uri.EMPTY; 135 | 136 | try { 137 | AssetManager assets = context.getAssets(); 138 | InputStream in = assets.open(resPath); 139 | FileOutputStream out = new FileOutputStream(file); 140 | copyFile(in, out); 141 | } catch (Exception e) { 142 | Log.e("Asset", "File not found: assets/" + resPath); 143 | e.printStackTrace(); 144 | return Uri.EMPTY; 145 | } 146 | 147 | return getUriFromFile(file); 148 | } 149 | 150 | /** 151 | * The URI for a resource. 152 | * 153 | * @param path The given relative path. 154 | * 155 | * @return URI pointing to the given path. 156 | */ 157 | private Uri getUriForResourcePath(String path) { 158 | Resources res = context.getResources(); 159 | String resPath = path.replaceFirst("res://", ""); 160 | int resId = getResId(resPath); 161 | 162 | if (resId == 0) { 163 | Log.e("Asset", "File not found: " + resPath); 164 | return Uri.EMPTY; 165 | } 166 | 167 | return new Uri.Builder() 168 | .scheme(ContentResolver.SCHEME_ANDROID_RESOURCE) 169 | .authority(res.getResourcePackageName(resId)) 170 | .appendPath(res.getResourceTypeName(resId)) 171 | .appendPath(res.getResourceEntryName(resId)) 172 | .build(); 173 | } 174 | 175 | /** 176 | * Uri from remote located content. 177 | * 178 | * @param path Remote address. 179 | * 180 | * @return Uri of the downloaded file. 181 | */ 182 | private Uri getUriFromRemote(String path) { 183 | File file = getTmpFile(); 184 | 185 | if (file == null) 186 | return Uri.EMPTY; 187 | 188 | try { 189 | URL url = new URL(path); 190 | HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 191 | 192 | StrictMode.ThreadPolicy policy = 193 | new StrictMode.ThreadPolicy.Builder().permitAll().build(); 194 | 195 | StrictMode.setThreadPolicy(policy); 196 | 197 | connection.setRequestProperty("Connection", "close"); 198 | connection.setConnectTimeout(5000); 199 | connection.connect(); 200 | 201 | InputStream in = connection.getInputStream(); 202 | FileOutputStream out = new FileOutputStream(file); 203 | 204 | copyFile(in, out); 205 | return getUriFromFile(file); 206 | } catch (MalformedURLException e) { 207 | Log.e("Asset", "Incorrect URL"); 208 | e.printStackTrace(); 209 | } catch (FileNotFoundException e) { 210 | Log.e("Asset", "Failed to create new File from HTTP Content"); 211 | e.printStackTrace(); 212 | } catch (IOException e) { 213 | Log.e("Asset", "No Input can be created from http Stream"); 214 | e.printStackTrace(); 215 | } 216 | 217 | return Uri.EMPTY; 218 | } 219 | 220 | /** 221 | * Copy content from input stream into output stream. 222 | * 223 | * @param in The input stream. 224 | * @param out The output stream. 225 | */ 226 | private void copyFile(InputStream in, FileOutputStream out) { 227 | byte[] buffer = new byte[1024]; 228 | int read; 229 | 230 | try { 231 | while ((read = in.read(buffer)) != -1) { 232 | out.write(buffer, 0, read); 233 | } 234 | out.flush(); 235 | out.close(); 236 | } catch (Exception e) { 237 | e.printStackTrace(); 238 | } 239 | } 240 | 241 | /** 242 | * Resource ID for drawable. 243 | * 244 | * @param resPath Resource path as string. 245 | * 246 | * @return The resource ID or 0 if not found. 247 | */ 248 | public int getResId(String resPath) { 249 | int resId = getResId(context.getResources(), resPath); 250 | 251 | if (resId == 0) { 252 | resId = getResId(Resources.getSystem(), resPath); 253 | } 254 | 255 | return resId; 256 | } 257 | 258 | /** 259 | * Get resource ID. 260 | * 261 | * @param res The resources where to look for. 262 | * @param resPath The name of the resource. 263 | * 264 | * @return The resource ID or 0 if not found. 265 | */ 266 | private int getResId(Resources res, String resPath) { 267 | String pkgName = getPkgName(res); 268 | String resName = getBaseName(resPath); 269 | int resId; 270 | 271 | resId = res.getIdentifier(resName, "mipmap", pkgName); 272 | 273 | if (resId == 0) { 274 | resId = res.getIdentifier(resName, "drawable", pkgName); 275 | } 276 | 277 | if (resId == 0) { 278 | resId = res.getIdentifier(resName, "raw", pkgName); 279 | } 280 | 281 | return resId; 282 | } 283 | 284 | /** 285 | * Convert URI to Bitmap. 286 | * 287 | * @param uri Internal image URI 288 | */ 289 | public Bitmap getIconFromUri(Uri uri) throws IOException { 290 | InputStream input = context.getContentResolver().openInputStream(uri); 291 | return BitmapFactory.decodeStream(input); 292 | } 293 | 294 | /** 295 | * Extract name of drawable resource from path. 296 | * 297 | * @param resPath Resource path as string. 298 | */ 299 | private String getBaseName (String resPath) { 300 | String drawable = resPath; 301 | 302 | if (drawable.contains("/")) { 303 | drawable = drawable.substring(drawable.lastIndexOf('/') + 1); 304 | } 305 | 306 | if (resPath.contains(".")) { 307 | drawable = drawable.substring(0, drawable.lastIndexOf('.')); 308 | } 309 | 310 | return drawable; 311 | } 312 | 313 | /** 314 | * Returns a file located under the external cache dir of that app. 315 | * 316 | * @return File with a random UUID name. 317 | */ 318 | private File getTmpFile () { 319 | // If random UUID is not be enough see 320 | // https://github.com/LukePulverenti/cordova-plugin-local-notifications/blob/267170db14044cbeff6f4c3c62d9b766b7a1dd62/src/android/notification/AssetUtil.java#L255 321 | return getTmpFile(UUID.randomUUID().toString()); 322 | } 323 | 324 | /** 325 | * Returns a file located under the external cache dir of that app. 326 | * 327 | * @param name The name of the file. 328 | * 329 | * @return File with the provided name. 330 | */ 331 | private File getTmpFile (String name) { 332 | File dir = context.getExternalCacheDir(); 333 | 334 | if (dir == null) { 335 | dir = context.getCacheDir(); 336 | } 337 | 338 | if (dir == null) { 339 | Log.e("Asset", "Missing cache dir"); 340 | return null; 341 | } 342 | 343 | String storage = dir.toString() + STORAGE_FOLDER; 344 | 345 | //noinspection ResultOfMethodCallIgnored 346 | new File(storage).mkdir(); 347 | 348 | return new File(storage, name); 349 | } 350 | 351 | /** 352 | * Get content URI for the specified file. 353 | * 354 | * @param file The file to get the URI. 355 | * 356 | * @return content://... 357 | */ 358 | private Uri getUriFromFile(File file) { 359 | try { 360 | String authority = context.getPackageName() + ".localnotifications.provider"; 361 | return AssetProvider.getUriForFile(context, authority, file); 362 | } catch (IllegalArgumentException e) { 363 | e.printStackTrace(); 364 | return Uri.EMPTY; 365 | } 366 | } 367 | 368 | /** 369 | * Package name specified by the resource bundle. 370 | */ 371 | private String getPkgName (Resources res) { 372 | return res == Resources.getSystem() ? "android" : context.getPackageName(); 373 | } 374 | 375 | } 376 | -------------------------------------------------------------------------------- /src/android/xml/localnotification_provider_paths.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/ios/APPLocalNotification.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | #import 23 | 24 | @import UserNotifications; 25 | 26 | @interface APPLocalNotification : CDVPlugin 27 | 28 | - (void) launch:(CDVInvokedUrlCommand*)command; 29 | - (void) ready:(CDVInvokedUrlCommand*)command; 30 | 31 | - (void) actions:(CDVInvokedUrlCommand*)command; 32 | 33 | - (void) check:(CDVInvokedUrlCommand*)command; 34 | - (void) request:(CDVInvokedUrlCommand*)command; 35 | 36 | - (void) schedule:(CDVInvokedUrlCommand*)command; 37 | - (void) update:(CDVInvokedUrlCommand*)command; 38 | 39 | - (void) clear:(CDVInvokedUrlCommand*)command; 40 | - (void) clearAll:(CDVInvokedUrlCommand*)command; 41 | 42 | - (void) cancel:(CDVInvokedUrlCommand*)command; 43 | - (void) cancelAll:(CDVInvokedUrlCommand*)command; 44 | 45 | - (void) type:(CDVInvokedUrlCommand*)command; 46 | 47 | - (void) ids:(CDVInvokedUrlCommand*)command; 48 | 49 | - (void) notification:(CDVInvokedUrlCommand*)command; 50 | - (void) notifications:(CDVInvokedUrlCommand*)command; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /src/ios/APPNotificationCategory.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | @import UserNotifications; 23 | 24 | @interface APPNotificationCategory : NSObject 25 | 26 | + (UNNotificationCategory*) parse:(NSArray*)list withId:(NSString*)groupId; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /src/ios/APPNotificationCategory.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | #import "APPNotificationCategory.h" 23 | 24 | @import UserNotifications; 25 | 26 | @implementation APPNotificationCategory : NSObject 27 | 28 | #pragma mark - 29 | #pragma mark Public 30 | 31 | /** 32 | * Parse the provided spec map into an action group. 33 | * 34 | * @param [ NSDictionary* ] spec A key-value property map. 35 | * Must contain an id and a list of actions. 36 | * 37 | * @return [ UNNotificationCategory* ] 38 | */ 39 | + (UNNotificationCategory*) parse:(NSArray*)list withId:(NSString*)groupId 40 | { 41 | NSArray* actions = [self parseActions:list]; 42 | 43 | return [UNNotificationCategory categoryWithIdentifier:groupId 44 | actions:actions 45 | intentIdentifiers:@[] 46 | options:UNNotificationCategoryOptionCustomDismissAction]; 47 | } 48 | 49 | #pragma mark - 50 | #pragma mark Private 51 | 52 | /** 53 | * The actions of the action group. 54 | * 55 | * @return [ NSArray* ] 56 | */ 57 | + (NSArray *) parseActions:(NSArray*)items 58 | { 59 | NSMutableArray* actions = [[NSMutableArray alloc] init]; 60 | 61 | for (NSDictionary* item in items) { 62 | NSString* id = item[@"id"]; 63 | NSString* title = item[@"title"]; 64 | NSString* type = item[@"type"]; 65 | 66 | UNNotificationActionOptions options = UNNotificationActionOptionNone; 67 | UNNotificationAction* action; 68 | 69 | if ([item[@"launch"] boolValue]) { 70 | options = UNNotificationActionOptionForeground; 71 | } 72 | 73 | if ([item[@"ui"] isEqualToString:@"decline"]) { 74 | options = options | UNNotificationActionOptionDestructive; 75 | } 76 | 77 | if ([item[@"needsAuth"] boolValue]) { 78 | options = options | UNNotificationActionOptionAuthenticationRequired; 79 | } 80 | 81 | if ([type isEqualToString:@"input"]) { 82 | NSString* submitTitle = item[@"submitTitle"]; 83 | NSString* placeholder = item[@"emptyText"]; 84 | 85 | if (!submitTitle.length) { 86 | submitTitle = @"Submit"; 87 | } 88 | 89 | action = [UNTextInputNotificationAction actionWithIdentifier:id 90 | title:title 91 | options:options 92 | textInputButtonTitle:submitTitle 93 | textInputPlaceholder:placeholder]; 94 | } else 95 | if (!type.length || [type isEqualToString:@"button"]) { 96 | action = [UNNotificationAction actionWithIdentifier:id 97 | title:title 98 | options:options]; 99 | } else { 100 | NSLog(@"Unknown action type: %@", type); 101 | } 102 | 103 | if (action) { 104 | [actions addObject:action]; 105 | } 106 | } 107 | 108 | return actions; 109 | } 110 | 111 | @end 112 | -------------------------------------------------------------------------------- /src/ios/APPNotificationContent.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | #import "APPNotificationOptions.h" 23 | 24 | @import UserNotifications; 25 | 26 | @interface APPNotificationContent : UNMutableNotificationContent 27 | 28 | - (id) initWithOptions:(NSDictionary*)dict; 29 | - (APPNotificationOptions*) options; 30 | - (UNNotificationRequest*) request; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /src/ios/APPNotificationContent.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | #import "APPNotificationContent.h" 23 | #import "APPNotificationOptions.h" 24 | #import 25 | 26 | @import UserNotifications; 27 | 28 | static char optionsKey; 29 | 30 | @implementation APPNotificationContent : UNMutableNotificationContent 31 | 32 | #pragma mark - 33 | #pragma mark Init 34 | 35 | /** 36 | * Initialize a notification with the given options. 37 | * 38 | * @param [ NSDictionary* ] dict A key-value property map. 39 | * 40 | * @return [ UNMutableNotificationContent ] 41 | */ 42 | - (id) initWithOptions:(NSDictionary*)dict 43 | { 44 | self = [self init]; 45 | 46 | [self setUserInfo:dict]; 47 | [self __init]; 48 | 49 | return self; 50 | } 51 | 52 | /** 53 | * Initialize a notification by using the options found under userInfo. 54 | * 55 | * @return [ Void ] 56 | */ 57 | - (void) __init 58 | { 59 | APPNotificationOptions* options = self.options; 60 | 61 | self.title = options.title; 62 | self.subtitle = options.subtitle; 63 | self.body = options.text; 64 | self.sound = options.sound; 65 | self.badge = options.badge; 66 | self.attachments = options.attachments; 67 | self.categoryIdentifier = options.actionGroupId; 68 | } 69 | 70 | #pragma mark - 71 | #pragma mark Public 72 | 73 | /** 74 | * The options used to initialize the notification. 75 | * 76 | * @return [ APPNotificationOptions* ] options 77 | */ 78 | - (APPNotificationOptions*) options 79 | { 80 | APPNotificationOptions* options = [self getOptions]; 81 | 82 | if (!options) { 83 | options = [[APPNotificationOptions alloc] 84 | initWithDict:[self userInfo]]; 85 | 86 | [self setOptions:options]; 87 | } 88 | 89 | return options; 90 | } 91 | 92 | /** 93 | * The notifcations request ready to add to the notification center including 94 | * all informations about trigger behavior. 95 | * 96 | * @return [ UNNotificationRequest* ] 97 | */ 98 | - (UNNotificationRequest*) request 99 | { 100 | APPNotificationOptions* opts = [self getOptions]; 101 | 102 | return [UNNotificationRequest requestWithIdentifier:opts.identifier 103 | content:self 104 | trigger:opts.trigger]; 105 | } 106 | 107 | #pragma mark - 108 | #pragma mark Private 109 | 110 | /** 111 | * The options used to initialize the notification. 112 | * 113 | * @return [ APPNotificationOptions* ] 114 | */ 115 | - (APPNotificationOptions*) getOptions 116 | { 117 | return objc_getAssociatedObject(self, &optionsKey); 118 | } 119 | 120 | /** 121 | * Set the options used to initialize the notification. 122 | * 123 | * @param [ NSDictionary* ] dict A key-value property map. 124 | * 125 | * @return [ Void ] 126 | */ 127 | - (void) setOptions:(APPNotificationOptions*)options 128 | { 129 | objc_setAssociatedObject(self, &optionsKey, 130 | options, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 131 | } 132 | 133 | @end 134 | -------------------------------------------------------------------------------- /src/ios/APPNotificationOptions.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | @import UserNotifications; 23 | 24 | @interface APPNotificationOptions : NSObject 25 | 26 | @property (readonly, getter=id) NSNumber* id; 27 | @property (readonly, getter=identifier) NSString* identifier; 28 | @property (readonly, getter=actionGroupId) NSString* actionGroupId; 29 | @property (readonly, getter=title) NSString* title; 30 | @property (readonly, getter=subtitle) NSString* subtitle; 31 | @property (readonly, getter=badge) NSNumber* badge; 32 | @property (readonly, getter=text) NSString* text; 33 | @property (readonly, getter=silent) BOOL silent; 34 | @property (readonly, getter=priority) int priority; 35 | @property (readonly, getter=sound) UNNotificationSound* sound; 36 | @property (readonly, getter=userInfo) NSDictionary* userInfo; 37 | @property (readonly, getter=attachments) NSArray*attachments; 38 | 39 | - (id) initWithDict:(NSDictionary*) dict; 40 | - (UNNotificationTrigger*) trigger; 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /src/ios/UNNotificationRequest+APPLocalNotification.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | #import "APPNotificationOptions.h" 23 | 24 | @import UserNotifications; 25 | 26 | @interface UNNotificationRequest (APPLocalNotification) 27 | 28 | - (APPNotificationOptions*) options; 29 | - (BOOL) wasUpdated; 30 | - (NSString*) encodeToJSON; 31 | 32 | @end 33 | -------------------------------------------------------------------------------- /src/ios/UNNotificationRequest+APPLocalNotification.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | #import "APPNotificationOptions.h" 23 | #import "UNNotificationRequest+APPLocalNotification.h" 24 | #import "APPNotificationContent.h" 25 | #import 26 | 27 | @import UserNotifications; 28 | 29 | static char optionsKey; 30 | 31 | @implementation UNNotificationRequest (APPLocalNotification) 32 | 33 | /** 34 | * Get associated option object 35 | */ 36 | - (APPNotificationOptions*) getOptions 37 | { 38 | return objc_getAssociatedObject(self, &optionsKey); 39 | } 40 | 41 | /** 42 | * Set associated option object 43 | */ 44 | - (void) setOptions:(APPNotificationOptions*)options 45 | { 46 | objc_setAssociatedObject(self, &optionsKey, 47 | options, OBJC_ASSOCIATION_RETAIN_NONATOMIC); 48 | } 49 | 50 | /** 51 | * The options provided by the plug-in. 52 | */ 53 | - (APPNotificationOptions*) options 54 | { 55 | APPNotificationOptions* options = [self getOptions]; 56 | 57 | if (!options) { 58 | options = [[APPNotificationOptions alloc] 59 | initWithDict:[self.content userInfo]]; 60 | 61 | [self setOptions:options]; 62 | } 63 | 64 | return options; 65 | } 66 | 67 | /** 68 | * If the notification was updated. 69 | * 70 | * @return [ BOOL ] 71 | */ 72 | - (BOOL) wasUpdated 73 | { 74 | return [self.content userInfo][@"updatedAt"] != NULL; 75 | } 76 | 77 | /** 78 | * Encode the user info dict to JSON. 79 | */ 80 | - (NSString*) encodeToJSON 81 | { 82 | NSString* json; 83 | NSData* data; 84 | NSMutableDictionary* obj = [self.content.userInfo mutableCopy]; 85 | 86 | [obj removeObjectForKey:@"updatedAt"]; 87 | 88 | if (obj == NULL || obj.count == 0) 89 | return json; 90 | 91 | data = [NSJSONSerialization dataWithJSONObject:obj 92 | options:NSJSONWritingPrettyPrinted 93 | error:NULL]; 94 | 95 | json = [[NSString alloc] initWithData:data 96 | encoding:NSUTF8StringEncoding]; 97 | 98 | return [json stringByReplacingOccurrencesOfString:@"\n" 99 | withString:@""]; 100 | } 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /src/ios/UNUserNotificationCenter+APPLocalNotification.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | #import "APPNotificationContent.h" 23 | 24 | @interface UNUserNotificationCenter (APPLocalNotification) 25 | 26 | extern NSString * const kAPPGeneralCategory; 27 | 28 | typedef NS_ENUM(NSUInteger, APPNotificationType) { 29 | NotifcationTypeAll = 0, 30 | NotifcationTypeScheduled = 1, 31 | NotifcationTypeTriggered = 2, 32 | NotifcationTypeUnknown = 3 33 | }; 34 | 35 | #define APPNotificationType_DEFINED 36 | 37 | @property (readonly, getter=getNotifications) NSArray* localNotifications; 38 | @property (readonly, getter=getNotificationIds) NSArray* localNotificationIds; 39 | 40 | - (void) registerGeneralNotificationCategory; 41 | - (void) addActionGroup:(UNNotificationCategory*)category; 42 | - (void) removeActionGroup:(NSString*)identifier; 43 | - (BOOL) hasActionGroup:(NSString*)identifier; 44 | 45 | - (NSArray*) getNotificationIdsByType:(APPNotificationType)type; 46 | 47 | - (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id; 48 | - (APPNotificationType) getTypeOfNotificationWithId:(NSNumber*)id; 49 | 50 | - (NSArray*) getNotificationOptions; 51 | - (NSArray*) getNotificationOptionsById:(NSArray*)ids; 52 | - (NSArray*) getNotificationOptionsByType:(APPNotificationType)type; 53 | 54 | - (void) clearNotification:(UNNotificationRequest*)notification; 55 | - (void) clearNotifications; 56 | 57 | - (void) cancelNotification:(UNNotificationRequest*)notification; 58 | - (void) cancelNotifications; 59 | 60 | @end 61 | -------------------------------------------------------------------------------- /src/ios/UNUserNotificationCenter+APPLocalNotification.m: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | #import "UNUserNotificationCenter+APPLocalNotification.h" 23 | #import "UNNotificationRequest+APPLocalNotification.h" 24 | 25 | @import UserNotifications; 26 | 27 | NSString * const kAPPGeneralCategory = @"GENERAL"; 28 | 29 | @implementation UNUserNotificationCenter (APPLocalNotification) 30 | 31 | #pragma mark - 32 | #pragma mark NotificationCategory 33 | 34 | /** 35 | * Register general notification category to listen for dismiss actions. 36 | * 37 | * @return [ Void ] 38 | */ 39 | - (void) registerGeneralNotificationCategory 40 | { 41 | UNNotificationCategory* category; 42 | 43 | category = [UNNotificationCategory 44 | categoryWithIdentifier:kAPPGeneralCategory 45 | actions:@[] 46 | intentIdentifiers:@[] 47 | options:UNNotificationCategoryOptionCustomDismissAction]; 48 | 49 | [self setNotificationCategories:[NSSet setWithObject:category]]; 50 | } 51 | 52 | /** 53 | * Add the specified category to the list of categories. 54 | * 55 | * @param [ UNNotificationCategory* ] category The category to add. 56 | * 57 | * @return [ Void ] 58 | */ 59 | - (void) addActionGroup:(UNNotificationCategory*)category 60 | { 61 | if (!category) 62 | return; 63 | 64 | [self getNotificationCategoriesWithCompletionHandler:^(NSSet *set) { 65 | NSMutableSet* categories = [NSMutableSet setWithSet:set]; 66 | 67 | for (UNNotificationCategory* item in categories) 68 | { 69 | if ([category.identifier isEqualToString:item.identifier]) { 70 | [categories removeObject:item]; 71 | break; 72 | } 73 | } 74 | 75 | [categories addObject:category]; 76 | [self setNotificationCategories:categories]; 77 | }]; 78 | } 79 | 80 | /** 81 | * Remove if the specified category does exist. 82 | * 83 | * @param [ NSString* ] identifier The category id to remove. 84 | * 85 | * @return [ Void ] 86 | */ 87 | - (void) removeActionGroup:(NSString*)identifier 88 | { 89 | [self getNotificationCategoriesWithCompletionHandler:^(NSSet *set) { 90 | NSMutableSet* categories = [NSMutableSet setWithSet:set]; 91 | 92 | for (UNNotificationCategory* item in categories) 93 | { 94 | if ([item.identifier isEqualToString:identifier]) { 95 | [categories removeObject:item]; 96 | break; 97 | } 98 | } 99 | 100 | [self setNotificationCategories:categories]; 101 | }]; 102 | } 103 | 104 | /** 105 | * Check if the specified category does exist. 106 | * 107 | * @param [ NSString* ] identifier The category id to check for. 108 | * 109 | * @return [ BOOL ] 110 | */ 111 | - (BOOL) hasActionGroup:(NSString*)identifier 112 | { 113 | dispatch_semaphore_t sema = dispatch_semaphore_create(0); 114 | __block BOOL found = NO; 115 | 116 | [self getNotificationCategoriesWithCompletionHandler:^(NSSet *items) { 117 | for (UNNotificationCategory* item in items) 118 | { 119 | if ([item.identifier isEqualToString:identifier]) { 120 | found = YES; 121 | dispatch_semaphore_signal(sema); 122 | break; 123 | } 124 | } 125 | }]; 126 | 127 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 128 | 129 | return found; 130 | } 131 | 132 | #pragma mark - 133 | #pragma mark LocalNotifications 134 | 135 | /** 136 | * List of all delivered or still pending notifications. 137 | * 138 | * @return [ NSArray* ] 139 | */ 140 | - (NSArray*) getNotifications 141 | { 142 | NSMutableArray* notifications = [[NSMutableArray alloc] init]; 143 | 144 | [notifications addObjectsFromArray:[self getPendingNotifications]]; 145 | [notifications addObjectsFromArray:[self getDeliveredNotifications]]; 146 | 147 | return notifications; 148 | } 149 | 150 | /** 151 | * List of all triggered notifications. 152 | * 153 | * @return [ NSArray* ] 154 | */ 155 | - (NSArray*) getDeliveredNotifications 156 | { 157 | NSMutableArray* notifications = [[NSMutableArray alloc] init]; 158 | dispatch_semaphore_t sema = dispatch_semaphore_create(0); 159 | 160 | [self getDeliveredNotificationsWithCompletionHandler:^(NSArray *delivered) { 161 | for (UNNotification* notification in delivered) 162 | { 163 | [notifications addObject:notification.request]; 164 | } 165 | dispatch_semaphore_signal(sema); 166 | }]; 167 | 168 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 169 | 170 | return notifications; 171 | } 172 | 173 | /** 174 | * List of all pending notifications. 175 | * 176 | * @return [ NSArray* ] 177 | */ 178 | - (NSArray*) getPendingNotifications 179 | { 180 | NSMutableArray* notifications = [[NSMutableArray alloc] init]; 181 | dispatch_semaphore_t sema = dispatch_semaphore_create(0); 182 | 183 | [self getPendingNotificationRequestsWithCompletionHandler:^(NSArray *requests) { 184 | [notifications addObjectsFromArray:requests]; 185 | dispatch_semaphore_signal(sema); 186 | }]; 187 | 188 | dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER); 189 | 190 | return notifications; 191 | } 192 | 193 | /** 194 | * List of all notifications from given type. 195 | * 196 | * @param [ APPNotificationType ] type Notification life cycle type. 197 | * 198 | * @return [ NSArray* ] 199 | */ 200 | - (NSArray*) getNotificationsByType:(APPNotificationType)type 201 | { 202 | switch (type) { 203 | case NotifcationTypeScheduled: 204 | return [self getPendingNotifications]; 205 | 206 | case NotifcationTypeTriggered: 207 | return [self getDeliveredNotifications]; 208 | 209 | default: 210 | return [self getNotifications]; 211 | } 212 | } 213 | 214 | /** 215 | * List of all local notifications IDs. 216 | * 217 | * @return [ NSArray* ] 218 | */ 219 | - (NSArray*) getNotificationIds 220 | { 221 | NSArray* notifications = [self getNotifications]; 222 | NSMutableArray* ids = [[NSMutableArray alloc] init]; 223 | 224 | for (UNNotificationRequest* notification in notifications) 225 | { 226 | [ids addObject:notification.options.id]; 227 | } 228 | 229 | return ids; 230 | } 231 | 232 | /** 233 | * List of all notifications IDs from given type. 234 | * 235 | * @param [ APPNotificationType ] type Notification life cycle type. 236 | * 237 | * @return [ NSArray* ] 238 | */ 239 | - (NSArray*) getNotificationIdsByType:(APPNotificationType)type 240 | { 241 | NSArray* notifications = [self getNotificationsByType:type]; 242 | NSMutableArray* ids = [[NSMutableArray alloc] init]; 243 | 244 | for (UNNotificationRequest* notification in notifications) 245 | { 246 | [ids addObject:notification.options.id]; 247 | } 248 | 249 | return ids; 250 | } 251 | 252 | /** 253 | * Find notification by ID. 254 | * 255 | * @param id Notification ID 256 | * 257 | * @return [ UNNotificationRequest* ] 258 | */ 259 | - (UNNotificationRequest*) getNotificationWithId:(NSNumber*)id 260 | { 261 | NSArray* notifications = [self getNotifications]; 262 | 263 | for (UNNotificationRequest* notification in notifications) 264 | { 265 | NSString* fid = [NSString stringWithFormat:@"%@", notification.options.id]; 266 | 267 | if ([fid isEqualToString:[id stringValue]]) { 268 | return notification; 269 | } 270 | } 271 | 272 | return NULL; 273 | } 274 | 275 | /** 276 | * Find notification type by ID. 277 | * 278 | * @param [ NSNumber* ] id The ID of the notification. 279 | * 280 | * @return [ APPNotificationType ] 281 | */ 282 | - (APPNotificationType) getTypeOfNotificationWithId:(NSNumber*)id 283 | { 284 | NSArray* ids = [self getNotificationIdsByType:NotifcationTypeTriggered]; 285 | 286 | if ([ids containsObject:id]) 287 | return NotifcationTypeTriggered; 288 | 289 | ids = [self getNotificationIdsByType:NotifcationTypeScheduled]; 290 | 291 | if ([ids containsObject:id]) 292 | return NotifcationTypeScheduled; 293 | 294 | return NotifcationTypeUnknown; 295 | } 296 | 297 | /** 298 | * List of properties from all notifications. 299 | * 300 | * @return [ NSArray* ] 301 | */ 302 | - (NSArray*) getNotificationOptions 303 | { 304 | return [self getNotificationOptionsByType:NotifcationTypeAll]; 305 | } 306 | 307 | /** 308 | * List of properties from all notifications of given type. 309 | * 310 | * @param [ APPNotificationType ] type Notification life cycle type. 311 | * 312 | * @return [ NSArray* ] 313 | */ 314 | - (NSArray*) getNotificationOptionsByType:(APPNotificationType)type 315 | { 316 | NSArray* notifications = [self getNotificationsByType:type]; 317 | NSMutableArray* options = [[NSMutableArray alloc] init]; 318 | 319 | for (UNNotificationRequest* notification in notifications) 320 | { 321 | [options addObject:notification.options.userInfo]; 322 | } 323 | 324 | return options; 325 | } 326 | 327 | /** 328 | * List of properties from given local notifications. 329 | * 330 | * @param [ NSArray ] ids The ids of the notifications to find. 331 | * 332 | * @return [ NSArray* ] 333 | */ 334 | - (NSArray*) getNotificationOptionsById:(NSArray*)ids 335 | { 336 | NSArray* notifications = [self getNotifications]; 337 | NSMutableArray* options = [[NSMutableArray alloc] init]; 338 | 339 | for (UNNotificationRequest* notification in notifications) 340 | { 341 | if ([ids containsObject:notification.options.id]) { 342 | [options addObject:notification.options.userInfo]; 343 | } 344 | } 345 | 346 | return options; 347 | } 348 | 349 | /* 350 | * Clear all notfications. 351 | * 352 | * @return [ Void ] 353 | */ 354 | - (void) clearNotifications 355 | { 356 | [self removeAllDeliveredNotifications]; 357 | } 358 | 359 | /* 360 | * Clear Specified notfication. 361 | * 362 | * @param [ UNNotificationRequest* ] notification The notification object. 363 | * 364 | * @return [ Void ] 365 | */ 366 | - (void) clearNotification:(UNNotificationRequest*)toast 367 | { 368 | [self removeDeliveredNotificationsWithIdentifiers:@[toast.identifier]]; 369 | } 370 | 371 | /* 372 | * Cancel all notfications. 373 | * 374 | * @return [ Void ] 375 | */ 376 | - (void) cancelNotifications 377 | { 378 | [self removeAllPendingNotificationRequests]; 379 | [self removeAllDeliveredNotifications]; 380 | } 381 | 382 | /* 383 | * Cancel specified notfication. 384 | * 385 | * @param [ UNNotificationRequest* ] notification The notification object. 386 | * 387 | * @return [ Void ] 388 | */ 389 | - (void) cancelNotification:(UNNotificationRequest*)toast 390 | { 391 | NSArray* ids = @[toast.identifier]; 392 | 393 | [self removeDeliveredNotificationsWithIdentifiers:ids]; 394 | [self removePendingNotificationRequestsWithIdentifiers:ids]; 395 | } 396 | 397 | @end 398 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/.vs/LocalNotificationProxy/v15/.suo: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/src/windows/LocalNotificationProxy/.vs/LocalNotificationProxy/v15/.suo -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 15 4 | VisualStudioVersion = 15.0.26430.14 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "LocalNotificationProxy", "LocalNotificationProxy\LocalNotificationProxy.csproj", "{F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}" 7 | EndProject 8 | Global 9 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 10 | Debug|Any CPU = Debug|Any CPU 11 | Debug|ARM = Debug|ARM 12 | Debug|x64 = Debug|x64 13 | Debug|x86 = Debug|x86 14 | Release|Any CPU = Release|Any CPU 15 | Release|ARM = Release|ARM 16 | Release|x64 = Release|x64 17 | Release|x86 = Release|x86 18 | EndGlobalSection 19 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 20 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 21 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|Any CPU.Build.0 = Debug|Any CPU 22 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.ActiveCfg = Debug|ARM 23 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|ARM.Build.0 = Debug|ARM 24 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.ActiveCfg = Debug|x64 25 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x64.Build.0 = Debug|x64 26 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.ActiveCfg = Debug|x86 27 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Debug|x86.Build.0 = Debug|x86 28 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.ActiveCfg = Release|Any CPU 29 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|Any CPU.Build.0 = Release|Any CPU 30 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.ActiveCfg = Release|ARM 31 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|ARM.Build.0 = Release|ARM 32 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.ActiveCfg = Release|x64 33 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x64.Build.0 = Release|x64 34 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.ActiveCfg = Release|x86 35 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1}.Release|x86.Build.0 = Release|x86 36 | EndGlobalSection 37 | GlobalSection(SolutionProperties) = preSolution 38 | HideSolutionNode = FALSE 39 | EndGlobalSection 40 | EndGlobal 41 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/ActionGroup.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification 23 | { 24 | using System.Collections.Generic; 25 | using System.Runtime.InteropServices.WindowsRuntime; 26 | using global::LocalNotificationProxy.LocalNotification.Toast; 27 | 28 | public sealed class ActionGroup 29 | { 30 | /// 31 | /// Saves all groups for later lookup. 32 | /// 33 | private static Dictionary groups = new Dictionary(); 34 | 35 | /// 36 | /// Initializes a new instance of the class. 37 | /// 38 | /// The ID of the action group. 39 | /// The list of actions to group for. 40 | public ActionGroup(string id, [ReadOnlyArray] IAction[] actions) 41 | { 42 | this.Id = id; 43 | this.Actions = actions; 44 | } 45 | 46 | /// 47 | /// Gets or sets the action group ID. 48 | /// 49 | public string Id { get; set; } 50 | 51 | /// 52 | /// Gets or sets the notification actions. 53 | /// 54 | public IAction[] Actions { get; set; } 55 | 56 | /// 57 | /// Lookup the action groups with the specified group id. 58 | /// 59 | /// The ID of the action group to find. 60 | /// Null if no group was found. 61 | public static ActionGroup Lookup(string id) 62 | { 63 | return groups[id]; 64 | } 65 | 66 | /// 67 | /// Register the provided set of actions under the specified group id. 68 | /// 69 | /// The action group to register. 70 | public static void Register(ActionGroup group) 71 | { 72 | groups.Add(group.Id, group); 73 | } 74 | 75 | /// 76 | /// Unregister the action group. 77 | /// 78 | /// The id of the action group to remove. 79 | public static void Unregister(string id) 80 | { 81 | groups.Remove(id); 82 | } 83 | 84 | /// 85 | /// Check if a action group with that id is registered. 86 | /// 87 | /// The id of the action group to check for. 88 | /// True if a group with the ID could be found. 89 | public static bool IsRegistered(string id) 90 | { 91 | return groups.ContainsKey(id); 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Builder.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification 23 | { 24 | using System.Diagnostics; 25 | using Microsoft.Toolkit.Uwp.Notifications; 26 | using Windows.UI.Notifications; 27 | 28 | internal class Builder 29 | { 30 | /// 31 | /// The provided trigger request. 32 | /// 33 | private readonly Request request; 34 | 35 | /// 36 | /// Initializes a new instance of the class. 37 | /// 38 | /// Trigger request. 39 | public Builder(Request request) 40 | { 41 | this.request = request; 42 | this.Content = new Notification(request.Options); 43 | } 44 | 45 | /// 46 | /// Gets the content. 47 | /// 48 | public Notification Content { get; private set; } 49 | 50 | /// 51 | /// Gets the options. 52 | /// 53 | private Options Options { get => this.Content.Options; } 54 | 55 | /// 56 | /// Build a toast notification specified by the options. 57 | /// 58 | /// A fully configured toast notification instance. 59 | public ScheduledToastNotification Build() 60 | { 61 | var toast = this.InitToast(); 62 | 63 | this.AddProgressBarToToast(toast); 64 | this.AddAttachmentsToToast(toast); 65 | this.AddActionsToToast(toast); 66 | 67 | return this.ConvertToastToNotification(toast); 68 | } 69 | 70 | /// 71 | /// Gets the initialize skeleton for a toast notification. 72 | /// 73 | /// Basic skeleton with sound, image and text. 74 | private ToastContent InitToast() 75 | { 76 | return new ToastContent() 77 | { 78 | Launch = this.Content.GetXml(), 79 | Audio = this.Content.Sound, 80 | 81 | Visual = new ToastVisual() 82 | { 83 | BindingGeneric = new ToastBindingGeneric() 84 | { 85 | Children = 86 | { 87 | new AdaptiveText() 88 | { 89 | Text = this.Options.Title 90 | }, 91 | 92 | new AdaptiveText() 93 | { 94 | Text = this.Options.Text 95 | } 96 | }, 97 | 98 | AppLogoOverride = this.Content.Icon 99 | } 100 | }, 101 | 102 | Actions = new ToastActionsCustom() 103 | { 104 | Buttons = { }, 105 | Inputs = { } 106 | } 107 | }; 108 | } 109 | 110 | /// 111 | /// Adds optional progress bar to the toast. 112 | /// 113 | /// Tho toast to extend for. 114 | private void AddProgressBarToToast(ToastContent toast) 115 | { 116 | var progressBar = this.Content.ProgressBar; 117 | 118 | if (progressBar != null) 119 | { 120 | toast.Visual.BindingGeneric.Children.Add(progressBar); 121 | } 122 | } 123 | 124 | /// 125 | /// Adds attachments to the toast. 126 | /// 127 | /// Tho toast to extend for. 128 | private void AddAttachmentsToToast(ToastContent toast) 129 | { 130 | foreach (var image in this.Content.Attachments) 131 | { 132 | toast.Visual.BindingGeneric.Children.Add(image); 133 | } 134 | } 135 | 136 | /// 137 | /// Adds buttons and input fields to the toast. 138 | /// 139 | /// Tho toast to extend for. 140 | private void AddActionsToToast(ToastContent toast) 141 | { 142 | foreach (var btn in this.Content.Inputs) 143 | { 144 | (toast.Actions as ToastActionsCustom).Inputs.Add(btn); 145 | } 146 | 147 | foreach (var btn in this.Content.Buttons) 148 | { 149 | (toast.Actions as ToastActionsCustom).Buttons.Add(btn); 150 | } 151 | } 152 | 153 | /// 154 | /// Converts the toast into a notification. 155 | /// 156 | /// The toast to convert. 157 | /// A notification ready to schedule. 158 | private ScheduledToastNotification ConvertToastToNotification(ToastContent toast) 159 | { 160 | var xml = toast.GetXml(); 161 | var at = this.request.TriggerDate; 162 | ScheduledToastNotification notification; 163 | 164 | Debug.WriteLine("[local-notification] Next trigger at: " + at); 165 | 166 | if (!at.HasValue) 167 | { 168 | return null; 169 | } 170 | 171 | try 172 | { 173 | notification = new ScheduledToastNotification(xml, at.Value); 174 | } 175 | catch 176 | { 177 | return null; 178 | } 179 | 180 | notification.Id = this.Content.Id; 181 | notification.Tag = this.Options.Id.ToString(); 182 | notification.SuppressPopup = this.Options.Silent; 183 | 184 | if (this.request.Occurrence > 2) 185 | { 186 | notification.Group = notification.Tag; 187 | } 188 | 189 | return notification; 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Notification.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification 23 | { 24 | using System; 25 | using System.Collections.Generic; 26 | using global::LocalNotificationProxy.LocalNotification.Toast; 27 | using Microsoft.Toolkit.Uwp.Notifications; 28 | using Windows.UI.Notifications; 29 | 30 | internal class Notification 31 | { 32 | /// 33 | /// Initializes a new instance of the class. 34 | /// 35 | /// The options hash map from JS side. 36 | public Notification(Options options) 37 | { 38 | this.Options = options; 39 | } 40 | 41 | /// 42 | /// Initializes a new instance of the class. 43 | /// 44 | /// The options as a xml string. 45 | public Notification(string xml) 46 | { 47 | this.Options = Options.Parse(xml); 48 | } 49 | 50 | /// 51 | /// Initializes a new instance of the class. 52 | /// 53 | /// The options as a toast object. 54 | public Notification(ScheduledToastNotification toast) 55 | { 56 | this.Options = Options.Parse(toast.Content.GetXml()); 57 | } 58 | 59 | /// 60 | /// Initializes a new instance of the class. 61 | /// 62 | /// The options as a toast object. 63 | public Notification(ToastNotification toast) 64 | { 65 | var xml = toast.Content.DocumentElement.GetAttribute("launch"); 66 | this.Options = Options.Parse(xml); 67 | } 68 | 69 | public enum Type 70 | { 71 | All, Scheduled, Triggered, Unknown 72 | } 73 | 74 | /// 75 | /// Gets the wrapped notification options. 76 | /// 77 | public Options Options { get; private set; } 78 | 79 | /// 80 | /// Gets the unique identifier for the toast. 81 | /// 82 | public string Id => $"{this.Options.Id}#{this.Options.Trigger.Occurrence}"; 83 | 84 | /// 85 | /// Gets a ToastAudio object based on the specified sound uri. 86 | /// 87 | public ToastAudio Sound 88 | { 89 | get 90 | { 91 | var sound = new ToastAudio(); 92 | var path = this.Options.Sound; 93 | 94 | if (path == null || path.Length == 0 || path.Equals("false")) 95 | { 96 | sound.Silent = true; 97 | } 98 | else 99 | if (path.StartsWith("file:///") || path.StartsWith("http")) 100 | { 101 | sound.Src = new Uri(path, UriKind.Absolute); 102 | } 103 | else 104 | if (path.StartsWith("file://")) 105 | { 106 | sound.Src = new Uri(path.Replace("file:/", "ms-appx:///www")); 107 | } 108 | else 109 | if (path.StartsWith("res://")) 110 | { 111 | sound.Src = new Uri(path.Replace("res://", "ms-winsoundevent:notification.")); 112 | } 113 | else 114 | if (path.StartsWith("app://")) 115 | { 116 | sound.Src = new Uri(path.Replace("app:/", "ms-appdata://")); 117 | } 118 | 119 | return sound; 120 | } 121 | } 122 | 123 | /// 124 | /// Gets a GenericAppLogo object based on the specified icon uri. 125 | /// 126 | public ToastGenericAppLogo Icon 127 | { 128 | get 129 | { 130 | var image = new ToastGenericAppLogo(); 131 | var path = this.Options.Icon; 132 | 133 | if (path == null || path.StartsWith("res://logo")) 134 | { 135 | image.Source = string.Empty; 136 | } 137 | else 138 | if (path.StartsWith("file:///") || path.StartsWith("http")) 139 | { 140 | image.Source = path; 141 | } 142 | else 143 | if (path.StartsWith("file://")) 144 | { 145 | image.Source = path.Replace("file:/", "ms-appx:///www"); 146 | } 147 | else 148 | if (path.StartsWith("res://")) 149 | { 150 | image.Source = path.Replace("res://", "ms-appx:///images"); 151 | } 152 | else 153 | if (path.StartsWith("app://")) 154 | { 155 | image.Source = path.Replace("app:/", "ms-appdata://local"); 156 | } 157 | else 158 | { 159 | image.Source = string.Empty; 160 | } 161 | 162 | if (image.Source.EndsWith("?crop=none")) 163 | { 164 | image.HintCrop = ToastGenericAppLogoCrop.None; 165 | } 166 | else 167 | if (image.Source.EndsWith("?crop=cirlce")) 168 | { 169 | image.HintCrop = ToastGenericAppLogoCrop.Circle; 170 | } 171 | 172 | return image; 173 | } 174 | } 175 | 176 | /// 177 | /// Gets the parsed image attachments. 178 | /// 179 | public List Attachments 180 | { 181 | get 182 | { 183 | var images = new List(); 184 | 185 | if (this.Options.Attachments == null) 186 | { 187 | return images; 188 | } 189 | 190 | foreach (string path in this.Options.Attachments) 191 | { 192 | var image = new AdaptiveImage(); 193 | 194 | if (path.StartsWith("file:///") || path.StartsWith("http")) 195 | { 196 | image.Source = path; 197 | } 198 | else 199 | if (path.StartsWith("file://")) 200 | { 201 | image.Source = path.Replace("file:/", "ms-appx:///www"); 202 | } 203 | else 204 | if (path.StartsWith("res://")) 205 | { 206 | image.Source = path.Replace("res://", "ms-appx:///images"); 207 | } 208 | else 209 | if (path.StartsWith("app://")) 210 | { 211 | image.Source = path.Replace("app:/", "ms-appdata://local"); 212 | } 213 | 214 | if (image.Source != null) 215 | { 216 | images.Add(image); 217 | } 218 | } 219 | 220 | return images; 221 | } 222 | } 223 | 224 | /// 225 | /// Gets all toast buttons. 226 | /// 227 | public List Buttons 228 | { 229 | get 230 | { 231 | var buttons = new List(); 232 | 233 | foreach (var action in this.Options.Actions) 234 | { 235 | if (action is Button) 236 | { 237 | buttons.Add(new ToastButton(action.Title, this.Options.GetXml(action.ID)) 238 | { 239 | ActivationType = action.Launch ? ToastActivationType.Foreground : ToastActivationType.Background 240 | }); 241 | } 242 | else if (action is Input && (action as Input).SubmitTitle != null) 243 | { 244 | var input = action as Input; 245 | 246 | buttons.Add(new ToastButton(input.SubmitTitle, this.Options.GetXml(input.ID)) 247 | { 248 | ActivationType = input.Launch ? ToastActivationType.Foreground : ToastActivationType.Background, 249 | TextBoxId = input.ID 250 | }); 251 | } 252 | } 253 | 254 | return buttons; 255 | } 256 | } 257 | 258 | /// 259 | /// Gets all toast inputs. 260 | /// 261 | public List Inputs 262 | { 263 | get 264 | { 265 | var inputs = new List(); 266 | 267 | foreach (var action in this.Options.Actions) 268 | { 269 | if (!(action is Input)) 270 | { 271 | continue; 272 | } 273 | 274 | inputs.Add(new ToastTextBox(action.ID) 275 | { 276 | Title = action.Title, 277 | PlaceholderContent = (action as Input).EmptyText, 278 | DefaultInput = (action as Input).DefaultValue 279 | }); 280 | } 281 | 282 | return inputs; 283 | } 284 | } 285 | 286 | /// 287 | /// Gets the progress bar widget. 288 | /// 289 | public AdaptiveProgressBar ProgressBar 290 | { 291 | get 292 | { 293 | var bar = this.Options.ProgressBar; 294 | 295 | if (!bar.Enabled) 296 | { 297 | return null; 298 | } 299 | 300 | return new AdaptiveProgressBar() 301 | { 302 | Title = bar.Title, 303 | Value = new BindableProgressBarValue("progress.value"), 304 | ValueStringOverride = new BindableString("progress.description"), 305 | Status = new BindableString("progress.status") 306 | }; 307 | } 308 | } 309 | 310 | /// 311 | /// Gets the instance as an serialized xml element. 312 | /// 313 | /// Element with all property values set as attributes. 314 | public string GetXml() 315 | { 316 | return this.Options.GetXml(); 317 | } 318 | } 319 | } 320 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Options.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification 23 | { 24 | using global::LocalNotificationProxy.LocalNotification.Toast; 25 | using Windows.Data.Xml.Dom; 26 | 27 | public sealed class Options 28 | { 29 | /// 30 | /// Gets notification event. 31 | /// 32 | public string Action { get; private set; } = "click"; 33 | 34 | /// 35 | /// Gets or sets notification ID. 36 | /// 37 | public int Id { get; set; } = 0; 38 | 39 | /// 40 | /// Gets or sets notification title. 41 | /// 42 | public string Title { get; set; } 43 | 44 | /// 45 | /// Gets or sets notification text. 46 | /// 47 | public string Text { get; set; } 48 | 49 | /// 50 | /// Gets or sets app badge number. 51 | /// 52 | public int Badge { get; set; } 53 | 54 | /// 55 | /// Gets or sets the notification sound. 56 | /// 57 | public string Sound { get; set; } 58 | 59 | /// 60 | /// Gets or sets the notification image. 61 | /// 62 | public string Icon { get; set; } 63 | 64 | /// 65 | /// Gets or sets a value indicating whether the popup shall be visible. 66 | /// 67 | public bool Silent { get; set; } = false; 68 | 69 | /// 70 | /// Gets or sets the notification trigger. 71 | /// 72 | public Toast.Trigger Trigger { get; set; } 73 | 74 | /// 75 | /// Gets or sets the notification user data. 76 | /// 77 | public string Data { get; set; } 78 | 79 | /// 80 | /// Gets or sets the notification attachments. 81 | /// 82 | public string[] Attachments { get; set; } 83 | 84 | /// 85 | /// Gets or sets the notification actions. 86 | /// 87 | public IAction[] Actions { get; set; } 88 | 89 | /// 90 | /// Gets or sets the notification progress bar. 91 | /// 92 | public ProgressBar ProgressBar { get; set; } 93 | 94 | /// 95 | /// Deserializes the XML string into an instance of Options. 96 | /// 97 | /// The serialized instance of Options as an xml string. 98 | /// An instance where all properties have been assigned. 99 | public static Options Parse(string identifier) 100 | { 101 | var doc = new XmlDocument(); 102 | doc.LoadXml(identifier); 103 | 104 | var options = new Options(); 105 | var node = doc.DocumentElement; 106 | 107 | options.Id = int.Parse(node.GetAttribute("id")); 108 | options.Badge = int.Parse(node.GetAttribute("badge")); 109 | options.Trigger = Toast.Trigger.Parse(node.GetAttribute("trigger")); 110 | 111 | if (node.GetAttributeNode("text") != null) 112 | { 113 | options.Text = node.GetAttribute("text"); 114 | } 115 | 116 | if (node.GetAttributeNode("title") != null) 117 | { 118 | options.Title = node.GetAttribute("title"); 119 | } 120 | 121 | if (node.GetAttributeNode("sound") != null) 122 | { 123 | options.Sound = node.GetAttribute("sound"); 124 | } 125 | 126 | if (node.GetAttributeNode("image") != null) 127 | { 128 | options.Icon = node.GetAttribute("image"); 129 | } 130 | 131 | if (node.GetAttributeNode("data") != null) 132 | { 133 | options.Data = node.GetAttribute("data"); 134 | } 135 | 136 | if (node.GetAttributeNode("attachments") != null) 137 | { 138 | options.Attachments = node.GetAttribute("attachments").Split(','); 139 | } 140 | 141 | if (node.GetAttributeNode("silent") != null) 142 | { 143 | options.Silent = true; 144 | } 145 | 146 | if (node.GetAttributeNode("action") != null) 147 | { 148 | options.Action = node.GetAttribute("action"); 149 | } 150 | 151 | return options; 152 | } 153 | 154 | /// 155 | /// Gets the instance as an serialized xml element. 156 | /// 157 | /// Element with all property values set as attributes. 158 | public string GetXml() 159 | { 160 | return this.GetXml(null); 161 | } 162 | 163 | /// 164 | /// Gets the instance as an serialized xml element. 165 | /// 166 | /// Optional (internal) event name. 167 | /// Element with all property values set as attributes. 168 | internal string GetXml(string action) 169 | { 170 | var node = new XmlDocument().CreateElement("options"); 171 | 172 | node.SetAttribute("id", this.Id.ToString()); 173 | node.SetAttribute("badge", this.Badge.ToString()); 174 | node.SetAttribute("trigger", this.Trigger.GetXml()); 175 | 176 | if (this.Title != null) 177 | { 178 | node.SetAttribute("title", this.Title); 179 | } 180 | 181 | if (this.Text != null) 182 | { 183 | node.SetAttribute("text", this.Text); 184 | } 185 | 186 | if (this.Sound != null) 187 | { 188 | node.SetAttribute("sound", this.Sound); 189 | } 190 | 191 | if (this.Icon != null) 192 | { 193 | node.SetAttribute("image", this.Icon); 194 | } 195 | 196 | if (this.Data != null) 197 | { 198 | node.SetAttribute("data", this.Data); 199 | } 200 | 201 | if (this.Attachments != null) 202 | { 203 | node.SetAttribute("attachments", string.Join(",", this.Attachments)); 204 | } 205 | 206 | if (this.Silent) 207 | { 208 | node.SetAttribute("silent", "1"); 209 | } 210 | 211 | if (action != null) 212 | { 213 | node.SetAttribute("action", action); 214 | } 215 | 216 | return node.GetXml(); 217 | } 218 | } 219 | } -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Request.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification 23 | { 24 | using System; 25 | 26 | internal class Request 27 | { 28 | /// 29 | /// The right trigger for the options 30 | /// 31 | private readonly Trigger.DateTrigger trigger; 32 | 33 | /// 34 | /// How often the trigger shall occur. 35 | /// 36 | private readonly int count; 37 | 38 | /// 39 | /// The trigger spec. 40 | /// 41 | private readonly Toast.Trigger spec; 42 | 43 | /// 44 | /// The current trigger date. 45 | /// 46 | private DateTime? triggerDate; 47 | 48 | /// 49 | /// Initializes a new instance of the class. 50 | /// 51 | /// The options spec. 52 | public Request(Options options) 53 | { 54 | this.Options = options; 55 | this.spec = options.Trigger; 56 | this.count = Math.Max(this.spec.Count, 1); 57 | this.trigger = this.BuildTrigger(); 58 | this.triggerDate = this.trigger.GetNextTriggerDate(this.GetBaseDate()); 59 | } 60 | 61 | /// 62 | /// Gets the options spec. 63 | /// 64 | public Options Options { get; private set; } 65 | 66 | /// 67 | /// Gets the value of the internal occurrence counter. 68 | /// 69 | public int Occurrence { get => this.trigger.Occurrence; } 70 | 71 | /// 72 | /// Gets a value indicating whether there's one more trigger date to calculate. 73 | /// 74 | public bool HasNext { get => this.triggerDate.HasValue && this.Occurrence <= this.count; } 75 | 76 | /// 77 | /// Gets the current trigger date. 78 | /// 79 | public DateTime? TriggerDate 80 | { 81 | get 82 | { 83 | if (!this.triggerDate.HasValue) 84 | { 85 | return null; 86 | } 87 | 88 | if (this.spec.Before != 0) 89 | { 90 | var before = this.ToDateTime(this.spec.Before); 91 | 92 | if (this.triggerDate.Value >= before) 93 | { 94 | return null; 95 | } 96 | } 97 | 98 | var minDate = DateTime.Now.AddSeconds(0.2); 99 | 100 | if (this.triggerDate >= minDate) 101 | { 102 | return this.triggerDate; 103 | } 104 | 105 | if ((minDate - this.triggerDate).Value.TotalMinutes <= 1) 106 | { 107 | return minDate; 108 | } 109 | 110 | return null; 111 | } 112 | } 113 | 114 | /// 115 | /// Moves the internal occurrence counter by one. 116 | /// 117 | /// false if it wasnt possible anymore to move ahead. 118 | public bool MoveNext() 119 | { 120 | if (this.HasNext) 121 | { 122 | this.triggerDate = this.GetNextTriggerDate(); 123 | } 124 | else 125 | { 126 | this.triggerDate = null; 127 | } 128 | 129 | return this.triggerDate.HasValue; 130 | } 131 | 132 | /// 133 | /// Gets the next trigger date based on the current trigger date. 134 | /// 135 | /// null if there's no next one. 136 | private DateTime? GetNextTriggerDate() 137 | { 138 | if (this.triggerDate.HasValue) 139 | { 140 | return this.trigger.GetNextTriggerDate(this.triggerDate.Value); 141 | } 142 | else 143 | { 144 | return null; 145 | } 146 | } 147 | 148 | /// 149 | /// Build the trigger specified in options. 150 | /// 151 | /// Configured trigger instance 152 | private Trigger.DateTrigger BuildTrigger() 153 | { 154 | if (this.spec.Every is Toast.Every) 155 | { 156 | var matchers = this.GetMatchers(); 157 | var specials = this.GetSpecials(); 158 | 159 | return new Trigger.MatchTrigger(matchers, specials); 160 | } 161 | 162 | var unit = this.GetUnit(); 163 | var ticks = this.GetTicks(); 164 | 165 | return new Trigger.IntervalTrigger(ticks, unit); 166 | } 167 | 168 | /// 169 | /// Gets the unit value. 170 | /// 171 | /// SECOND by default. 172 | private Trigger.DateTrigger.Unit GetUnit() 173 | { 174 | var unit = "SECOND"; 175 | 176 | if (!string.IsNullOrEmpty(this.spec.Unit)) 177 | { 178 | unit = this.spec.Unit; 179 | } 180 | else if (this.spec.Every is string) 181 | { 182 | unit = this.spec.Every as string; 183 | } 184 | 185 | return (Trigger.DateTrigger.Unit)Enum.Parse( 186 | typeof(Trigger.DateTrigger.Unit), unit.ToUpper()); 187 | } 188 | 189 | /// 190 | /// Gets the tick value. 191 | /// 192 | /// Defaults to 0 193 | private int GetTicks() 194 | { 195 | if (this.spec.At != 0) 196 | { 197 | return 0; 198 | } 199 | else if (this.spec.In != 0) 200 | { 201 | return this.spec.In; 202 | } 203 | else if (this.spec.Every is string) 204 | { 205 | return 1; 206 | } 207 | else if (this.spec.Every is double) 208 | { 209 | return Convert.ToInt32(this.spec.Every); 210 | } 211 | 212 | return 0; 213 | } 214 | 215 | /// 216 | /// Gets an array of all date parts to construct a datetime instance. 217 | /// 218 | /// [min, hour, day, month, year] 219 | private int?[] GetMatchers() 220 | { 221 | var every = this.spec.Every as Toast.Every; 222 | 223 | return new int?[] 224 | { 225 | every.Minute, every.Hour, every.Day, every.Month, every.Year 226 | }; 227 | } 228 | 229 | /// 230 | /// Gets an array of all date parts to construct a datetime instance. 231 | /// 232 | /// [weekday, weekdayOrdinal, weekOfMonth, quarter] 233 | private int?[] GetSpecials() 234 | { 235 | var every = this.spec.Every as Toast.Every; 236 | 237 | return new int?[] 238 | { 239 | every.Weekday, every.WeekdayOrdinal, every.WeekOfMonth, every.Quarter 240 | }; 241 | } 242 | 243 | /// 244 | /// Gets the base date from where to calculate the next trigger date. 245 | /// 246 | /// Usually points to now 247 | private DateTime GetBaseDate() 248 | { 249 | if (this.spec.At != 0) 250 | { 251 | return this.ToDateTime(this.spec.At); 252 | } 253 | else if (this.spec.FirstAt != 0) 254 | { 255 | return this.ToDateTime(this.spec.FirstAt); 256 | } 257 | else if (this.spec.After != 0) 258 | { 259 | return this.ToDateTime(this.spec.After); 260 | } 261 | 262 | return DateTime.Now; 263 | } 264 | 265 | /// 266 | /// Unix time from milliseconds. 267 | /// 268 | /// Milliseconds 269 | /// DateTime object. 270 | private DateTime ToDateTime(long ms) 271 | { 272 | return DateTimeOffset.FromUnixTimeMilliseconds(ms).LocalDateTime; 273 | } 274 | } 275 | } 276 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/Button.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification.Toast 23 | { 24 | public sealed class Button : IAction 25 | { 26 | /// 27 | /// Gets or sets the ID. 28 | /// 29 | public string ID { get; set; } 30 | 31 | /// 32 | /// Gets or sets the title. 33 | /// 34 | public string Title { get; set; } 35 | 36 | /// 37 | /// Gets or sets a value indicating whether to launch the app. 38 | /// 39 | public bool Launch { get; set; } = true; 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/Every.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification.Toast 23 | { 24 | using System; 25 | using Windows.Data.Xml.Dom; 26 | 27 | public sealed class Every 28 | { 29 | /// 30 | /// Gets or sets the minute. 31 | /// 32 | public int? Minute { get; set; } 33 | 34 | /// 35 | /// Gets or sets the hour. 36 | /// 37 | public int? Hour { get; set; } 38 | 39 | /// 40 | /// Gets or sets the day. 41 | /// 42 | public int? Day { get; set; } 43 | 44 | /// 45 | /// Gets or sets the day of week. 46 | /// 47 | public int? Weekday { get; set; } 48 | 49 | /// 50 | /// Gets or sets the week of year. 51 | /// 52 | public int? Week { get; set; } 53 | 54 | /// 55 | /// Gets or sets the day of ordinal week. 56 | /// 57 | public int? WeekdayOrdinal { get; set; } 58 | 59 | /// 60 | /// Gets or sets the week of month. 61 | /// 62 | public int? WeekOfMonth { get; set; } 63 | 64 | /// 65 | /// Gets or sets the month. 66 | /// 67 | public int? Month { get; set; } 68 | 69 | /// 70 | /// Gets or sets the quarter. 71 | /// 72 | public int? Quarter { get; set; } 73 | 74 | /// 75 | /// Gets or sets the year. 76 | /// 77 | public int? Year { get; set; } 78 | 79 | /// 80 | /// Deserializes the XML string into an instance of Every. 81 | /// 82 | /// The serialized instance of Options as an xml string. 83 | /// An instance where all properties have been assigned. 84 | internal static Every Parse(string xml) 85 | { 86 | var doc = new XmlDocument(); 87 | doc.LoadXml(xml); 88 | 89 | var every = new Every(); 90 | var node = doc.DocumentElement; 91 | 92 | if (node.GetAttributeNode("minute") != null) 93 | { 94 | every.Minute = Convert.ToInt32(node.GetAttribute("minute")); 95 | } 96 | 97 | if (node.GetAttributeNode("hour") != null) 98 | { 99 | every.Hour = Convert.ToInt32(node.GetAttribute("hour")); 100 | } 101 | 102 | if (node.GetAttributeNode("day") != null) 103 | { 104 | every.Day = Convert.ToInt32(node.GetAttribute("day")); 105 | } 106 | 107 | if (node.GetAttributeNode("weekday") != null) 108 | { 109 | every.Weekday = Convert.ToInt32(node.GetAttribute("weekday")); 110 | } 111 | 112 | if (node.GetAttributeNode("week") != null) 113 | { 114 | every.Week = Convert.ToInt32(node.GetAttribute("week")); 115 | } 116 | 117 | if (node.GetAttributeNode("weekdayordinal") != null) 118 | { 119 | every.WeekdayOrdinal = Convert.ToInt32(node.GetAttribute("weekdayOrdinal")); 120 | } 121 | 122 | if (node.GetAttributeNode("weekOfMonth") != null) 123 | { 124 | every.WeekOfMonth = Convert.ToInt32(node.GetAttribute("weekOfMonth")); 125 | } 126 | 127 | if (node.GetAttributeNode("month") != null) 128 | { 129 | every.Month = Convert.ToInt32(node.GetAttribute("month")); 130 | } 131 | 132 | if (node.GetAttributeNode("year") != null) 133 | { 134 | every.Year = Convert.ToInt32(node.GetAttribute("year")); 135 | } 136 | 137 | return every; 138 | } 139 | 140 | /// 141 | /// Gets the instance as an serialized xml element. 142 | /// 143 | /// Element with all property values set as attributes. 144 | internal string GetXml() 145 | { 146 | var node = new XmlDocument().CreateElement("every"); 147 | 148 | if (this.Minute.HasValue) 149 | { 150 | node.SetAttribute("minute", this.Minute.ToString()); 151 | } 152 | 153 | if (this.Hour.HasValue) 154 | { 155 | node.SetAttribute("hour", this.Hour.ToString()); 156 | } 157 | 158 | if (this.Day.HasValue) 159 | { 160 | node.SetAttribute("day", this.Day.ToString()); 161 | } 162 | 163 | if (this.Weekday.HasValue) 164 | { 165 | node.SetAttribute("weekday", this.Weekday.ToString()); 166 | } 167 | 168 | if (this.Week.HasValue) 169 | { 170 | node.SetAttribute("week", this.Week.ToString()); 171 | } 172 | 173 | if (this.WeekdayOrdinal.HasValue) 174 | { 175 | node.SetAttribute("weekdayOrdinal", this.WeekdayOrdinal.ToString()); 176 | } 177 | 178 | if (this.WeekOfMonth.HasValue) 179 | { 180 | node.SetAttribute("weekOfMonth", this.WeekOfMonth.ToString()); 181 | } 182 | 183 | if (this.Month.HasValue) 184 | { 185 | node.SetAttribute("month", this.Month.ToString()); 186 | } 187 | 188 | if (this.Year.HasValue) 189 | { 190 | node.SetAttribute("year", this.Year.ToString()); 191 | } 192 | 193 | return node.GetXml(); 194 | } 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/IAction.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification.Toast 23 | { 24 | public interface IAction 25 | { 26 | /// 27 | /// Gets or sets the ID. 28 | /// 29 | string ID { get; set; } 30 | 31 | /// 32 | /// Gets or sets the title. 33 | /// 34 | string Title { get; set; } 35 | 36 | /// 37 | /// Gets or sets a value indicating whether to launch the app. 38 | /// 39 | bool Launch { get; set; } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/Input.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification.Toast 23 | { 24 | public sealed class Input : IAction 25 | { 26 | /// 27 | /// Gets or sets the ID. 28 | /// 29 | public string ID { get; set; } 30 | 31 | /// 32 | /// Gets or sets the title. 33 | /// 34 | public string Title { get; set; } 35 | 36 | /// 37 | /// Gets or sets the title of the submit button. 38 | /// 39 | public string SubmitTitle { get; set; } 40 | 41 | /// 42 | /// Gets or sets placeholder text. 43 | /// 44 | public string EmptyText { get; set; } 45 | 46 | /// 47 | /// Gets or sets the default text. 48 | /// 49 | public string DefaultValue { get; set; } 50 | 51 | /// 52 | /// Gets or sets a value indicating whether to launch the app. 53 | /// 54 | public bool Launch { get; set; } = true; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/ProgressBar.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification.Toast 23 | { 24 | public sealed class ProgressBar 25 | { 26 | /// 27 | /// Gets or sets a value indicating whether the notification has a progress bar. 28 | /// 29 | public bool Enabled { get; set; } = false; 30 | 31 | /// 32 | /// Gets or sets the title. 33 | /// 34 | public string Title { get; set; } = string.Empty; 35 | 36 | /// 37 | /// Gets or sets the value. 38 | /// 39 | public double Value { get; set; } = 0; 40 | 41 | /// 42 | /// Gets or sets the status. 43 | /// 44 | public string Status { get; set; } = string.Empty; 45 | 46 | /// 47 | /// Gets or sets the description. 48 | /// 49 | public string Description { get; set; } = string.Empty; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Toast/Trigger.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification.Toast 23 | { 24 | using Windows.Data.Xml.Dom; 25 | 26 | public sealed class Trigger 27 | { 28 | // private DateTime? triggerDate; 29 | 30 | /// 31 | /// Gets the trigger type. 32 | /// 33 | public string Type { get; } = "calendar"; 34 | 35 | /// 36 | /// Gets or sets the fix trigger date. 37 | /// 38 | public long At { get; set; } = 0; 39 | 40 | /// 41 | /// Gets or sets the first trigger date. 42 | /// 43 | public long FirstAt { get; set; } = 0; 44 | 45 | /// 46 | /// Gets or sets the before trigger date. 47 | /// 48 | public long Before { get; set; } = 0; 49 | 50 | /// 51 | /// Gets or sets the after trigger date. 52 | /// 53 | public long After { get; set; } = 0; 54 | 55 | /// 56 | /// Gets or sets the relative trigger date from now. 57 | /// 58 | public int In { get; set; } = 0; 59 | 60 | /// 61 | /// Gets or sets the trigger count. 62 | /// 63 | public int Count { get; set; } = 1; 64 | 65 | /// 66 | /// Gets the trigger occurrence. 67 | /// 68 | public int Occurrence { get; internal set; } = 1; 69 | 70 | /// 71 | /// Gets or sets the trigger interval. 72 | /// 73 | public object Every { get; set; } 74 | 75 | /// 76 | /// Gets or sets the trigger unit. 77 | /// 78 | public string Unit { get; set; } 79 | 80 | /// 81 | /// Deserializes the XML string into an instance of Trigger. 82 | /// 83 | /// The serialized instance of Options as an xml string. 84 | /// An instance where all properties have been assigned. 85 | internal static Trigger Parse(string xml) 86 | { 87 | var doc = new XmlDocument(); 88 | doc.LoadXml(xml); 89 | 90 | var trigger = new Trigger(); 91 | var node = doc.DocumentElement; 92 | 93 | trigger.At = long.Parse(node.GetAttribute("at")); 94 | trigger.FirstAt = long.Parse(node.GetAttribute("firstAt")); 95 | trigger.Before = long.Parse(node.GetAttribute("before")); 96 | trigger.After = long.Parse(node.GetAttribute("after")); 97 | trigger.In = int.Parse(node.GetAttribute("in")); 98 | trigger.Count = int.Parse(node.GetAttribute("count")); 99 | trigger.Occurrence = int.Parse(node.GetAttribute("occurrence")); 100 | 101 | if (node.GetAttributeNode("unit") != null) 102 | { 103 | trigger.Unit = node.GetAttribute("unit"); 104 | } 105 | 106 | if (node.GetAttributeNode("strEvery") != null) 107 | { 108 | trigger.Every = node.GetAttribute("strEvery"); 109 | } 110 | else if (node.GetAttributeNode("hshEvery") != null) 111 | { 112 | trigger.Every = Toast.Every.Parse(node.GetAttribute("hshEvery")); 113 | } 114 | 115 | return trigger; 116 | } 117 | 118 | /// 119 | /// Gets the instance as an serialized xml element. 120 | /// 121 | /// Element with all property values set as attributes. 122 | internal string GetXml() 123 | { 124 | var node = new XmlDocument().CreateElement("trigger"); 125 | 126 | node.SetAttribute("at", this.At.ToString()); 127 | node.SetAttribute("firstAt", this.FirstAt.ToString()); 128 | node.SetAttribute("before", this.Before.ToString()); 129 | node.SetAttribute("after", this.After.ToString()); 130 | node.SetAttribute("in", this.In.ToString()); 131 | node.SetAttribute("count", this.Count.ToString()); 132 | node.SetAttribute("occurrence", this.Occurrence.ToString()); 133 | 134 | if (!string.IsNullOrEmpty(this.Unit)) 135 | { 136 | node.SetAttribute("unit", this.Unit); 137 | } 138 | 139 | if (this.Every != null) 140 | { 141 | if (this.Every is Every) 142 | { 143 | node.SetAttribute("hshEvery", (this.Every as Every).GetXml()); 144 | } 145 | else 146 | { 147 | node.SetAttribute("strEvery", this.Every.ToString()); 148 | } 149 | } 150 | 151 | return node.GetXml(); 152 | } 153 | } 154 | 155 | } 156 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Trigger/DateTrigger.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification.Trigger 23 | { 24 | using System; 25 | 26 | internal abstract class DateTrigger 27 | { 28 | /// 29 | /// Default unit is SECOND 30 | /// 31 | public enum Unit : byte 32 | { 33 | NULL, SECOND, MINUTE, HOUR, DAY, WEEK, MONTH, QUARTER, YEAR 34 | } 35 | 36 | /// 37 | /// Gets or sets the occurrence counter. 38 | /// 39 | public int Occurrence { get; protected set; } = 1; 40 | 41 | /// 42 | /// Gets the next trigger date. 43 | /// 44 | /// The date from where to calculate the next one. 45 | /// Null if there is no next trigger date. 46 | public abstract DateTime? GetNextTriggerDate(DateTime date); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotification/Trigger/IntervalTrigger.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy.LocalNotification.Trigger 23 | { 24 | using System; 25 | 26 | internal class IntervalTrigger : DateTrigger 27 | { 28 | /// 29 | /// The number of ticks per interval. 30 | /// 31 | private readonly int ticks; 32 | 33 | /// 34 | /// Initializes a new instance of the class. 35 | /// 36 | /// The number of ticks per interval. 37 | /// The unit of the ticks. 38 | public IntervalTrigger(int ticks, Unit unit) 39 | { 40 | this.ticks = ticks; 41 | this.Unit = unit; 42 | } 43 | 44 | /// 45 | /// Gets the unit of the ticks 46 | /// 47 | internal new Unit Unit { get; private set; } 48 | 49 | /// 50 | /// Gets the next trigger date. 51 | /// 52 | /// The date from where to calculate the next one. 53 | /// Null if there is no next trigger date. 54 | public override DateTime? GetNextTriggerDate(DateTime date) 55 | { 56 | this.Occurrence += 1; 57 | return this.AddInterval(date); 58 | } 59 | 60 | /// 61 | /// Adds the interval to the specified date. 62 | /// 63 | /// The date where to add the interval of ticks 64 | /// A new datetime instance 65 | protected DateTime AddInterval(DateTime date) 66 | { 67 | switch (this.Unit) 68 | { 69 | case Unit.SECOND: 70 | return date.AddSeconds(this.ticks); 71 | case Unit.MINUTE: 72 | return date.AddMinutes(this.ticks); 73 | case Unit.HOUR: 74 | return date.AddHours(this.ticks); 75 | case Unit.DAY: 76 | return date.AddDays(this.ticks); 77 | case Unit.WEEK: 78 | return date.AddDays(this.ticks * 7); 79 | case Unit.MONTH: 80 | return date.AddMonths(this.ticks); 81 | case Unit.QUARTER: 82 | return date.AddMonths(this.ticks * 3); 83 | case Unit.YEAR: 84 | return date.AddYears(this.ticks); 85 | default: 86 | return date; 87 | } 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotificationProxy.cs: -------------------------------------------------------------------------------- 1 | /* 2 | * Apache 2.0 License 3 | * 4 | * Copyright (c) Sebastian Katzer 2017 5 | * 6 | * This file contains Original Code and/or Modifications of Original Code 7 | * as defined in and that are subject to the Apache License 8 | * Version 2.0 (the 'License'). You may not use this file except in 9 | * compliance with the License. Please obtain a copy of the License at 10 | * http://opensource.org/licenses/Apache-2.0/ and read it before using this 11 | * file. 12 | * 13 | * The Original Code and all software distributed under the License are 14 | * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 | * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 | * Please see the License for the specific language governing rights and 19 | * limitations under the License. 20 | */ 21 | 22 | namespace LocalNotificationProxy 23 | { 24 | using System.Runtime.InteropServices.WindowsRuntime; 25 | using LocalNotification; 26 | 27 | public sealed class LocalNotificationProxy 28 | { 29 | /// 30 | /// Manager wrapps the native SDK methods. 31 | /// 32 | private Manager manager = new Manager(); 33 | 34 | /// 35 | /// Check permission to schedule notifications. 36 | /// 37 | /// True if settings are enabled 38 | public bool HasPermission() 39 | { 40 | return this.manager.Enabled; 41 | } 42 | 43 | /// 44 | /// Schedule notifications. 45 | /// 46 | /// List of key-value properties 47 | public void Schedule([ReadOnlyArray] Options[] notifications) 48 | { 49 | this.manager.Schedule(notifications); 50 | } 51 | 52 | /// 53 | /// Update notifications. 54 | /// 55 | /// List of key-value properties 56 | public void Update([ReadOnlyArray] Options[] notifications) 57 | { 58 | this.manager.Update(notifications); 59 | } 60 | 61 | /// 62 | /// Clear the notifications specified by id. 63 | /// 64 | /// The IDs of the notification to clear. 65 | /// The cleared notifications. 66 | public Options[] Clear([ReadOnlyArray] int[] ids) 67 | { 68 | return this.manager.Clear(ids).ToArray(); 69 | } 70 | 71 | /// 72 | /// Clear all notifications. 73 | /// 74 | public void ClearAll() 75 | { 76 | this.manager.ClearAll(); 77 | } 78 | 79 | /// 80 | /// Cancel the notifications specified by id. 81 | /// 82 | /// The IDs of the notification to clear. 83 | /// The cleared notifications. 84 | public Options[] Cancel([ReadOnlyArray] int[] ids) 85 | { 86 | return this.manager.Cancel(ids).ToArray(); 87 | } 88 | 89 | /// 90 | /// Cancel all notifications. 91 | /// 92 | public void CancelAll() 93 | { 94 | this.manager.CancelAll(); 95 | } 96 | 97 | /// 98 | /// Gets the type of the notification specified by ID. 99 | /// 100 | /// The ID of the notification to find for. 101 | /// The type (scheduled, triggered or unknown). 102 | public string Type(int id) 103 | { 104 | return this.manager.GetType(id.ToString()).ToString().ToLower(); 105 | } 106 | 107 | /// 108 | /// List of all notifiation by id. 109 | /// 110 | /// The type of the notifications to return for. 111 | /// List of numbers 112 | public int[] Ids(int code) 113 | { 114 | var type = Notification.Type.Unknown; 115 | 116 | switch (code) 117 | { 118 | case 0: 119 | type = Notification.Type.All; 120 | break; 121 | case 1: 122 | type = Notification.Type.Scheduled; 123 | break; 124 | case 2: 125 | type = Notification.Type.Triggered; 126 | break; 127 | } 128 | 129 | return this.manager.GetIdsByType(type).ToArray(); 130 | } 131 | 132 | #pragma warning disable SA1300 // Element must begin with upper-case letter 133 | /// 134 | /// Gets a single notifiation specified by id. 135 | /// 136 | /// The ID of the notification to find. 137 | /// List of options instances 138 | public Options notification(int id) 139 | { 140 | var toast = this.manager.Get(id); 141 | 142 | return toast != null ? toast.Options : null; 143 | } 144 | #pragma warning restore SA1300 // Element must begin with upper-case letter 145 | 146 | /// 147 | /// List of (all) notifiation specified by id. 148 | /// 149 | /// The type of the notifications to return for. 150 | /// Optional list of IDs to find. 151 | /// List of options instances 152 | public Options[] Notifications(int code, [ReadOnlyArray] int[] ids) 153 | { 154 | var type = Notification.Type.Unknown; 155 | 156 | switch (code) 157 | { 158 | case 0: 159 | type = Notification.Type.All; 160 | break; 161 | case 1: 162 | type = Notification.Type.Scheduled; 163 | break; 164 | case 2: 165 | type = Notification.Type.Triggered; 166 | break; 167 | case 3: 168 | return this.manager.GetOptions(ids).ToArray(); 169 | } 170 | 171 | return this.manager.GetOptionsByType(type).ToArray(); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/LocalNotificationProxy.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F5B32CBA-8DAB-43E5-AE4F-98B3B1281FF1} 8 | winmdobj 9 | Properties 10 | LocalNotificationProxy 11 | LocalNotificationProxy 12 | de-DE 13 | UAP 14 | 10.0.16299.0 15 | 10.0.15063.0 16 | 14 17 | 512 18 | {A5A43C5B-DE2A-4C0C-9213-0A381AF9435A};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 19 | false 20 | 21 | 22 | AnyCPU 23 | true 24 | full 25 | false 26 | bin\Debug\ 27 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 28 | prompt 29 | 4 30 | 31 | 32 | AnyCPU 33 | pdbonly 34 | true 35 | bin\Release\ 36 | TRACE;NETFX_CORE;WINDOWS_UWP 37 | prompt 38 | 4 39 | 40 | 41 | x86 42 | true 43 | bin\x86\Debug\ 44 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 45 | ;2008 46 | full 47 | x86 48 | false 49 | prompt 50 | 51 | 52 | x86 53 | bin\x86\Release\ 54 | TRACE;NETFX_CORE;WINDOWS_UWP 55 | true 56 | ;2008 57 | pdbonly 58 | x86 59 | false 60 | prompt 61 | 62 | 63 | ARM 64 | true 65 | bin\ARM\Debug\ 66 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 67 | ;2008 68 | full 69 | ARM 70 | false 71 | prompt 72 | false 73 | false 74 | 75 | 76 | ARM 77 | bin\ARM\Release\ 78 | TRACE;NETFX_CORE;WINDOWS_UWP 79 | true 80 | ;2008 81 | pdbonly 82 | ARM 83 | false 84 | prompt 85 | false 86 | 87 | 88 | x64 89 | true 90 | bin\x64\Debug\ 91 | DEBUG;TRACE;NETFX_CORE;WINDOWS_UWP 92 | ;2008 93 | full 94 | x64 95 | false 96 | prompt 97 | 98 | 99 | x64 100 | bin\x64\Release\ 101 | TRACE;NETFX_CORE;WINDOWS_UWP 102 | true 103 | ;2008 104 | pdbonly 105 | x64 106 | false 107 | prompt 108 | 109 | 110 | PackageReference 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 5.0.2 134 | 135 | 136 | 1.0.2 137 | 138 | 139 | 140 | 141 | {fb381278-f4ad-4703-a12a-c43ee0b231bd} 142 | Microsoft.Toolkit.Uwp.Notifications.UWP 143 | 144 | 145 | 146 | 147 | 14.0 148 | 149 | 150 | 157 | -------------------------------------------------------------------------------- /src/windows/LocalNotificationProxy/LocalNotificationProxy/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("LocalNotificationProxy")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("LocalNotificationProxy")] 13 | [assembly: AssemblyCopyright("Copyright © 2017")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Version information for an assembly consists of the following four values: 18 | // 19 | // Major Version 20 | // Minor Version 21 | // Build Number 22 | // Revision 23 | // 24 | // You can specify all the values or you can default the Build and Revision Numbers 25 | // by using the '*' as shown below: 26 | // [assembly: AssemblyVersion("1.0.*")] 27 | [assembly: AssemblyVersion("1.0.0.0")] 28 | [assembly: AssemblyFileVersion("1.0.0.0")] 29 | [assembly: ComVisible(false)] -------------------------------------------------------------------------------- /src/windows/lib.UW/ARM/LocalNotificationProxy.winmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/src/windows/lib.UW/ARM/LocalNotificationProxy.winmd -------------------------------------------------------------------------------- /src/windows/lib.UW/ARM/Microsoft.Toolkit.Uwp.Notifications.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/src/windows/lib.UW/ARM/Microsoft.Toolkit.Uwp.Notifications.dll -------------------------------------------------------------------------------- /src/windows/lib.UW/x64/LocalNotificationProxy.winmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/src/windows/lib.UW/x64/LocalNotificationProxy.winmd -------------------------------------------------------------------------------- /src/windows/lib.UW/x64/Microsoft.Toolkit.Uwp.Notifications.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/src/windows/lib.UW/x64/Microsoft.Toolkit.Uwp.Notifications.dll -------------------------------------------------------------------------------- /src/windows/lib.UW/x86/LocalNotificationProxy.winmd: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/src/windows/lib.UW/x86/LocalNotificationProxy.winmd -------------------------------------------------------------------------------- /src/windows/lib.UW/x86/Microsoft.Toolkit.Uwp.Notifications.dll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Steffaan/cordova-plugin-local-notifications/06863a7b453706a1335119ac7cdd7cc157f765de/src/windows/lib.UW/x86/Microsoft.Toolkit.Uwp.Notifications.dll --------------------------------------------------------------------------------