local-notification.js 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757
  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. date: undefined
  60. };
  61. /**
  62. * Returns the default settings
  63. *
  64. * @return {Object}
  65. */
  66. exports.getDefaults = function () {
  67. return this._defaults;
  68. };
  69. /**
  70. * Overwrite default settings
  71. *
  72. * @param {Object} defaults
  73. */
  74. exports.setDefaults = function (newDefaults) {
  75. var defaults = this.getDefaults();
  76. for (var key in defaults) {
  77. if (newDefaults[key] !== undefined) {
  78. defaults[key] = newDefaults[key];
  79. }
  80. }
  81. };
  82. /**
  83. * Add a new entry to the registry
  84. *
  85. * @param {Object} opts
  86. * The notification properties
  87. * @param {Function} callback
  88. * A function to be called after the notification has been canceled
  89. * @param {Object?} scope
  90. * The scope for the callback function
  91. */
  92. exports.add = function (opts, callback, scope) {
  93. this.registerPermission(function(granted) {
  94. if (!granted)
  95. return;
  96. var notifications = Array.isArray(opts) ? opts : [opts];
  97. for (var i = 0; i < notifications.length; i++) {
  98. var properties = notifications[i];
  99. this.mergeWithDefaults(properties);
  100. this.convertProperties(properties);
  101. }
  102. this.exec('add', notifications, callback, scope);
  103. }, this);
  104. };
  105. /**
  106. * Update existing notifications specified by IDs in options.
  107. *
  108. * @param {Object} options
  109. * The notification properties to update
  110. * @param {Function} callback
  111. * A function to be called after the notification has been updated
  112. * @param {Object?} scope
  113. * The scope for the callback function
  114. */
  115. exports.update = function (opts, callback, scope) {
  116. var notifications = Array.isArray(opts) ? opts : [opts];
  117. for (var i = 0; i < notifications.length; i++) {
  118. var properties = notifications[i];
  119. this.convertProperties(properties);
  120. }
  121. this.exec('update', notifications, callback, scope);
  122. };
  123. /**
  124. * Clear the specified notification.
  125. *
  126. * @param {String} id
  127. * The ID of the notification
  128. * @param {Function} callback
  129. * A function to be called after the notification has been cleared
  130. * @param {Object?} scope
  131. * The scope for the callback function
  132. */
  133. exports.clear = function (ids, callback, scope) {
  134. ids = Array.isArray(ids) ? ids : [ids];
  135. ids = this.convertIds(ids);
  136. this.exec('clear', ids, callback, scope);
  137. };
  138. /**
  139. * Clear all previously sheduled notifications.
  140. *
  141. * @param {Function} callback
  142. * A function to be called after all notifications have been cleared
  143. * @param {Object?} scope
  144. * The scope for the callback function
  145. */
  146. exports.clearAll = function (callback, scope) {
  147. this.exec('clearAll', null, callback, scope);
  148. };
  149. /**
  150. * Cancel the specified notifications.
  151. *
  152. * @param {String[]} ids
  153. * The IDs of the notifications
  154. * @param {Function} callback
  155. * A function to be called after the notifications has been canceled
  156. * @param {Object?} scope
  157. * The scope for the callback function
  158. */
  159. exports.cancel = function (ids, callback, scope) {
  160. ids = Array.isArray(ids) ? ids : [ids];
  161. ids = this.convertIds(ids);
  162. this.exec('cancel', ids, callback, scope);
  163. };
  164. /**
  165. * Remove all previously registered notifications.
  166. *
  167. * @param {Function} callback
  168. * A function to be called after all notifications have been canceled
  169. * @param {Object?} scope
  170. * The scope for the callback function
  171. */
  172. exports.cancelAll = function (callback, scope) {
  173. this.exec('cancelAll', null, callback, scope);
  174. };
  175. /**
  176. * Check if a notification with an ID exists.
  177. *
  178. * @param {String} id
  179. * The ID of the notification
  180. * @param {Function} callback
  181. * A callback function to be called with the list
  182. * @param {Object?} scope
  183. * The scope for the callback function
  184. */
  185. exports.exist = function (id, callback, scope) {
  186. var notId = (id || '0').toString();
  187. this.exec('exist', notId, callback, scope);
  188. };
  189. /**
  190. * Alias for `exist`.
  191. */
  192. exports.exists = function () {
  193. this.exist.apply(this, arguments);
  194. };
  195. /**
  196. * Check if a notification with an ID is scheduled.
  197. *
  198. * @param {String} id
  199. * The ID of the notification
  200. * @param {Function} callback
  201. * A callback function to be called with the list
  202. * @param {Object?} scope
  203. * The scope for the callback function
  204. */
  205. exports.isScheduled = function (id, callback, scope) {
  206. var notId = (id || '0').toString();
  207. this.exec('isScheduled', notId, callback, scope);
  208. };
  209. /**
  210. * Check if a notification with an ID was triggered.
  211. *
  212. * @param {String} id
  213. * The ID of the notification
  214. * @param {Function} callback
  215. * A callback function to be called with the list
  216. * @param {Object?} scope
  217. * The scope for the callback function
  218. */
  219. exports.isTriggered = function (id, callback, scope) {
  220. var notId = (id || '0').toString();
  221. this.exec('isTriggered', notId, callback, scope);
  222. };
  223. /**
  224. * List all local notification IDs.
  225. *
  226. * @param {Function} callback
  227. * A callback function to be called with the list
  228. * @param {Object?} scope
  229. * The scope for the callback function
  230. */
  231. exports.getAllIds = function (callback, scope) {
  232. this.exec('getAllIds', null, callback, scope);
  233. };
  234. /**
  235. * Alias for `getAllIds`.
  236. */
  237. exports.getIds = function () {
  238. this.getAllIds.apply(this, arguments);
  239. };
  240. /**
  241. * List all scheduled notification IDs.
  242. *
  243. * @param {Function} callback
  244. * A callback function to be called with the list
  245. * @param {Object?} scope
  246. * The scope for the callback function
  247. */
  248. exports.getScheduledIds = function (callback, scope) {
  249. this.exec('getScheduledIds', null, callback, scope);
  250. };
  251. /**
  252. * List all triggered notification IDs.
  253. *
  254. * @param {Function} callback
  255. * A callback function to be called with the list
  256. * @param {Object?} scope
  257. * The scope for the callback function
  258. */
  259. exports.getTriggeredIds = function (callback, scope) {
  260. this.exec('getTriggeredIds', null, callback, scope);
  261. };
  262. /**
  263. * Property list for given local notifications.
  264. * If called without IDs, all notification will be returned.
  265. *
  266. * @param {Number[]?} ids
  267. * Set of notification IDs
  268. * @param {Function} callback
  269. * A callback function to be called with the list
  270. * @param {Object?} scope
  271. * The scope for the callback function
  272. */
  273. exports.get = function () {
  274. var args = Array.apply(null, arguments);
  275. if (typeof args[0] == 'function') {
  276. args.unshift([]);
  277. }
  278. var ids = args[0],
  279. callback = args[1],
  280. scope = args[2];
  281. if (!Array.isArray(ids)) {
  282. ids = [ids];
  283. }
  284. ids = this.convertIds(ids);
  285. this.exec('getAll', ids, callback, scope);
  286. };
  287. /**
  288. * Property list for all local notifications.
  289. *
  290. * @param {Function} callback
  291. * A callback function to be called with the list
  292. * @param {Object?} scope
  293. * The scope for the callback function
  294. */
  295. exports.getAll = function (callback, scope) {
  296. this.exec('getAll', null, callback, scope);
  297. };
  298. /**
  299. * Property list for given scheduled notifications.
  300. * If called without IDs, all notification will be returned.
  301. *
  302. * @param {Number[]?} ids
  303. * Set of notification IDs
  304. * @param {Function} callback
  305. * A callback function to be called with the list
  306. * @param {Object?} scope
  307. * The scope for the callback function
  308. */
  309. exports.getScheduled = function () {
  310. var args = Array.apply(null, arguments);
  311. if (typeof args[0] == 'function') {
  312. args.unshift([]);
  313. }
  314. var ids = args[0],
  315. callback = args[1],
  316. scope = args[2];
  317. if (!Array.isArray(ids)) {
  318. ids = [ids];
  319. }
  320. ids = this.convertIds(ids);
  321. this.exec('getScheduled', ids, callback, scope);
  322. };
  323. /**
  324. * Retrieve the properties for all scheduled notifications.
  325. *
  326. * @param {Function} callback
  327. * A callback function to be called with the list
  328. * @param {Object?} scope
  329. * The scope for the callback function
  330. */
  331. exports.getAllScheduled = function (callback, scope) {
  332. this.exec('getScheduled', null, callback, scope);
  333. };
  334. /**
  335. * Property list for given triggered notifications.
  336. * If called without IDs, all notification will be returned.
  337. *
  338. * @param {Number[]?} ids
  339. * Set of notification IDs
  340. * @param {Function} callback
  341. * A callback function to be called with the list
  342. * @param {Object?} scope
  343. * The scope for the callback function
  344. */
  345. exports.getTriggered = function () {
  346. var args = Array.apply(null, arguments);
  347. if (typeof args[0] == 'function') {
  348. args.unshift([]);
  349. }
  350. var ids = args[0],
  351. callback = args[1],
  352. scope = args[2];
  353. if (!Array.isArray(ids)) {
  354. ids = [ids];
  355. }
  356. ids = this.convertIds(ids);
  357. this.exec('getTriggered', ids, callback, scope);
  358. };
  359. /**
  360. * Retrieve the properties for all triggered notifications.
  361. *
  362. * @param {Function} callback
  363. * A callback function to be called with the list
  364. * @param {Object?} scope
  365. * The scope for the callback function
  366. */
  367. exports.getAllTriggered = function (callback, scope) {
  368. this.exec('getTriggered', null, callback, scope);
  369. };
  370. /**
  371. * Informs if the app has the permission to show notifications.
  372. *
  373. * @param {Function} callback
  374. * The function to be exec as the callback
  375. * @param {Object?} scope
  376. * The callback function's scope
  377. */
  378. exports.hasPermission = function (callback, scope) {
  379. var fn = this.createCallbackFn(callback, scope);
  380. if (device.platform != 'iOS') {
  381. fn(true);
  382. return;
  383. }
  384. exec(fn, null, 'LocalNotification', 'hasPermission', []);
  385. };
  386. /**
  387. * Register permission to show notifications if not already granted.
  388. *
  389. * @param {Function} callback
  390. * The function to be exec as the callback
  391. * @param {Object?} scope
  392. * The callback function's scope
  393. */
  394. exports.registerPermission = function (callback, scope) {
  395. var fn = this.createCallbackFn(callback, scope);
  396. if (device.platform != 'iOS') {
  397. fn(true);
  398. return;
  399. }
  400. exec(fn, null, 'LocalNotification', 'registerPermission', []);
  401. };
  402. /**
  403. * @deprecated
  404. *
  405. * Register permission to show notifications if not already granted.
  406. *
  407. * @param {Function} callback
  408. * The function to be exec as the callback
  409. * @param {Object?} scope
  410. * The callback function's scope
  411. */
  412. exports.promptForPermission = function (callback, scope) {
  413. console.warn('Depreated: Please use `notification.local.registerPermission` instead.');
  414. exports.registerPermission.apply(this, arguments);
  415. };
  416. /**
  417. * Occurs when a notification was added.
  418. *
  419. * @param {String} id
  420. * The ID of the notification
  421. * @param {String} state
  422. * Either "foreground" or "background"
  423. * @param {String} json
  424. * A custom (JSON) string
  425. * @param {Object} data
  426. * The notification properties
  427. */
  428. exports.onadd = function (id, state, json, data) {};
  429. /**
  430. * Occurs when the notification is triggered.
  431. *
  432. * @param {String} id
  433. * The ID of the notification
  434. * @param {String} state
  435. * Either "foreground" or "background"
  436. * @param {String} json
  437. * A custom (JSON) string
  438. * @param {Object} data
  439. * The notification properties
  440. */
  441. exports.ontrigger = function (id, state, json, data) {};
  442. /**
  443. * Fires after the notification was clicked.
  444. *
  445. * @param {String} id
  446. * The ID of the notification
  447. * @param {String} state
  448. * Either "foreground" or "background"
  449. * @param {String} json
  450. * A custom (JSON) string
  451. * @param {Object} data
  452. * The notification properties
  453. */
  454. exports.onclick = function (id, state, json, data) {};
  455. /**
  456. * Fires if the notification was canceled.
  457. *
  458. * @param {String} id
  459. * The ID of the notification
  460. * @param {String} state
  461. * Either "foreground" or "background"
  462. * @param {String} json
  463. * A custom (JSON) string
  464. * @param {Object} data
  465. * The notification properties
  466. */
  467. exports.oncancel = function (id, state, json, data) {};
  468. /**
  469. * Get fired when the notification was cleared.
  470. *
  471. * @param {String} id
  472. * The ID of the notification
  473. * @param {String} state
  474. * Either "foreground" or "background"
  475. * @param {String} json
  476. * A custom (JSON) string
  477. * @param {Object} data
  478. * The notification properties
  479. */
  480. exports.onclear = function (id, state, json, data) {};
  481. /**
  482. * @private
  483. *
  484. * Merges custom properties with the default values.
  485. *
  486. * @param {Object} options
  487. * Set of custom values
  488. *
  489. * @retrun {Object}
  490. * The merged property list
  491. */
  492. exports.mergeWithDefaults = function (options) {
  493. var defaults = this.getDefaults();
  494. options.date = this.getValueFor(options, 'date', 'at', 'firstAt');
  495. options.repeat = this.getValueFor(options, 'repeat', 'every');
  496. options.message = this.getValueFor(options, 'message', 'text');
  497. for (var key in defaults) {
  498. if (options[key] === null || options[key] === undefined) {
  499. options[key] = defaults[key];
  500. }
  501. }
  502. for (key in options) {
  503. if (!defaults.hasOwnProperty(key)) {
  504. delete options[key];
  505. }
  506. }
  507. return options;
  508. };
  509. /**
  510. * @private
  511. *
  512. * Convert the passed values to their required type.
  513. *
  514. * @param {Object} options
  515. * Set of custom values
  516. *
  517. * @retrun {Object}
  518. * The converted property list
  519. */
  520. exports.convertProperties = function (options) {
  521. options.id = options.id.toString();
  522. options.title = options.title.toString();
  523. options.message = options.message.toString();
  524. options.autoCancel = options.autoCancel === true;
  525. if (isNaN(options.id)) {
  526. options.id = this.getDefaults().id;
  527. }
  528. if (isNaN(options.badge)) {
  529. options.badge = this.getDefaults().badge;
  530. }
  531. options.badge = Number(options.badge);
  532. if (options.date === undefined || options.date === null) {
  533. options.date = new Date();
  534. }
  535. if (typeof options.date == 'object') {
  536. options.date = Math.round(options.date.getTime()/1000);
  537. }
  538. if (typeof options.json == 'object') {
  539. options.json = JSON.stringify(options.json);
  540. }
  541. return options;
  542. };
  543. /**
  544. * @private
  545. *
  546. * Merges the platform specific properties into the default properties.
  547. *
  548. * @return {Object}
  549. * The default properties for the platform
  550. */
  551. exports.applyPlatformSpecificOptions = function () {
  552. var defaults = this._defaults;
  553. switch (device.platform) {
  554. case 'Android':
  555. defaults.icon = 'icon';
  556. defaults.smallIcon = null;
  557. defaults.ongoing = false;
  558. defaults.led = 'FFFFFF'; /*RRGGBB*/
  559. defaults.sound = 'TYPE_NOTIFICATION'; break;
  560. case 'iOS':
  561. defaults.sound = ''; break;
  562. case 'WinCE': case 'Win32NT':
  563. defaults.smallImage = null;
  564. defaults.image = null;
  565. defaults.wideImage = null;
  566. }
  567. return defaults;
  568. };
  569. /**
  570. * @private
  571. *
  572. * Creates a callback, which will be executed within a specific scope.
  573. *
  574. * @param {Function} callbackFn
  575. * The callback function
  576. * @param {Object} scope
  577. * The scope for the function
  578. *
  579. * @return {Function}
  580. * The new callback function
  581. */
  582. exports.createCallbackFn = function (callbackFn, scope) {
  583. if (typeof callbackFn != 'function')
  584. return;
  585. return function () {
  586. callbackFn.apply(scope || this, arguments);
  587. };
  588. };
  589. /**
  590. * @private
  591. *
  592. * Convert the IDs to Strings.
  593. *
  594. * @param {String/Number[]} ids
  595. *
  596. * @return Array of Strings
  597. */
  598. exports.convertIds = function (ids) {
  599. var convertedIds = [];
  600. for (var i = 0; i < ids.length; i++) {
  601. convertedIds.push(ids[i].toString());
  602. }
  603. return convertedIds;
  604. };
  605. /**
  606. * @private
  607. *
  608. * Return the first found value for the given keys.
  609. *
  610. * @param {Object} options
  611. * Object with key-value properties
  612. *
  613. * @param {String[]} keys*
  614. * Key list
  615. */
  616. exports.getValueFor = function (options) {
  617. var keys = Array.apply(null, arguments).slice(1);
  618. for (var i = 0; i < keys.length; i++) {
  619. var key = keys[i];
  620. if (options.hasOwnProperty(key)) {
  621. return options[key];
  622. }
  623. }
  624. };
  625. /**
  626. * @private
  627. *
  628. * Executes the native counterpart.
  629. *
  630. * @param {String} action
  631. * The name of the action
  632. * @param args[]
  633. * Array of arguments
  634. * @param {Function} callback
  635. * The callback function
  636. * @param {Object} scope
  637. * The scope for the function
  638. */
  639. exports.exec = function (action, args, callback, scope) {
  640. var fn = this.createCallbackFn(callback, scope),
  641. params = [];
  642. if (Array.isArray(args)) {
  643. params = args;
  644. } else if (args) {
  645. params.push(args);
  646. }
  647. exec(fn, null, 'LocalNotification', action, params);
  648. };