local-notification.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672
  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 is scheduled.
  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.isScheduled = function (id, callback, scope) {
  186. var notId = (id || '0').toString();
  187. this.exec('isScheduled', notId, callback, scope);
  188. };
  189. /**
  190. * Check if a notification with an ID was triggered.
  191. *
  192. * @param {String} id
  193. * The ID of the notification
  194. * @param {Function} callback
  195. * A callback function to be called with the list
  196. * @param {Object?} scope
  197. * The scope for the callback function
  198. */
  199. exports.isTriggered = function (id, callback, scope) {
  200. var notId = (id || '0').toString();
  201. this.exec('isTriggered', notId, callback, scope);
  202. };
  203. /**
  204. * List all currently pending notifications.
  205. *
  206. * @param {Function} callback
  207. * A callback function to be called with the list
  208. * @param {Object?} scope
  209. * The scope for the callback function
  210. */
  211. exports.getScheduledIds = function (callback, scope) {
  212. this.exec('getScheduledIds', null, callback, scope);
  213. };
  214. /**
  215. * List all triggered notifications.
  216. *
  217. * @param {Function} callback
  218. * A callback function to be called with the list
  219. * @param {Object?} scope
  220. * The scope for the callback function
  221. */
  222. exports.getTriggeredIds = function (callback, scope) {
  223. this.exec('getTriggeredIds', null, callback, scope);
  224. };
  225. /**
  226. * List all properties for given scheduled notifications.
  227. * If called without IDs, all notification will be returned.
  228. *
  229. * @param {Number[]?} ids
  230. * Set of notification IDs
  231. * @param {Function} callback
  232. * A callback function to be called with the list
  233. * @param {Object?} scope
  234. * The scope for the callback function
  235. */
  236. exports.getScheduled = function () {
  237. var args = Array.apply(null, arguments);
  238. if (typeof args[0] == 'function') {
  239. args.unshift([]);
  240. }
  241. var ids = args[0],
  242. callback = args[1],
  243. scope = args[2];
  244. if (!Array.isArray(ids)) {
  245. ids = [ids];
  246. }
  247. ids = this.convertIds(ids);
  248. this.exec('getScheduled', ids, callback, scope);
  249. };
  250. /**
  251. * Retrieve the properties for all scheduled notifications.
  252. *
  253. * @param {Function} callback
  254. * A callback function to be called with the list
  255. * @param {Object?} scope
  256. * The scope for the callback function
  257. */
  258. exports.getAllScheduled = function (callback, scope) {
  259. this.exec('getScheduled', null, callback, scope);
  260. };
  261. /**
  262. * List all properties for given triggered notifications.
  263. * If called without IDs, all notification will be returned.
  264. *
  265. * @param {Number[]?} ids
  266. * Set of notification IDs
  267. * @param {Function} callback
  268. * A callback function to be called with the list
  269. * @param {Object?} scope
  270. * The scope for the callback function
  271. */
  272. exports.getTriggered = function () {
  273. var args = Array.apply(null, arguments);
  274. if (typeof args[0] == 'function') {
  275. args.unshift([]);
  276. }
  277. var ids = args[0],
  278. callback = args[1],
  279. scope = args[2];
  280. if (!Array.isArray(ids)) {
  281. ids = [ids];
  282. }
  283. ids = this.convertIds(ids);
  284. this.exec('getTriggered', ids, callback, scope);
  285. };
  286. /**
  287. * Retrieve the properties for all triggered notifications.
  288. *
  289. * @param {Function} callback
  290. * A callback function to be called with the list
  291. * @param {Object?} scope
  292. * The scope for the callback function
  293. */
  294. exports.getAllTriggered = function (callback, scope) {
  295. this.exec('getTriggered', null, callback, scope);
  296. };
  297. /**
  298. * Informs if the app has the permission to show notifications.
  299. *
  300. * @param {Function} callback
  301. * The function to be exec as the callback
  302. * @param {Object?} scope
  303. * The callback function's scope
  304. */
  305. exports.hasPermission = function (callback, scope) {
  306. var fn = this.createCallbackFn(callback, scope);
  307. if (device.platform != 'iOS') {
  308. fn(true);
  309. return;
  310. }
  311. exec(fn, null, 'LocalNotification', 'hasPermission', []);
  312. };
  313. /**
  314. * Register permission to show notifications if not already granted.
  315. *
  316. * @param {Function} callback
  317. * The function to be exec as the callback
  318. * @param {Object?} scope
  319. * The callback function's scope
  320. */
  321. exports.registerPermission = function (callback, scope) {
  322. var fn = this.createCallbackFn(callback, scope);
  323. if (device.platform != 'iOS') {
  324. fn(true);
  325. return;
  326. }
  327. exec(fn, null, 'LocalNotification', 'registerPermission', []);
  328. };
  329. /**
  330. * @deprecated
  331. *
  332. * Register permission to show notifications if not already granted.
  333. *
  334. * @param {Function} callback
  335. * The function to be exec as the callback
  336. * @param {Object?} scope
  337. * The callback function's scope
  338. */
  339. exports.promptForPermission = function (callback, scope) {
  340. console.warn('Depreated: Please use `notification.local.registerPermission` instead.');
  341. exports.registerPermission.apply(this, arguments);
  342. };
  343. /**
  344. * Occurs when a notification was added.
  345. *
  346. * @param {String} id
  347. * The ID of the notification
  348. * @param {String} state
  349. * Either "foreground" or "background"
  350. * @param {String} json
  351. * A custom (JSON) string
  352. * @param {Object} data
  353. * The notification properties
  354. */
  355. exports.onadd = function (id, state, json, data) {};
  356. /**
  357. * Occurs when the notification is triggered.
  358. *
  359. * @param {String} id
  360. * The ID of the notification
  361. * @param {String} state
  362. * Either "foreground" or "background"
  363. * @param {String} json
  364. * A custom (JSON) string
  365. * @param {Object} data
  366. * The notification properties
  367. */
  368. exports.ontrigger = function (id, state, json, data) {};
  369. /**
  370. * Fires after the notification was clicked.
  371. *
  372. * @param {String} id
  373. * The ID of the notification
  374. * @param {String} state
  375. * Either "foreground" or "background"
  376. * @param {String} json
  377. * A custom (JSON) string
  378. * @param {Object} data
  379. * The notification properties
  380. */
  381. exports.onclick = function (id, state, json, data) {};
  382. /**
  383. * Fires if the notification was canceled.
  384. *
  385. * @param {String} id
  386. * The ID of the notification
  387. * @param {String} state
  388. * Either "foreground" or "background"
  389. * @param {String} json
  390. * A custom (JSON) string
  391. * @param {Object} data
  392. * The notification properties
  393. */
  394. exports.oncancel = function (id, state, json, data) {};
  395. /**
  396. * Get fired when the notification was cleared.
  397. *
  398. * @param {String} id
  399. * The ID of the notification
  400. * @param {String} state
  401. * Either "foreground" or "background"
  402. * @param {String} json
  403. * A custom (JSON) string
  404. * @param {Object} data
  405. * The notification properties
  406. */
  407. exports.onclear = function (id, state, json, data) {};
  408. /**
  409. * @private
  410. *
  411. * Merges custom properties with the default values.
  412. *
  413. * @param {Object} options
  414. * Set of custom values
  415. *
  416. * @retrun {Object}
  417. * The merged property list
  418. */
  419. exports.mergeWithDefaults = function (options) {
  420. var defaults = this.getDefaults();
  421. options.date = this.getValueFor(options, 'date', 'at', 'firstAt');
  422. options.repeat = this.getValueFor(options, 'repeat', 'every');
  423. options.message = this.getValueFor(options, 'message', 'text');
  424. for (var key in defaults) {
  425. if (options[key] === null || options[key] === undefined) {
  426. options[key] = defaults[key];
  427. }
  428. }
  429. for (key in options) {
  430. if (!defaults.hasOwnProperty(key)) {
  431. delete options[key];
  432. }
  433. }
  434. return options;
  435. };
  436. /**
  437. * @private
  438. *
  439. * Convert the passed values to their required type.
  440. *
  441. * @param {Object} options
  442. * Set of custom values
  443. *
  444. * @retrun {Object}
  445. * The converted property list
  446. */
  447. exports.convertProperties = function (options) {
  448. options.id = options.id.toString();
  449. options.title = options.title.toString();
  450. options.message = options.message.toString();
  451. options.autoCancel = options.autoCancel === true;
  452. if (isNaN(options.id)) {
  453. options.id = this.getDefaults().id;
  454. }
  455. if (isNaN(options.badge)) {
  456. options.badge = this.getDefaults().badge;
  457. }
  458. options.badge = Number(options.badge);
  459. if (options.date === undefined || options.date === null) {
  460. options.date = new Date();
  461. }
  462. if (typeof options.date == 'object') {
  463. options.date = Math.round(options.date.getTime()/1000);
  464. }
  465. if (typeof options.json == 'object') {
  466. options.json = JSON.stringify(options.json);
  467. }
  468. return options;
  469. };
  470. /**
  471. * @private
  472. *
  473. * Merges the platform specific properties into the default properties.
  474. *
  475. * @return {Object}
  476. * The default properties for the platform
  477. */
  478. exports.applyPlatformSpecificOptions = function () {
  479. var defaults = this._defaults;
  480. switch (device.platform) {
  481. case 'Android':
  482. defaults.icon = 'icon';
  483. defaults.smallIcon = null;
  484. defaults.ongoing = false;
  485. defaults.led = 'FFFFFF'; /*RRGGBB*/
  486. defaults.sound = 'TYPE_NOTIFICATION'; break;
  487. case 'iOS':
  488. defaults.sound = ''; break;
  489. case 'WinCE': case 'Win32NT':
  490. defaults.smallImage = null;
  491. defaults.image = null;
  492. defaults.wideImage = null;
  493. }
  494. return defaults;
  495. };
  496. /**
  497. * @private
  498. *
  499. * Creates a callback, which will be executed within a specific scope.
  500. *
  501. * @param {Function} callbackFn
  502. * The callback function
  503. * @param {Object} scope
  504. * The scope for the function
  505. *
  506. * @return {Function}
  507. * The new callback function
  508. */
  509. exports.createCallbackFn = function (callbackFn, scope) {
  510. if (typeof callbackFn != 'function')
  511. return;
  512. return function () {
  513. callbackFn.apply(scope || this, arguments);
  514. };
  515. };
  516. /**
  517. * @private
  518. *
  519. * Convert the IDs to Strings.
  520. *
  521. * @param {String/Number[]} ids
  522. *
  523. * @return Array of Strings
  524. */
  525. exports.convertIds = function (ids) {
  526. var convertedIds = [];
  527. for (var i = 0; i < ids.length; i++) {
  528. convertedIds.push(ids[i].toString());
  529. }
  530. return convertedIds;
  531. };
  532. /**
  533. * @private
  534. *
  535. * Return the first found value for the given keys.
  536. *
  537. * @param {Object} options
  538. * Object with key-value properties
  539. *
  540. * @param {String[]} keys*
  541. * Key list
  542. */
  543. exports.getValueFor = function (options) {
  544. var keys = Array.apply(null, arguments).slice(1);
  545. for (var i = 0; i < keys.length; i++) {
  546. var key = keys[i];
  547. if (options.hasOwnProperty(key)) {
  548. return options[key];
  549. }
  550. }
  551. };
  552. /**
  553. * @private
  554. *
  555. * Executes the native counterpart.
  556. *
  557. * @param {String} action
  558. * The name of the action
  559. * @param args[]
  560. * Array of arguments
  561. * @param {Function} callback
  562. * The callback function
  563. * @param {Object} scope
  564. * The scope for the function
  565. */
  566. exports.exec = function (action, args, callback, scope) {
  567. var fn = this.createCallbackFn(callback, scope),
  568. params = [];
  569. if (Array.isArray(args)) {
  570. params = args;
  571. } else if (args) {
  572. params.push(args);
  573. }
  574. exec(fn, null, 'LocalNotification', action, params);
  575. };