local-notification.js 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638
  1. /*
  2. Copyright 2013-2014 appPlant UG
  3. Licensed to the Apache Software Foundation (ASF) under one
  4. or more contributor license agreements. See the NOTICE file
  5. distributed with this work for additional information
  6. regarding copyright ownership. The ASF licenses this file
  7. to you under the Apache License, Version 2.0 (the
  8. "License"); you may not use this file except in compliance
  9. with the License. You may obtain a copy of the License at
  10. http://www.apache.org/licenses/LICENSE-2.0
  11. Unless required by applicable law or agreed to in writing,
  12. software distributed under the License is distributed on an
  13. "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
  14. KIND, either express or implied. See the License for the
  15. specific language governing permissions and limitations
  16. under the License.
  17. */
  18. var exec = require('cordova/exec'),
  19. channel = require('cordova/channel');
  20. // Called after 'deviceready' event
  21. channel.deviceready.subscribe( function () {
  22. // Device is ready now, the listeners are registered
  23. // and all queued events can be executed.
  24. exec(null, null, 'LocalNotification', 'deviceready', []);
  25. });
  26. // Called before 'deviceready' event
  27. channel.onCordovaReady.subscribe( function () {
  28. // The cordova device plugin is ready now
  29. channel.onCordovaInfoReady.subscribe( function () {
  30. if (device.platform == 'Android') {
  31. channel.onPause.subscribe( function () {
  32. // Necessary to set the state to `background`
  33. exec(null, null, 'LocalNotification', 'pause', []);
  34. });
  35. channel.onResume.subscribe( function () {
  36. // Necessary to set the state to `foreground`
  37. exec(null, null, 'LocalNotification', 'resume', []);
  38. });
  39. // Necessary to set the state to `foreground`
  40. exec(null, null, 'LocalNotification', 'resume', []);
  41. }
  42. // Merges the platform specific properties into the default properties
  43. exports.applyPlatformSpecificOptions();
  44. });
  45. });
  46. /**
  47. * @private
  48. *
  49. * Default values.
  50. */
  51. exports._defaults = {
  52. message: '',
  53. title: '',
  54. autoCancel: false,
  55. badge: -1,
  56. id: '0',
  57. json: '',
  58. repeat: ''
  59. };
  60. /**
  61. * Returns the default settings
  62. *
  63. * @return {Object}
  64. */
  65. exports.getDefaults = function () {
  66. return this._defaults;
  67. };
  68. /**
  69. * Overwrite default settings
  70. *
  71. * @param {Object} defaults
  72. */
  73. exports.setDefaults = function (newDefaults) {
  74. var defaults = this.getDefaults();
  75. for (var key in defaults) {
  76. if (newDefaults[key] !== undefined) {
  77. defaults[key] = newDefaults[key];
  78. }
  79. }
  80. };
  81. /**
  82. * Add a new entry to the registry
  83. *
  84. * @param {Object} opts
  85. * The notification properties
  86. * @param {Function} callback
  87. * A function to be called after the notification has been canceled
  88. * @param {Object?} scope
  89. * The scope for the callback function
  90. */
  91. exports.add = function (opts, callback, scope) {
  92. this.registerPermission(function(granted) {
  93. if (!granted)
  94. return;
  95. var notifications = Array.isArray(opts) ? opts : [opts];
  96. for (var i = 0; i < notifications.length; i++) {
  97. var properties = notifications[i];
  98. this.mergeWithDefaults(properties);
  99. this.convertProperties(properties);
  100. }
  101. this.exec('add', notifications, callback, scope);
  102. }, this);
  103. };
  104. /**
  105. * Update existing notifications specified by IDs in options.
  106. *
  107. * @param {Object} options
  108. * The notification properties to update
  109. * @param {Function} callback
  110. * A function to be called after the notification has been updated
  111. * @param {Object?} scope
  112. * The scope for the callback function
  113. */
  114. exports.update = function (opts, callback, scope) {
  115. var notifications = Array.isArray(opts) ? opts : [opts];
  116. for (var i = 0; i < notifications.length; i++) {
  117. var properties = notifications[i];
  118. this.convertProperties(properties);
  119. }
  120. this.exec('update', notifications, callback, scope);
  121. };
  122. /**
  123. * Clear the specified notification.
  124. *
  125. * @param {String} id
  126. * The ID of the notification
  127. * @param {Function} callback
  128. * A function to be called after the notification has been cleared
  129. * @param {Object?} scope
  130. * The scope for the callback function
  131. */
  132. exports.clear = function (ids, callback, scope) {
  133. ids = Array.isArray(ids) ? ids : [ids];
  134. ids = this.convertIds(ids);
  135. this.exec('clear', ids, callback, scope);
  136. };
  137. /**
  138. * Clear all previously sheduled notifications.
  139. *
  140. * @param {Function} callback
  141. * A function to be called after all notifications have been cleared
  142. * @param {Object?} scope
  143. * The scope for the callback function
  144. */
  145. exports.clearAll = function (callback, scope) {
  146. this.exec('clearAll', null, callback, scope);
  147. };
  148. /**
  149. * Cancel the specified notifications.
  150. *
  151. * @param {String[]} ids
  152. * The IDs of the notifications
  153. * @param {Function} callback
  154. * A function to be called after the notifications has been canceled
  155. * @param {Object?} scope
  156. * The scope for the callback function
  157. */
  158. exports.cancel = function (ids, callback, scope) {
  159. ids = Array.isArray(ids) ? ids : [ids];
  160. ids = this.convertIds(ids);
  161. this.exec('cancel', ids, callback, scope);
  162. };
  163. /**
  164. * Remove all previously registered notifications.
  165. *
  166. * @param {Function} callback
  167. * A function to be called after all notifications have been canceled
  168. * @param {Object?} scope
  169. * The scope for the callback function
  170. */
  171. exports.cancelAll = function (callback, scope) {
  172. this.exec('cancelAll', null, callback, scope);
  173. };
  174. /**
  175. * Check if a notification with an ID is scheduled.
  176. *
  177. * @param {String} id
  178. * The ID of the notification
  179. * @param {Function} callback
  180. * A callback function to be called with the list
  181. * @param {Object?} scope
  182. * The scope for the callback function
  183. */
  184. exports.isScheduled = function (id, callback, scope) {
  185. var notId = (id || '0').toString();
  186. this.exec('isScheduled', notId, callback, scope);
  187. };
  188. /**
  189. * Check if a notification with an ID was triggered.
  190. *
  191. * @param {String} id
  192. * The ID of the notification
  193. * @param {Function} callback
  194. * A callback function to be called with the list
  195. * @param {Object?} scope
  196. * The scope for the callback function
  197. */
  198. exports.isTriggered = function (id, callback, scope) {
  199. var notId = (id || '0').toString();
  200. this.exec('isTriggered', notId, callback, scope);
  201. };
  202. /**
  203. * List all currently pending notifications.
  204. *
  205. * @param {Function} callback
  206. * A callback function to be called with the list
  207. * @param {Object?} scope
  208. * The scope for the callback function
  209. */
  210. exports.getScheduledIds = function (callback, scope) {
  211. this.exec('getScheduledIds', null, callback, scope);
  212. };
  213. /**
  214. * List all triggered notifications.
  215. *
  216. * @param {Function} callback
  217. * A callback function to be called with the list
  218. * @param {Object?} scope
  219. * The scope for the callback function
  220. */
  221. exports.getTriggeredIds = function (callback, scope) {
  222. this.exec('getTriggeredIds', null, callback, scope);
  223. };
  224. /**
  225. * List all properties for given scheduled notifications.
  226. * If called without IDs, all notification will be returned.
  227. *
  228. * @param {Number[]?} ids
  229. * Set of notification IDs
  230. * @param {Function} callback
  231. * A callback function to be called with the list
  232. * @param {Object?} scope
  233. * The scope for the callback function
  234. */
  235. exports.getScheduled = function () {
  236. var args = Array.apply(null, arguments);
  237. if (typeof args[0] == 'function') {
  238. args.unshift([]);
  239. }
  240. var ids = args[0],
  241. callback = args[1],
  242. scope = args[2];
  243. if (!Array.isArray(ids)) {
  244. ids = [ids];
  245. }
  246. ids = this.convertIds(ids);
  247. this.exec('getScheduled', ids, callback, scope);
  248. };
  249. /**
  250. * Retrieve the properties for all scheduled notifications.
  251. *
  252. * @param {Function} callback
  253. * A callback function to be called with the list
  254. * @param {Object?} scope
  255. * The scope for the callback function
  256. */
  257. exports.getAllScheduled = function (callback, scope) {
  258. this.exec('getScheduled', null, callback, scope);
  259. };
  260. /**
  261. * List all properties for given triggered notifications.
  262. * If called without IDs, all notification will be returned.
  263. *
  264. * @param {Number[]?} ids
  265. * Set of notification IDs
  266. * @param {Function} callback
  267. * A callback function to be called with the list
  268. * @param {Object?} scope
  269. * The scope for the callback function
  270. */
  271. exports.getTriggered = function () {
  272. var args = Array.apply(null, arguments);
  273. if (typeof args[0] == 'function') {
  274. args.unshift([]);
  275. }
  276. var ids = args[0],
  277. callback = args[1],
  278. scope = args[2];
  279. if (!Array.isArray(ids)) {
  280. ids = [ids];
  281. }
  282. ids = this.convertIds(ids);
  283. this.exec('getTriggered', ids, callback, scope);
  284. };
  285. /**
  286. * Retrieve the properties for all triggered notifications.
  287. *
  288. * @param {Function} callback
  289. * A callback function to be called with the list
  290. * @param {Object?} scope
  291. * The scope for the callback function
  292. */
  293. exports.getAllTriggered = function (callback, scope) {
  294. this.exec('getTriggered', null, callback, scope);
  295. };
  296. /**
  297. * Informs if the app has the permission to show notifications.
  298. *
  299. * @param {Function} callback
  300. * The function to be exec as the callback
  301. * @param {Object?} scope
  302. * The callback function's scope
  303. */
  304. exports.hasPermission = function (callback, scope) {
  305. var fn = this.createCallbackFn(callback, scope);
  306. if (device.platform != 'iOS') {
  307. fn(true);
  308. return;
  309. }
  310. exec(fn, null, 'LocalNotification', 'hasPermission', []);
  311. };
  312. /**
  313. * Register permission to show notifications if not already granted.
  314. *
  315. * @param {Function} callback
  316. * The function to be exec as the callback
  317. * @param {Object?} scope
  318. * The callback function's scope
  319. */
  320. exports.registerPermission = function (callback, scope) {
  321. var fn = this.createCallbackFn(callback, scope);
  322. if (device.platform != 'iOS') {
  323. fn(true);
  324. return;
  325. }
  326. exec(fn, null, 'LocalNotification', 'registerPermission', []);
  327. };
  328. /**
  329. * @deprecated
  330. *
  331. * Register permission to show notifications if not already granted.
  332. *
  333. * @param {Function} callback
  334. * The function to be exec as the callback
  335. * @param {Object?} scope
  336. * The callback function's scope
  337. */
  338. exports.promptForPermission = function (callback, scope) {
  339. console.warn('Depreated: Please use `notification.local.registerPermission` instead.');
  340. exports.registerPermission.apply(this, arguments);
  341. };
  342. /**
  343. * Occurs when a notification was added.
  344. *
  345. * @param {String} id
  346. * The ID of the notification
  347. * @param {String} state
  348. * Either "foreground" or "background"
  349. * @param {String} json
  350. * A custom (JSON) string
  351. * @param {Object} data
  352. * The notification properties
  353. */
  354. exports.onadd = function (id, state, json, data) {};
  355. /**
  356. * Occurs when the notification is triggered.
  357. *
  358. * @param {String} id
  359. * The ID of the notification
  360. * @param {String} state
  361. * Either "foreground" or "background"
  362. * @param {String} json
  363. * A custom (JSON) string
  364. * @param {Object} data
  365. * The notification properties
  366. */
  367. exports.ontrigger = function (id, state, json, data) {};
  368. /**
  369. * Fires after the notification was clicked.
  370. *
  371. * @param {String} id
  372. * The ID of the notification
  373. * @param {String} state
  374. * Either "foreground" or "background"
  375. * @param {String} json
  376. * A custom (JSON) string
  377. * @param {Object} data
  378. * The notification properties
  379. */
  380. exports.onclick = function (id, state, json, data) {};
  381. /**
  382. * Fires if the notification was canceled.
  383. *
  384. * @param {String} id
  385. * The ID of the notification
  386. * @param {String} state
  387. * Either "foreground" or "background"
  388. * @param {String} json
  389. * A custom (JSON) string
  390. * @param {Object} data
  391. * The notification properties
  392. */
  393. exports.oncancel = function (id, state, json, data) {};
  394. /**
  395. * Get fired when the notification was cleared.
  396. *
  397. * @param {String} id
  398. * The ID of the notification
  399. * @param {String} state
  400. * Either "foreground" or "background"
  401. * @param {String} json
  402. * A custom (JSON) string
  403. * @param {Object} data
  404. * The notification properties
  405. */
  406. exports.onclear = function (id, state, json, data) {};
  407. /**
  408. * @private
  409. *
  410. * Merges custom properties with the default values.
  411. *
  412. * @param {Object} options
  413. * Set of custom values
  414. *
  415. * @retrun {Object}
  416. * The merged property list
  417. */
  418. exports.mergeWithDefaults = function (options) {
  419. var defaults = this.getDefaults();
  420. for (var key in defaults) {
  421. if (options[key] === null || options[key] === undefined) {
  422. options[key] = defaults[key];
  423. }
  424. }
  425. return options;
  426. };
  427. /**
  428. * @private
  429. *
  430. * Convert the passed values to their required type.
  431. *
  432. * @param {Object} options
  433. * Set of custom values
  434. *
  435. * @retrun {Object}
  436. * The converted property list
  437. */
  438. exports.convertProperties = function (options) {
  439. if (options.id) {
  440. options.id = options.id.toString();
  441. }
  442. if (options.date === undefined) {
  443. options.date = new Date();
  444. }
  445. if (options.title) {
  446. options.title = options.title.toString();
  447. }
  448. if (options.message) {
  449. options.message = options.message.toString();
  450. }
  451. if (options.text) {
  452. options.message = options.text.toString();
  453. }
  454. if (typeof options.date == 'object') {
  455. options.date = Math.round(options.date.getTime()/1000);
  456. }
  457. if (typeof options.json == 'object') {
  458. options.json = JSON.stringify(options.json);
  459. }
  460. return options;
  461. };
  462. /**
  463. * @private
  464. *
  465. * Merges the platform specific properties into the default properties.
  466. *
  467. * @return {Object}
  468. * The default properties for the platform
  469. */
  470. exports.applyPlatformSpecificOptions = function () {
  471. var defaults = this._defaults;
  472. switch (device.platform) {
  473. case 'Android':
  474. defaults.icon = 'icon';
  475. defaults.smallIcon = null;
  476. defaults.ongoing = false;
  477. defaults.led = 'FFFFFF'; /*RRGGBB*/
  478. defaults.sound = 'TYPE_NOTIFICATION'; break;
  479. case 'iOS':
  480. defaults.sound = ''; break;
  481. case 'WinCE': case 'Win32NT':
  482. defaults.smallImage = null;
  483. defaults.image = null;
  484. defaults.wideImage = null;
  485. }
  486. return defaults;
  487. };
  488. /**
  489. * @private
  490. *
  491. * Creates a callback, which will be executed within a specific scope.
  492. *
  493. * @param {Function} callbackFn
  494. * The callback function
  495. * @param {Object} scope
  496. * The scope for the function
  497. *
  498. * @return {Function}
  499. * The new callback function
  500. */
  501. exports.createCallbackFn = function (callbackFn, scope) {
  502. if (typeof callbackFn != 'function')
  503. return;
  504. return function () {
  505. callbackFn.apply(scope || this, arguments);
  506. };
  507. };
  508. /**
  509. * @private
  510. *
  511. * Convert the IDs to Strings.
  512. *
  513. * @param {String/Number[]} ids
  514. *
  515. * @return Array of Strings
  516. */
  517. exports.convertIds = function (ids) {
  518. var convertedIds = [];
  519. for (var i = 0; i < ids.length; i++) {
  520. convertedIds.push(ids[i].toString());
  521. }
  522. return convertedIds;
  523. };
  524. /**
  525. * @private
  526. *
  527. * Executes the native counterpart.
  528. *
  529. * @param {String} action
  530. * The name of the action
  531. * @param args[]
  532. * Array of arguments
  533. * @param {Function} callback
  534. * The callback function
  535. * @param {Object} scope
  536. * The scope for the function
  537. */
  538. exports.exec = function (action, args, callback, scope) {
  539. var fn = this.createCallbackFn(callback, scope),
  540. params = [];
  541. if (Array.isArray(args)) {
  542. params = args;
  543. } else if (args) {
  544. params.push(args);
  545. }
  546. exec(fn, null, 'LocalNotification', action, params);
  547. };