CB-6521: Remove development branch
diff --git a/LICENSE b/LICENSE
deleted file mode 100644
index 7a4a3ea..0000000
--- a/LICENSE
+++ /dev/null
@@ -1,202 +0,0 @@
-
- Apache License
- Version 2.0, January 2004
- http://www.apache.org/licenses/
-
- TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
-
- 1. Definitions.
-
- "License" shall mean the terms and conditions for use, reproduction,
- and distribution as defined by Sections 1 through 9 of this document.
-
- "Licensor" shall mean the copyright owner or entity authorized by
- the copyright owner that is granting the License.
-
- "Legal Entity" shall mean the union of the acting entity and all
- other entities that control, are controlled by, or are under common
- control with that entity. For the purposes of this definition,
- "control" means (i) the power, direct or indirect, to cause the
- direction or management of such entity, whether by contract or
- otherwise, or (ii) ownership of fifty percent (50%) or more of the
- outstanding shares, or (iii) beneficial ownership of such entity.
-
- "You" (or "Your") shall mean an individual or Legal Entity
- exercising permissions granted by this License.
-
- "Source" form shall mean the preferred form for making modifications,
- including but not limited to software source code, documentation
- source, and configuration files.
-
- "Object" form shall mean any form resulting from mechanical
- transformation or translation of a Source form, including but
- not limited to compiled object code, generated documentation,
- and conversions to other media types.
-
- "Work" shall mean the work of authorship, whether in Source or
- Object form, made available under the License, as indicated by a
- copyright notice that is included in or attached to the work
- (an example is provided in the Appendix below).
-
- "Derivative Works" shall mean any work, whether in Source or Object
- form, that is based on (or derived from) the Work and for which the
- editorial revisions, annotations, elaborations, or other modifications
- represent, as a whole, an original work of authorship. For the purposes
- of this License, Derivative Works shall not include works that remain
- separable from, or merely link (or bind by name) to the interfaces of,
- the Work and Derivative Works thereof.
-
- "Contribution" shall mean any work of authorship, including
- the original version of the Work and any modifications or additions
- to that Work or Derivative Works thereof, that is intentionally
- submitted to Licensor for inclusion in the Work by the copyright owner
- or by an individual or Legal Entity authorized to submit on behalf of
- the copyright owner. For the purposes of this definition, "submitted"
- means any form of electronic, verbal, or written communication sent
- to the Licensor or its representatives, including but not limited to
- communication on electronic mailing lists, source code control systems,
- and issue tracking systems that are managed by, or on behalf of, the
- Licensor for the purpose of discussing and improving the Work, but
- excluding communication that is conspicuously marked or otherwise
- designated in writing by the copyright owner as "Not a Contribution."
-
- "Contributor" shall mean Licensor and any individual or Legal Entity
- on behalf of whom a Contribution has been received by Licensor and
- subsequently incorporated within the Work.
-
- 2. Grant of Copyright License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- copyright license to reproduce, prepare Derivative Works of,
- publicly display, publicly perform, sublicense, and distribute the
- Work and such Derivative Works in Source or Object form.
-
- 3. Grant of Patent License. Subject to the terms and conditions of
- this License, each Contributor hereby grants to You a perpetual,
- worldwide, non-exclusive, no-charge, royalty-free, irrevocable
- (except as stated in this section) patent license to make, have made,
- use, offer to sell, sell, import, and otherwise transfer the Work,
- where such license applies only to those patent claims licensable
- by such Contributor that are necessarily infringed by their
- Contribution(s) alone or by combination of their Contribution(s)
- with the Work to which such Contribution(s) was submitted. If You
- institute patent litigation against any entity (including a
- cross-claim or counterclaim in a lawsuit) alleging that the Work
- or a Contribution incorporated within the Work constitutes direct
- or contributory patent infringement, then any patent licenses
- granted to You under this License for that Work shall terminate
- as of the date such litigation is filed.
-
- 4. Redistribution. You may reproduce and distribute copies of the
- Work or Derivative Works thereof in any medium, with or without
- modifications, and in Source or Object form, provided that You
- meet the following conditions:
-
- (a) You must give any other recipients of the Work or
- Derivative Works a copy of this License; and
-
- (b) You must cause any modified files to carry prominent notices
- stating that You changed the files; and
-
- (c) You must retain, in the Source form of any Derivative Works
- that You distribute, all copyright, patent, trademark, and
- attribution notices from the Source form of the Work,
- excluding those notices that do not pertain to any part of
- the Derivative Works; and
-
- (d) If the Work includes a "NOTICE" text file as part of its
- distribution, then any Derivative Works that You distribute must
- include a readable copy of the attribution notices contained
- within such NOTICE file, excluding those notices that do not
- pertain to any part of the Derivative Works, in at least one
- of the following places: within a NOTICE text file distributed
- as part of the Derivative Works; within the Source form or
- documentation, if provided along with the Derivative Works; or,
- within a display generated by the Derivative Works, if and
- wherever such third-party notices normally appear. The contents
- of the NOTICE file are for informational purposes only and
- do not modify the License. You may add Your own attribution
- notices within Derivative Works that You distribute, alongside
- or as an addendum to the NOTICE text from the Work, provided
- that such additional attribution notices cannot be construed
- as modifying the License.
-
- You may add Your own copyright statement to Your modifications and
- may provide additional or different license terms and conditions
- for use, reproduction, or distribution of Your modifications, or
- for any such Derivative Works as a whole, provided Your use,
- reproduction, and distribution of the Work otherwise complies with
- the conditions stated in this License.
-
- 5. Submission of Contributions. Unless You explicitly state otherwise,
- any Contribution intentionally submitted for inclusion in the Work
- by You to the Licensor shall be under the terms and conditions of
- this License, without any additional terms or conditions.
- Notwithstanding the above, nothing herein shall supersede or modify
- the terms of any separate license agreement you may have executed
- with Licensor regarding such Contributions.
-
- 6. Trademarks. This License does not grant permission to use the trade
- names, trademarks, service marks, or product names of the Licensor,
- except as required for reasonable and customary use in describing the
- origin of the Work and reproducing the content of the NOTICE file.
-
- 7. Disclaimer of Warranty. Unless required by applicable law or
- agreed to in writing, Licensor provides the Work (and each
- Contributor provides its Contributions) on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
- implied, including, without limitation, any warranties or conditions
- of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
- PARTICULAR PURPOSE. You are solely responsible for determining the
- appropriateness of using or redistributing the Work and assume any
- risks associated with Your exercise of permissions under this License.
-
- 8. Limitation of Liability. In no event and under no legal theory,
- whether in tort (including negligence), contract, or otherwise,
- unless required by applicable law (such as deliberate and grossly
- negligent acts) or agreed to in writing, shall any Contributor be
- liable to You for damages, including any direct, indirect, special,
- incidental, or consequential damages of any character arising as a
- result of this License or out of the use or inability to use the
- Work (including but not limited to damages for loss of goodwill,
- work stoppage, computer failure or malfunction, or any and all
- other commercial damages or losses), even if such Contributor
- has been advised of the possibility of such damages.
-
- 9. Accepting Warranty or Additional Liability. While redistributing
- the Work or Derivative Works thereof, You may choose to offer,
- and charge a fee for, acceptance of support, warranty, indemnity,
- or other liability obligations and/or rights consistent with this
- License. However, in accepting such obligations, You may act only
- on Your own behalf and on Your sole responsibility, not on behalf
- of any other Contributor, and only if You agree to indemnify,
- defend, and hold each Contributor harmless for any liability
- incurred by, or claims asserted against, such Contributor by reason
- of your accepting any such warranty or additional liability.
-
- END OF TERMS AND CONDITIONS
-
- APPENDIX: How to apply the Apache License to your work.
-
- To apply the Apache License to your work, attach the following
- boilerplate notice, with the fields enclosed by brackets "[]"
- replaced with your own identifying information. (Don't include
- the brackets!) The text should be enclosed in the appropriate
- comment syntax for the file format. We also recommend that a
- file or class name and description of purpose be included on the
- same "printed page" as the copyright notice for easier
- identification within third-party archives.
-
- Copyright [yyyy] [name of copyright owner]
-
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
deleted file mode 100644
index 8ec56a5..0000000
--- a/NOTICE
+++ /dev/null
@@ -1,5 +0,0 @@
-Apache Cordova
-Copyright 2012 The Apache Software Foundation
-
-This product includes software developed at
-The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
index 5b74138..07daee6 100644
--- a/README.md
+++ b/README.md
@@ -20,3 +20,5 @@
# org.apache.cordova.contacts
Plugin documentation: [doc/index.md](doc/index.md)
+
+This is `dev` - the deprecated development branch of this plugin; development of this plugin has moved to the `master` branch
diff --git a/RELEASENOTES.md b/RELEASENOTES.md
deleted file mode 100644
index 30f2c2f..0000000
--- a/RELEASENOTES.md
+++ /dev/null
@@ -1,84 +0,0 @@
-<!--
-#
-# Licensed to the Apache Software Foundation (ASF) under one
-# or more contributor license agreements. See the NOTICE file
-# distributed with this work for additional information
-# regarding copyright ownership. The ASF licenses this file
-# to you under the Apache License, Version 2.0 (the
-# "License"); you may not use this file except in compliance
-# with the License. You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing,
-# software distributed under the License is distributed on an
-# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-# KIND, either express or implied. See the License for the
-# specific language governing permissions and limitations
-# under the License.
-#
--->
-# Release Notes
-
-### 0.2.1 (Sept 5, 2013)
-* [CB-4580] Fixed up duplicate definitions of module id
-* [CB-4432] Copyright notice change
-
-### 0.2.3 (Sept 25, 2013)
-* CB-4889 bumping&resetting version
-* [BlackBerry10] removed uneeded permission tags in plugin.xml
-* [BlackBerry10] removed uneeded permission tags in plugin.xml
-* CB-4889 renaming blackberry10 reference in plugin.xml
-* CB-4888 renaming org.apache.cordova.core.contacts to org.apache.cordova.contacts
-* added contacts api for firefoxos
-* Rename CHANGELOG.md -> RELEASENOTES.md
-* [CB-4824] Fix XCode 5 contacts plugin warnings
-* [CB-4752] Incremented plugin version on dev branch.
-
-### 0.2.4 (Oct 9, 2013)
-* [CB-4950] Remove the dependence on concrete component android.webkit.WebView.
-* [CB-4915] Incremented plugin version on dev branch.
-
- ### 0.2.5 (Oct 28, 2013)
-* CB-5128: added repo + issue tags for contacts
-* [CB-5010] Incremented plugin version on dev branch.
-
-### 0.2.6 (Dec 4, 2013)
-* Fix bad commit/merge
-* CB-3035 Fix issue with windows new line char \n\r
-* wrong example given
-* docs added
-* FxOS name fields are arrays hackedSearch refactored search based on find commented out
-* search hacked via getAll
-* search added - no idea if this is working
-* createMozillaFromCordova and vice versa are used to translate contact objects from one API to another.
-* add/remove working
-* save is working
-* attempt to save is failing trying to limit the translated contact fields to name and familyName, but still failing
-* save is linked with the proxy contact.name doesn't exist www/Contact.js#Contact.prototype.save check on which side is the error
-* CB-5214 Make mobile spec tests on WP8 to run w/o user interaction + Sync with cordova-mobile-spec
-* CB-5525 WP8. Contacts Api fails in case of there is special character in contact field
-* fixed ubuntu policy error
-* [ubuntu] specify policy_group
-* add ubuntu platform
-* CB-3035 Fix issue with windows new line char \n\r
-* 1. Added amazon-fireos platform. 2. Change to use amazon-fireos as the platform if user agent string contains 'cordova-amazon-fireos'.
-* CB-5198 [BlackBerry10] Update dependencies to point to registry
-* handle null filter when fields are specified. ( long standing pull-req from @kevfromireland )
-
-### 0.2.7 (Jan 02, 2014)
-* B-5658 Add doc/index.md for Contacts plugin
-
-### 0.2.8 (Feb 05, 2014)
-* [CB-3208] FFOS docs updated
-* CB-4590 - chooseContact in CDVContacts crashes app
-
-### 0.2.9 (Feb 26, 2014)
-* CB-6086 Fix typo in ffos part of plugin.xml: Camera -> Contacts
-* CB-5994 Switch Contact ID lookup to use Raw contact id.
-
-### 0.2.10 (Apr 17, 2014)
-* CB-6126: [BlackBerry10] Update docs quirks section for fields which are supported
-* CB-6212: [iOS] fix warnings compiled under arm64 64-bit
-* CB-6460: Update license headers
-* Add NOTICE file
diff --git a/doc/index.md b/doc/index.md
deleted file mode 100644
index 83f5a30..0000000
--- a/doc/index.md
+++ /dev/null
@@ -1,687 +0,0 @@
-<!---
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-
-# org.apache.cordova.contacts
-
-Provides access to the device contacts database.
-
-__WARNING__: Collection and use of contact data raises
-important privacy issues. Your app's privacy policy should discuss
-how the app uses contact data and whether it is shared with any other
-parties. Contact information is considered sensitive because it
-reveals the people with whom a person communicates. Therefore, in
-addition to the app's privacy policy, you should strongly consider
-providing a just-in-time notice before the app accesses or uses
-contact data, if the device operating system doesn't do so
-already. That notice should provide the same information noted above,
-as well as obtaining the user's permission (e.g., by presenting
-choices for __OK__ and __No Thanks__). Note that some app
-marketplaces may require the app to provide a just-in-time notice and
-obtain the user's permission before accessing contact data. A
-clear and easy-to-understand user experience surrounding the use of
-contact data helps avoid user confusion and perceived misuse of
-contact data. For more information, please see the Privacy Guide.
-
-## Installation
-
- cordova plugin add org.apache.cordova.contacts
-
-### Firefox OS Quirks
-
-Create __www/manifest.webapp__ as described in
-[Manifest Docs](https://developer.mozilla.org/en-US/Apps/Developing/Manifest).
-Add relevant permisions.
-There is also a need to change the webapp type to "privileged" - [Manifest Docs](https://developer.mozilla.org/en-US/Apps/Developing/Manifest#type).
-__WARNING__: All privileged apps enforce [Content Security Policy](https://developer.mozilla.org/en-US/Apps/CSP) which forbids inline script. Initialize your application in another way.
-
- "type": "privileged",
- "permissions": {
- "contacts": {
- "access": "readwrite",
- "description": "Describe why there is a need for such permission"
- }
- }
-
-## navigator.contacts
-
-### Methods
-
-- navigator.contacts.create
-- navigator.contacts.find
-
-### Objects
-
-- Contact
-- ContactName
-- ContactField
-- ContactAddress
-- ContactOrganization
-- ContactFindOptions
-- ContactError
-
-## navigator.contacts.create
-
-The `navigator.contacts.create` method is synchronous, and returns a new `Contact` object.
-
-This method does not retain the Contact object in the device contacts
-database, for which you need to invoke the `Contact.save` method.
-
-### Supported Platforms
-
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8 ( Note: Windows 8 Contacts are readonly via the Cordova API
-Contacts are not queryable/searchable, you should inform the user to pick a contact as a call to contacts.find will open the 'People' app where the user must choose a contact.
-Any contacts returned are readonly, so your application cannot modify them. )
-
-### Example
-
- var myContact = navigator.contacts.create({"displayName": "Test User"});
-
-## navigator.contacts.find
-
-The `navigator.contacts.find` method executes asynchronously, querying the
-device contacts database and returning an array of `Contact` objects.
-The resulting objects are passed to the `contactSuccess` callback
-function specified by the __contactSuccess__ parameter.
-
-The __contactFields__ parameter specifies the fields to be used as a
-search qualifier, and only those results are passed to the
-__contactSuccess__ callback function. A zero-length __contactFields__
-parameter is invalid and results in
-`ContactError.INVALID_ARGUMENT_ERROR`. A __contactFields__ value of
-`"*"` returns all contact fields.
-
-The __contactFindOptions.filter__ string can be used as a search
-filter when querying the contacts database. If provided, a
-case-insensitive, partial value match is applied to each field
-specified in the __contactFields__ parameter. If there's a match for
-_any_ of the specified fields, the contact is returned.
-
-### Parameters
-
-- __contactFields__: Contact fields to use as a search qualifier. The resulting `Contact` object only features values for these fields. _(DOMString[])_ [Required]
-
-- __contactSuccess__: Success callback function invoked with the array of Contact objects returned from the database. [Required]
-
-- __contactError__: Error callback function, invoked when an error occurs. [Optional]
-
-- __contactFindOptions__: Search options to filter navigator.contacts. [Optional] Keys include:
-
-- __filter__: The search string used to find navigator.contacts. _(DOMString)_ (Default: `""`)
-
-- __multiple__: Determines if the find operation returns multiple navigator.contacts. _(Boolean)_ (Default: `false`)
-
-### Supported Platforms
-
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8 ( read-only support, search requires user interaction, contactFields are ignored, only contactFindOptions.multiple is used to enable the user to select 1 or many contacts. )
-
-### Example
-
- function onSuccess(contacts) {
- alert('Found ' + contacts.length + ' contacts.');
- };
-
- function onError(contactError) {
- alert('onError!');
- };
-
- // find all contacts with 'Bob' in any name field
- var options = new ContactFindOptions();
- options.filter = "Bob";
- options.multiple = true;
- var fields = ["displayName", "name"];
- navigator.contacts.find(fields, onSuccess, onError, options);
-
-
-## Contact
-
-The `Contact` object represents a user's contact. Contacts can be
-created, stored, or removed from the device contacts database.
-Contacts can also be retrieved (individually or in bulk) from the
-database by invoking the `navigator.contacts.find` method.
-
-__NOTE__: Not all of the contact fields listed above are supported on
-every device platform. Please check each platform's _Quirks_ section
-for details.
-
-
-### Properties
-
-- __id__: A globally unique identifier. _(DOMString)_
-
-- __displayName__: The name of this Contact, suitable for display to end users. _(DOMString)_
-
-- __name__: An object containing all components of a persons name. _(ContactName)_
-
-- __nickname__: A casual name by which to address the contact. _(DOMString)_
-
-- __phoneNumbers__: An array of all the contact's phone numbers. _(ContactField[])_
-
-- __emails__: An array of all the contact's email addresses. _(ContactField[])_
-
-- __addresses__: An array of all the contact's addresses. _(ContactAddress[])_
-
-- __ims__: An array of all the contact's IM addresses. _(ContactField[])_
-
-- __organizations__: An array of all the contact's organizations. _(ContactOrganization[])_
-
-- __birthday__: The birthday of the contact. _(Date)_
-
-- __note__: A note about the contact. _(DOMString)_
-
-- __photos__: An array of the contact's photos. _(ContactField[])_
-
-- __categories__: An array of all the user-defined categories associated with the contact. _(ContactField[])_
-
-- __urls__: An array of web pages associated with the contact. _(ContactField[])_
-
-### Methods
-
-- __clone__: Returns a new `Contact` object that is a deep copy of the calling object, with the `id` property set to `null`.
-
-- __remove__: Removes the contact from the device contacts database, otherwise executes an error callback with a `ContactError` object.
-
-- __save__: Saves a new contact to the device contacts database, or updates an existing contact if a contact with the same __id__ already exists.
-
-### Supported Platforms
-
-- Amazon Fire OS
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-
-### Save Example
-
- function onSuccess(contact) {
- alert("Save Success");
- };
-
- function onError(contactError) {
- alert("Error = " + contactError.code);
- };
-
- // create a new contact object
- var contact = navigator.contacts.create();
- contact.displayName = "Plumber";
- contact.nickname = "Plumber"; // specify both to support all devices
-
- // populate some fields
- var name = new ContactName();
- name.givenName = "Jane";
- name.familyName = "Doe";
- contact.name = name;
-
- // save to device
- contact.save(onSuccess,onError);
-
-### Clone Example
-
- // clone the contact object
- var clone = contact.clone();
- clone.name.givenName = "John";
- console.log("Original contact name = " + contact.name.givenName);
- console.log("Cloned contact name = " + clone.name.givenName);
-
-### Remove Example
-
- function onSuccess() {
- alert("Removal Success");
- };
-
- function onError(contactError) {
- alert("Error = " + contactError.code);
- };
-
- // remove the contact from the device
- contact.remove(onSuccess,onError);
-
-
-### Android 2.X Quirks
-
-- __categories__: Not supported on Android 2.X devices, returning `null`.
-
-### BlackBerry 10 Quirks
-
-- __id__: Assigned by the device when saving the contact.
-
-### FirefoxOS Quirks
-
-- __categories__: Partially supported. Fields __pref__ and __type__ are returning `null`
-
-- __ims__: Not supported
-
-- __photos__: Not supported
-
-
-### iOS Quirks
-
-- __displayName__: Not supported on iOS, returning `null` unless there is no `ContactName` specified, in which case it returns the composite name, __nickname__ or `""`, respectively.
-
-- __birthday__: Must be input as a JavaScript `Date` object, the same way it is returned.
-
-- __photos__: Returns a File URL to the image, which is stored in the application's temporary directory. Contents of the temporary directory are removed when the application exits.
-
-- __categories__: This property is currently not supported, returning `null`.
-
-### Windows Phone 7 and 8 Quirks
-
-- __displayName__: When creating a contact, the value provided for the display name parameter differs from the display name retrieved when finding the contact.
-
-- __urls__: When creating a contact, users can input and save more than one web address, but only one is available when searching the contact.
-
-- __phoneNumbers__: The _pref_ option is not supported. The _type_ is not supported in a _find_ operation. Only one `phoneNumber` is allowed for each _type_.
-
-- __emails__: The _pref_ option is not supported. Home and personal references same email entry. Only one entry is allowed for each _type_.
-
-- __addresses__: Supports only work, and home/personal _type_. The home and personal _type_ reference the same address entry. Only one entry is allowed for each _type_.
-
-- __organizations__: Only one is allowed, and does not support the _pref_, _type_, and _department_ attributes.
-
-- __note__: Not supported, returning `null`.
-
-- __ims__: Not supported, returning `null`.
-
-- __birthdays__: Not supported, returning `null`.
-
-- __categories__: Not supported, returning `null`.
-
-
-## ContactAddress
-
-The `ContactAddress` object stores the properties of a single address
-of a contact. A `Contact` object may include more than one address in
-a `ContactAddress[]` array.
-
-
-### Properties
-
-- __pref__: Set to `true` if this `ContactAddress` contains the user's preferred value. _(boolean)_
-
-- __type__: A string indicating what type of field this is, _home_ for example. _(DOMString)_
-
-- __formatted__: The full address formatted for display. _(DOMString)_
-
-- __streetAddress__: The full street address. _(DOMString)_
-
-- __locality__: The city or locality. _(DOMString)_
-
-- __region__: The state or region. _(DOMString)_
-
-- __postalCode__: The zip code or postal code. _(DOMString)_
-
-- __country__: The country name. _(DOMString)_
-
-### Supported Platforms
-
-- Amazon Fire OS
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8
-
-### Example
-
- // display the address information for all contacts
-
- function onSuccess(contacts) {
- for (var i = 0; i < contacts.length; i++) {
- for (var j = 0; j < contacts[i].addresses.length; j++) {
- alert("Pref: " + contacts[i].addresses[j].pref + "\n" +
- "Type: " + contacts[i].addresses[j].type + "\n" +
- "Formatted: " + contacts[i].addresses[j].formatted + "\n" +
- "Street Address: " + contacts[i].addresses[j].streetAddress + "\n" +
- "Locality: " + contacts[i].addresses[j].locality + "\n" +
- "Region: " + contacts[i].addresses[j].region + "\n" +
- "Postal Code: " + contacts[i].addresses[j].postalCode + "\n" +
- "Country: " + contacts[i].addresses[j].country);
- }
- }
- };
-
- function onError(contactError) {
- alert('onError!');
- };
-
- // find all contacts
- var options = new ContactFindOptions();
- options.filter = "";
- var filter = ["displayName", "addresses"];
- navigator.contacts.find(filter, onSuccess, onError, options);
-
-### Android 2.X Quirks
-
-- __pref__: Not supported, returning `false` on Android 2.X devices.
-
-### BlackBerry 10 Quirks
-
-- __pref__: Not supported on BlackBerry devices, returning `false`.
-
-- __type__: Partially supported. Only one each of _Work_ and _Home_ type addresses can be stored per contact.
-
-- __formatted__: Partially supported. Returns a concatenation of all BlackBerry address fields.
-
-- __streetAddress__: Supported. Returns a concatenation of BlackBerry __address1__ and __address2__ address fields.
-
-- __locality__: Supported. Stored in BlackBerry __city__ address field.
-
-- __region__: Supported. Stored in BlackBerry __stateProvince__ address field.
-
-- __postalCode__: Supported. Stored in BlackBerry __zipPostal__ address field.
-
-- __country__: Supported.
-
-### FirefoxOS Quirks
-
-- __formatted__: Currently not supported
-
-### iOS Quirks
-
-- __pref__: Not supported on iOS devices, returning `false`.
-
-- __formatted__: Currently not supported.
-
-### Windows 8 Quirks
-
-- __pref__: Not supported
-
-
-## ContactError
-
-The `ContactError` object is returned to the user through the
-`contactError` callback function when an error occurs.
-
-### Properties
-
-- __code__: One of the predefined error codes listed below.
-
-### Constants
-
-- `ContactError.UNKNOWN_ERROR`
-- `ContactError.INVALID_ARGUMENT_ERROR`
-- `ContactError.TIMEOUT_ERROR`
-- `ContactError.PENDING_OPERATION_ERROR`
-- `ContactError.IO_ERROR`
-- `ContactError.NOT_SUPPORTED_ERROR`
-- `ContactError.PERMISSION_DENIED_ERROR`
-
-
-## ContactField
-
-The `ContactField` object is a reusable component that represents
-contact fields generically. Each `ContactField` object contains a
-`value`, `type`, and `pref` property. A `Contact` object stores
-several properties in `ContactField[]` arrays, such as phone numbers
-and email addresses.
-
-In most instances, there are no pre-determined values for a
-`ContactField` object's __type__ attribute. For example, a phone
-number can specify __type__ values of _home_, _work_, _mobile_,
-_iPhone_, or any other value that is supported by a particular device
-platform's contact database. However, for the `Contact` __photos__
-field, the __type__ field indicates the format of the returned image:
-__url__ when the __value__ attribute contains a URL to the photo
-image, or _base64_ when the __value__ contains a base64-encoded image
-string.
-
-### Properties
-
-- __type__: A string that indicates what type of field this is, _home_ for example. _(DOMString)_
-
-- __value__: The value of the field, such as a phone number or email address. _(DOMString)_
-
-- __pref__: Set to `true` if this `ContactField` contains the user's preferred value. _(boolean)_
-
-### Supported Platforms
-
-- Amazon Fire OS
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8
-
-### Example
-
- // create a new contact
- var contact = navigator.contacts.create();
-
- // store contact phone numbers in ContactField[]
- var phoneNumbers = [];
- phoneNumbers[0] = new ContactField('work', '212-555-1234', false);
- phoneNumbers[1] = new ContactField('mobile', '917-555-5432', true); // preferred number
- phoneNumbers[2] = new ContactField('home', '203-555-7890', false);
- contact.phoneNumbers = phoneNumbers;
-
- // save the contact
- contact.save();
-
-### Android Quirks
-
-- __pref__: Not supported, returning `false`.
-
-### BlackBerry 10 Quirks
-
-- __type__: Partially supported. Used for phone numbers.
-
-- __value__: Supported.
-
-- __pref__: Not supported, returning `false`.
-
-### iOS Quirks
-
-- __pref__: Not supported, returning `false`.
-
-### Windows8 Quirks
-
-- __pref__: Not supported, returning `false`.
-
-
-## ContactName
-
-Contains different kinds of information about a `Contact` object's name.
-
-### Properties
-
-- __formatted__: The complete name of the contact. _(DOMString)_
-
-- __familyName__: The contact's family name. _(DOMString)_
-
-- __givenName__: The contact's given name. _(DOMString)_
-
-- __middleName__: The contact's middle name. _(DOMString)_
-
-- __honorificPrefix__: The contact's prefix (example _Mr._ or _Dr._) _(DOMString)_
-
-- __honorificSuffix__: The contact's suffix (example _Esq._). _(DOMString)_
-
-### Supported Platforms
-
-- Amazon Fire OS
-- Android 2.X
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-- Windows 8
-
-### Example
-
- function onSuccess(contacts) {
- for (var i = 0; i < contacts.length; i++) {
- alert("Formatted: " + contacts[i].name.formatted + "\n" +
- "Family Name: " + contacts[i].name.familyName + "\n" +
- "Given Name: " + contacts[i].name.givenName + "\n" +
- "Middle Name: " + contacts[i].name.middleName + "\n" +
- "Suffix: " + contacts[i].name.honorificSuffix + "\n" +
- "Prefix: " + contacts[i].name.honorificSuffix);
- }
- };
-
- function onError(contactError) {
- alert('onError!');
- };
-
- var options = new ContactFindOptions();
- options.filter = "";
- filter = ["displayName", "name"];
- navigator.contacts.find(filter, onSuccess, onError, options);
-
-### Android Quirks
-
-- __formatted__: Partially supported, and read-only. Returns a concatenation of `honorificPrefix`, `givenName`, `middleName`, `familyName`, and `honorificSuffix`.
-
-### BlackBerry 10 Quirks
-
-- __formatted__: Partially supported. Returns a concatenation of BlackBerry __firstName__ and __lastName__ fields.
-
-- __familyName__: Supported. Stored in BlackBerry __lastName__ field.
-
-- __givenName__: Supported. Stored in BlackBerry __firstName__ field.
-
-- __middleName__: Not supported, returning `null`.
-
-- __honorificPrefix__: Not supported, returning `null`.
-
-- __honorificSuffix__: Not supported, returning `null`.
-
-### FirefoxOS Quirks
-
-- __formatted__: Partially supported, and read-only. Returns a concatenation of `honorificPrefix`, `givenName`, `middleName`, `familyName`, and `honorificSuffix`.
-
-
-### iOS Quirks
-
-- __formatted__: Partially supported. Returns iOS Composite Name, but is read-only.
-
-### Windows 8 Quirks
-
-- __formatted__: This is the only name property, and is identical to `displayName`, and `nickname`
-
-- __familyName__: not supported
-
-- __givenName__: not supported
-
-- __middleName__: not supported
-
-- __honorificPrefix__: not supported
-
-- __honorificSuffix__: not supported
-
-
-## ContactOrganization
-
-The `ContactOrganization` object stores a contact's organization
-properties. A `Contact` object stores one or more
-`ContactOrganization` objects in an array.
-
-### Properties
-
-- __pref__: Set to `true` if this `ContactOrganization` contains the user's preferred value. _(boolean)_
-
-- __type__: A string that indicates what type of field this is, _home_ for example. _(DOMString)
-
-- __name__: The name of the organization. _(DOMString)_
-
-- __department__: The department the contract works for. _(DOMString)_
-
-- __title__: The contact's title at the organization. _(DOMString)_
-
-
-### Supported Platforms
-
-- Android
-- BlackBerry 10
-- Firefox OS
-- iOS
-- Windows Phone 7 and 8
-
-### Example
-
- function onSuccess(contacts) {
- for (var i = 0; i < contacts.length; i++) {
- for (var j = 0; j < contacts[i].organizations.length; j++) {
- alert("Pref: " + contacts[i].organizations[j].pref + "\n" +
- "Type: " + contacts[i].organizations[j].type + "\n" +
- "Name: " + contacts[i].organizations[j].name + "\n" +
- "Department: " + contacts[i].organizations[j].department + "\n" +
- "Title: " + contacts[i].organizations[j].title);
- }
- }
- };
-
- function onError(contactError) {
- alert('onError!');
- };
-
- var options = new ContactFindOptions();
- options.filter = "";
- filter = ["displayName", "organizations"];
- navigator.contacts.find(filter, onSuccess, onError, options);
-
-### Android 2.X Quirks
-
-- __pref__: Not supported by Android 2.X devices, returning `false`.
-
-### BlackBerry 10 Quirks
-
-- __pref__: Not supported by BlackBerry devices, returning `false`.
-
-- __type__: Not supported by BlackBerry devices, returning `null`.
-
-- __name__: Partially supported. The first organization name is stored in the BlackBerry __company__ field.
-
-- __department__: Not supported, returning `null`.
-
-- __title__: Partially supported. The first organization title is stored in the BlackBerry __jobTitle__ field.
-
-### Firefox OS Quirks
-
-- __pref__: Not supported
-
-- __type__: Not supported
-
-- __department__: Not supported
-
-- Fields __name__ and __title__ stored in __org__ and __jobTitle__.
-
-### iOS Quirks
-
-- __pref__: Not supported on iOS devices, returning `false`.
-
-- __type__: Not supported on iOS devices, returning `null`.
-
-- __name__: Partially supported. The first organization name is stored in the iOS __kABPersonOrganizationProperty__ field.
-
-- __department__: Partially supported. The first department name is stored in the iOS __kABPersonDepartmentProperty__ field.
-
-- __title__: Partially supported. The first title is stored in the iOS __kABPersonJobTitleProperty__ field.
diff --git a/plugin.xml b/plugin.xml
deleted file mode 100644
index 676ffd5..0000000
--- a/plugin.xml
+++ /dev/null
@@ -1,215 +0,0 @@
-<?xml version="1.0" encoding="UTF-8"?>
-<!--
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
--->
-
-<plugin xmlns="http://apache.org/cordova/ns/plugins/1.0"
- xmlns:rim="http://www.blackberry.com/ns/widgets"
- xmlns:android="http://schemas.android.com/apk/res/android"
- id="org.apache.cordova.contacts"
- version="0.2.11-dev">
-
- <name>Contacts</name>
- <description>Cordova Contacts Plugin</description>
- <license>Apache 2.0</license>
- <keywords>cordova,contacts</keywords>
- <repo>https://git-wip-us.apache.org/repos/asf/cordova-plugin-contacts.git</repo>
- <issue>https://issues.apache.org/jira/browse/CB/component/12320652</issue>
-
- <js-module src="www/contacts.js" name="contacts">
- <clobbers target="navigator.contacts" />
- </js-module>
-
- <js-module src="www/Contact.js" name="Contact">
- <clobbers target="Contact" />
- </js-module>
-
- <js-module src="www/ContactAddress.js" name="ContactAddress">
- <clobbers target="ContactAddress" />
- </js-module>
-
- <js-module src="www/ContactError.js" name="ContactError">
- <clobbers target="ContactError" />
- </js-module>
-
- <js-module src="www/ContactField.js" name="ContactField">
- <clobbers target="ContactField" />
- </js-module>
-
- <js-module src="www/ContactFindOptions.js" name="ContactFindOptions">
- <clobbers target="ContactFindOptions" />
- </js-module>
-
- <js-module src="www/ContactName.js" name="ContactName">
- <clobbers target="ContactName" />
- </js-module>
-
- <js-module src="www/ContactOrganization.js" name="ContactOrganization">
- <clobbers target="ContactOrganization" />
- </js-module>
-
-
-
-
- <!-- android -->
- <platform name="android">
- <config-file target="res/xml/config.xml" parent="/*">
- <feature name="Contacts">
- <param name="android-package" value="org.apache.cordova.contacts.ContactManager"/>
- </feature>
- </config-file>
-
- <config-file target="AndroidManifest.xml" parent="/*">
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.WRITE_CONTACTS" />
- <uses-permission android:name="android.permission.GET_ACCOUNTS" />
- </config-file>
-
- <source-file src="src/android/ContactAccessor.java" target-dir="src/org/apache/cordova/contacts" />
- <source-file src="src/android/ContactAccessorSdk5.java" target-dir="src/org/apache/cordova/contacts" />
- <source-file src="src/android/ContactManager.java" target-dir="src/org/apache/cordova/contacts" />
- </platform>
-
- <!-- amazon-fireos -->
- <platform name="amazon-fireos">
- <config-file target="res/xml/config.xml" parent="/*">
- <feature name="Contacts">
- <param name="android-package" value="org.apache.cordova.contacts.ContactManager"/>
- </feature>
- </config-file>
-
- <config-file target="AndroidManifest.xml" parent="/*">
- <uses-permission android:name="android.permission.READ_CONTACTS" />
- <uses-permission android:name="android.permission.WRITE_CONTACTS" />
- <uses-permission android:name="android.permission.GET_ACCOUNTS" />
- </config-file>
-
- <source-file src="src/android/ContactAccessor.java" target-dir="src/org/apache/cordova/contacts" />
- <source-file src="src/android/ContactAccessorSdk5.java" target-dir="src/org/apache/cordova/contacts" />
- <source-file src="src/android/ContactManager.java" target-dir="src/org/apache/cordova/contacts" />
- </platform>
-
- <!-- ubuntu -->
- <platform name="ubuntu">
- <config-file target="config.xml" parent="/*">
- <feature name="Contacts">
- <param policy_group="contacts" policy_version="1" />
- </feature>
- </config-file>
- <header-file src="src/ubuntu/contacts.h" />
- <source-file src="src/ubuntu/contacts.cpp" />
- </platform>
-
- <!-- ios -->
- <platform name="ios">
- <config-file target="config.xml" parent="/*">
- <feature name="Contacts">
- <param name="ios-package" value="CDVContacts"/>
- </feature>
- </config-file>
-
- <js-module src="www/ios/contacts.js" name="contacts-ios">
- <merges target="navigator.contacts" />
- </js-module>
-
- <js-module src="www/ios/Contact.js" name="Contact-iOS">
- <merges target="Contact" />
- </js-module>
-
- <header-file src="src/ios/CDVContacts.h" />
- <source-file src="src/ios/CDVContacts.m" />
- <header-file src="src/ios/CDVContact.h" />
- <source-file src="src/ios/CDVContact.m" />
-
- <framework src="AddressBook.framework" weak="true" />
- <framework src="AddressBookUI.framework" weak="true" />
- <framework src="CoreGraphics.framework" />
- </platform>
-
- <!-- blackberry10 -->
- <platform name="blackberry10">
- <config-file target="www/config.xml" parent="/widget">
- <feature name="Contacts" value="Contacts"/>
- </config-file>
- <config-file target="www/config.xml" parent="/widget/rim:permissions">
- <rim:permit>access_pimdomain_contacts</rim:permit>
- </config-file>
- <source-file src="src/blackberry10/index.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/ContactActivity.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/ContactAddress.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/contactConsts.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/ContactError.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/ContactField.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/ContactFindOptions.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/ContactName.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/ContactNews.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/ContactOrganization.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/ContactPhoto.js" target-dir="Contacts"></source-file>
- <source-file src="src/blackberry10/contactUtils.js" target-dir="Contacts"></source-file>
- <dependency id="com.blackberry.utils" />
- <dependency id="com.blackberry.pim.lib" />
- </platform>
-
- <!-- wp7 -->
- <platform name="wp7">
- <config-file target="config.xml" parent="/*">
- <feature name="Contacts">
- <param name="wp-package" value="Contacts"/>
- </feature>
- </config-file>
-
- <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
- <Capability Name="ID_CAP_CONTACTS" />
- </config-file>
-
- <source-file src="src/wp/Contacts.cs" />
- </platform>
-
- <!-- wp8 -->
- <platform name="wp8">
- <config-file target="config.xml" parent="/*">
- <feature name="Contacts">
- <param name="wp-package" value="Contacts"/>
- </feature>
- </config-file>
-
- <config-file target="Properties/WMAppManifest.xml" parent="/Deployment/App/Capabilities">
- <Capability Name="ID_CAP_CONTACTS" />
- </config-file>
-
- <source-file src="src/wp/Contacts.cs" />
- </platform>
-
- <!-- firefoxos -->
- <platform name="firefoxos">
- <config-file target="config.xml" parent="/*">
- <feature name="Contacts">
- <param name="firefoxos-package" value="Contacts" />
- </feature>
- </config-file>
- <js-module src="src/firefoxos/ContactsProxy.js" name="ContactsProxy">
- <runs />
- </js-module>
- </platform>
-
- <!-- wp8 -->
- <js-module src="src/windows8/ContactProxy.js" name="ContactProxy">
- <merges target="" />
- </js-module>
-
-</plugin>
diff --git a/src/android/ContactAccessor.java b/src/android/ContactAccessor.java
deleted file mode 100644
index bac243e..0000000
--- a/src/android/ContactAccessor.java
+++ /dev/null
@@ -1,196 +0,0 @@
-/*
- * Copyright (C) 2009 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.apache.cordova.contacts;
-
-import java.util.HashMap;
-
-import android.util.Log;
-
-import org.apache.cordova.CordovaInterface;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-/**
- * This abstract class defines SDK-independent API for communication with
- * Contacts Provider. The actual implementation used by the application depends
- * on the level of API available on the device. If the API level is Cupcake or
- * Donut, we want to use the {@link ContactAccessorSdk3_4} class. If it is
- * Eclair or higher, we want to use {@link ContactAccessorSdk5}.
- */
-public abstract class ContactAccessor {
-
- protected final String LOG_TAG = "ContactsAccessor";
- protected CordovaInterface mApp;
-
- /**
- * Check to see if the data associated with the key is required to
- * be populated in the Contact object.
- * @param key
- * @param map created by running buildPopulationSet.
- * @return true if the key data is required
- */
- protected boolean isRequired(String key, HashMap<String,Boolean> map) {
- Boolean retVal = map.get(key);
- return (retVal == null) ? false : retVal.booleanValue();
- }
-
- /**
- * Create a hash map of what data needs to be populated in the Contact object
- * @param fields the list of fields to populate
- * @return the hash map of required data
- */
- protected HashMap<String,Boolean> buildPopulationSet(JSONArray fields) {
- HashMap<String,Boolean> map = new HashMap<String,Boolean>();
-
- String key;
- try {
- if (fields.length() == 1 && fields.getString(0).equals("*")) {
- map.put("displayName", true);
- map.put("name", true);
- map.put("nickname", true);
- map.put("phoneNumbers", true);
- map.put("emails", true);
- map.put("addresses", true);
- map.put("ims", true);
- map.put("organizations", true);
- map.put("birthday", true);
- map.put("note", true);
- map.put("urls", true);
- map.put("photos", true);
- map.put("categories", true);
- }
- else {
- for (int i=0; i<fields.length(); i++) {
- key = fields.getString(i);
- if (key.startsWith("displayName")) {
- map.put("displayName", true);
- }
- else if (key.startsWith("name")) {
- map.put("displayName", true);
- map.put("name", true);
- }
- else if (key.startsWith("nickname")) {
- map.put("nickname", true);
- }
- else if (key.startsWith("phoneNumbers")) {
- map.put("phoneNumbers", true);
- }
- else if (key.startsWith("emails")) {
- map.put("emails", true);
- }
- else if (key.startsWith("addresses")) {
- map.put("addresses", true);
- }
- else if (key.startsWith("ims")) {
- map.put("ims", true);
- }
- else if (key.startsWith("organizations")) {
- map.put("organizations", true);
- }
- else if (key.startsWith("birthday")) {
- map.put("birthday", true);
- }
- else if (key.startsWith("note")) {
- map.put("note", true);
- }
- else if (key.startsWith("urls")) {
- map.put("urls", true);
- }
- else if (key.startsWith("photos")) {
- map.put("photos", true);
- }
- else if (key.startsWith("categories")) {
- map.put("categories", true);
- }
- }
- }
- }
- catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return map;
- }
-
- /**
- * Convenience method to get a string from a JSON object. Saves a
- * lot of try/catch writing.
- * If the property is not found in the object null will be returned.
- *
- * @param obj contact object to search
- * @param property to be looked up
- * @return The value of the property
- */
- protected String getJsonString(JSONObject obj, String property) {
- String value = null;
- try {
- if (obj != null) {
- value = obj.getString(property);
- if (value.equals("null")) {
- Log.d(LOG_TAG, property + " is string called 'null'");
- value = null;
- }
- }
- }
- catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get = " + e.getMessage());
- }
- return value;
- }
-
- /**
- * Handles adding a JSON Contact object into the database.
- * @return TODO
- */
- public abstract String save(JSONObject contact);
-
- /**
- * Handles searching through SDK-specific contacts API.
- */
- public abstract JSONArray search(JSONArray filter, JSONObject options);
-
- /**
- * Handles searching through SDK-specific contacts API.
- * @throws JSONException
- */
- public abstract JSONObject getContactById(String id) throws JSONException;
-
- /**
- * Handles removing a contact from the database.
- */
- public abstract boolean remove(String id);
-
- /**
- * A class that represents the where clause to be used in the database query
- */
- class WhereOptions {
- private String where;
- private String[] whereArgs;
- public void setWhere(String where) {
- this.where = where;
- }
- public String getWhere() {
- return where;
- }
- public void setWhereArgs(String[] whereArgs) {
- this.whereArgs = whereArgs;
- }
- public String[] getWhereArgs() {
- return whereArgs;
- }
- }
-}
diff --git a/src/android/ContactAccessorSdk5.java b/src/android/ContactAccessorSdk5.java
deleted file mode 100644
index d8b9592..0000000
--- a/src/android/ContactAccessorSdk5.java
+++ /dev/null
@@ -1,2181 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-
-package org.apache.cordova.contacts;
-
-import android.accounts.Account;
-import android.accounts.AccountManager;
-import android.content.ContentProviderOperation;
-import android.content.ContentProviderResult;
-import android.content.ContentUris;
-import android.content.ContentValues;
-import android.content.OperationApplicationException;
-import android.database.Cursor;
-import android.net.Uri;
-import android.os.RemoteException;
-import android.provider.ContactsContract;
-import android.util.Log;
-
-import org.apache.cordova.CordovaInterface;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URL;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.Map;
-import java.util.Set;
-//import android.app.Activity;
-//import android.content.Context;
-
-/**
- * An implementation of {@link ContactAccessor} that uses current Contacts API.
- * This class should be used on Eclair or beyond, but would not work on any earlier
- * release of Android. As a matter of fact, it could not even be loaded.
- * <p>
- * This implementation has several advantages:
- * <ul>
- * <li>It sees contacts from multiple accounts.
- * <li>It works with aggregated contacts. So for example, if the contact is the result
- * of aggregation of two raw contacts from different accounts, it may return the name from
- * one and the phone number from the other.
- * <li>It is efficient because it uses the more efficient current API.
- * <li>Not obvious in this particular example, but it has access to new kinds
- * of data available exclusively through the new APIs. Exercise for the reader: add support
- * for nickname (see {@link android.provider.ContactsContract.CommonDataKinds.Nickname}) or
- * social status updates (see {@link android.provider.ContactsContract.StatusUpdates}).
- * </ul>
- */
-
-public class ContactAccessorSdk5 extends ContactAccessor {
-
- /**
- * Keep the photo size under the 1 MB blog limit.
- */
- private static final long MAX_PHOTO_SIZE = 1048576;
-
- private static final String EMAIL_REGEXP = ".+@.+\\.+.+"; /* <anything>@<anything>.<anything>*/
-
- /**
- * A static map that converts the JavaScript property name to Android database column name.
- */
- private static final Map<String, String> dbMap = new HashMap<String, String>();
- static {
- dbMap.put("id", ContactsContract.Data.CONTACT_ID);
- dbMap.put("displayName", ContactsContract.Contacts.DISPLAY_NAME);
- dbMap.put("name", ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
- dbMap.put("name.formatted", ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
- dbMap.put("name.familyName", ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
- dbMap.put("name.givenName", ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
- dbMap.put("name.middleName", ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME);
- dbMap.put("name.honorificPrefix", ContactsContract.CommonDataKinds.StructuredName.PREFIX);
- dbMap.put("name.honorificSuffix", ContactsContract.CommonDataKinds.StructuredName.SUFFIX);
- dbMap.put("nickname", ContactsContract.CommonDataKinds.Nickname.NAME);
- dbMap.put("phoneNumbers", ContactsContract.CommonDataKinds.Phone.NUMBER);
- dbMap.put("phoneNumbers.value", ContactsContract.CommonDataKinds.Phone.NUMBER);
- dbMap.put("emails", ContactsContract.CommonDataKinds.Email.DATA);
- dbMap.put("emails.value", ContactsContract.CommonDataKinds.Email.DATA);
- dbMap.put("addresses", ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS);
- dbMap.put("addresses.formatted", ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS);
- dbMap.put("addresses.streetAddress", ContactsContract.CommonDataKinds.StructuredPostal.STREET);
- dbMap.put("addresses.locality", ContactsContract.CommonDataKinds.StructuredPostal.CITY);
- dbMap.put("addresses.region", ContactsContract.CommonDataKinds.StructuredPostal.REGION);
- dbMap.put("addresses.postalCode", ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE);
- dbMap.put("addresses.country", ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY);
- dbMap.put("ims", ContactsContract.CommonDataKinds.Im.DATA);
- dbMap.put("ims.value", ContactsContract.CommonDataKinds.Im.DATA);
- dbMap.put("organizations", ContactsContract.CommonDataKinds.Organization.COMPANY);
- dbMap.put("organizations.name", ContactsContract.CommonDataKinds.Organization.COMPANY);
- dbMap.put("organizations.department", ContactsContract.CommonDataKinds.Organization.DEPARTMENT);
- dbMap.put("organizations.title", ContactsContract.CommonDataKinds.Organization.TITLE);
- dbMap.put("birthday", ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE);
- dbMap.put("note", ContactsContract.CommonDataKinds.Note.NOTE);
- dbMap.put("photos.value", ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
- //dbMap.put("categories.value", null);
- dbMap.put("urls", ContactsContract.CommonDataKinds.Website.URL);
- dbMap.put("urls.value", ContactsContract.CommonDataKinds.Website.URL);
- }
-
- /**
- * Create an contact accessor.
- */
- public ContactAccessorSdk5(CordovaInterface context) {
- mApp = context;
- }
-
- /**
- * This method takes the fields required and search options in order to produce an
- * array of contacts that matches the criteria provided.
- * @param fields an array of items to be used as search criteria
- * @param options that can be applied to contact searching
- * @return an array of contacts
- */
- @Override
- public JSONArray search(JSONArray fields, JSONObject options) {
- // Get the find options
- String searchTerm = "";
- int limit = Integer.MAX_VALUE;
- boolean multiple = true;
-
- if (options != null) {
- searchTerm = options.optString("filter");
- if (searchTerm.length() == 0) {
- searchTerm = "%";
- }
- else {
- searchTerm = "%" + searchTerm + "%";
- }
-
- try {
- multiple = options.getBoolean("multiple");
- if (!multiple) {
- limit = 1;
- }
- } catch (JSONException e) {
- // Multiple was not specified so we assume the default is true.
- }
- }
- else {
- searchTerm = "%";
- }
-
-
- //Log.d(LOG_TAG, "Search Term = " + searchTerm);
- //Log.d(LOG_TAG, "Field Length = " + fields.length());
- //Log.d(LOG_TAG, "Fields = " + fields.toString());
-
- // Loop through the fields the user provided to see what data should be returned.
- HashMap<String, Boolean> populate = buildPopulationSet(fields);
-
- // Build the ugly where clause and where arguments for one big query.
- WhereOptions whereOptions = buildWhereClause(fields, searchTerm);
-
- // Get all the id's where the search term matches the fields passed in.
- Cursor idCursor = mApp.getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
- new String[] { ContactsContract.Data.CONTACT_ID },
- whereOptions.getWhere(),
- whereOptions.getWhereArgs(),
- ContactsContract.Data.CONTACT_ID + " ASC");
-
- // Create a set of unique ids
- Set<String> contactIds = new HashSet<String>();
- int idColumn = -1;
- while (idCursor.moveToNext()) {
- if (idColumn < 0) {
- idColumn = idCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID);
- }
- contactIds.add(idCursor.getString(idColumn));
- }
- idCursor.close();
-
- // Build a query that only looks at ids
- WhereOptions idOptions = buildIdClause(contactIds, searchTerm);
-
- // Determine which columns we should be fetching.
- HashSet<String> columnsToFetch = new HashSet<String>();
- columnsToFetch.add(ContactsContract.Data.CONTACT_ID);
- columnsToFetch.add(ContactsContract.Data.RAW_CONTACT_ID);
- columnsToFetch.add(ContactsContract.Data.MIMETYPE);
-
- if (isRequired("displayName", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
- }
- if (isRequired("name", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.PREFIX);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredName.SUFFIX);
- }
- if (isRequired("phoneNumbers", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.Phone._ID);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Phone.NUMBER);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Phone.TYPE);
- }
- if (isRequired("emails", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.Email._ID);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Email.DATA);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Email.TYPE);
- }
- if (isRequired("addresses", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal._ID);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.TYPE);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.STREET);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.CITY);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.REGION);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE);
- columnsToFetch.add(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY);
- }
- if (isRequired("organizations", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.Organization._ID);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.TYPE);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.DEPARTMENT);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.COMPANY);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Organization.TITLE);
- }
- if (isRequired("ims", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.Im._ID);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Im.DATA);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Im.TYPE);
- }
- if (isRequired("note", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.Note.NOTE);
- }
- if (isRequired("nickname", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.Nickname.NAME);
- }
- if (isRequired("urls", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.Website._ID);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Website.URL);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Website.TYPE);
- }
- if (isRequired("birthday", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.Event.START_DATE);
- columnsToFetch.add(ContactsContract.CommonDataKinds.Event.TYPE);
- }
- if (isRequired("photos", populate)) {
- columnsToFetch.add(ContactsContract.CommonDataKinds.Photo._ID);
- }
-
- // Do the id query
- Cursor c = mApp.getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
- columnsToFetch.toArray(new String[] {}),
- idOptions.getWhere(),
- idOptions.getWhereArgs(),
- ContactsContract.Data.CONTACT_ID + " ASC");
-
- JSONArray contacts = populateContactArray(limit, populate, c);
- return contacts;
- }
-
- /**
- * A special search that finds one contact by id
- *
- * @param id contact to find by id
- * @return a JSONObject representing the contact
- * @throws JSONException
- */
- public JSONObject getContactById(String id) throws JSONException {
- // Do the id query
- Cursor c = mApp.getActivity().getContentResolver().query(ContactsContract.Data.CONTENT_URI,
- null,
- ContactsContract.Data.RAW_CONTACT_ID + " = ? ",
- new String[] { id },
- ContactsContract.Data.RAW_CONTACT_ID + " ASC");
-
- JSONArray fields = new JSONArray();
- fields.put("*");
-
- HashMap<String, Boolean> populate = buildPopulationSet(fields);
-
- JSONArray contacts = populateContactArray(1, populate, c);
-
- if (contacts.length() == 1) {
- return contacts.getJSONObject(0);
- } else {
- return null;
- }
- }
-
- /**
- * Creates an array of contacts from the cursor you pass in
- *
- * @param limit max number of contacts for the array
- * @param populate whether or not you should populate a certain value
- * @param c the cursor
- * @return a JSONArray of contacts
- */
- private JSONArray populateContactArray(int limit,
- HashMap<String, Boolean> populate, Cursor c) {
-
- String contactId = "";
- String rawId = "";
- String oldContactId = "";
- boolean newContact = true;
- String mimetype = "";
-
- JSONArray contacts = new JSONArray();
- JSONObject contact = new JSONObject();
- JSONArray organizations = new JSONArray();
- JSONArray addresses = new JSONArray();
- JSONArray phones = new JSONArray();
- JSONArray emails = new JSONArray();
- JSONArray ims = new JSONArray();
- JSONArray websites = new JSONArray();
- JSONArray photos = new JSONArray();
-
- // Column indices
- int colContactId = c.getColumnIndex(ContactsContract.Data.CONTACT_ID);
- int colRawContactId = c.getColumnIndex(ContactsContract.Data.RAW_CONTACT_ID);
- int colMimetype = c.getColumnIndex(ContactsContract.Data.MIMETYPE);
- int colDisplayName = c.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME);
- int colNote = c.getColumnIndex(ContactsContract.CommonDataKinds.Note.NOTE);
- int colNickname = c.getColumnIndex(ContactsContract.CommonDataKinds.Nickname.NAME);
- int colBirthday = c.getColumnIndex(ContactsContract.CommonDataKinds.Event.START_DATE);
- int colEventType = c.getColumnIndex(ContactsContract.CommonDataKinds.Event.TYPE);
-
- if (c.getCount() > 0) {
- while (c.moveToNext() && (contacts.length() <= (limit - 1))) {
- try {
- contactId = c.getString(colContactId);
- rawId = c.getString(colRawContactId);
-
- // If we are in the first row set the oldContactId
- if (c.getPosition() == 0) {
- oldContactId = contactId;
- }
-
- // When the contact ID changes we need to push the Contact object
- // to the array of contacts and create new objects.
- if (!oldContactId.equals(contactId)) {
- // Populate the Contact object with it's arrays
- // and push the contact into the contacts array
- contacts.put(populateContact(contact, organizations, addresses, phones,
- emails, ims, websites, photos));
-
- // Clean up the objects
- contact = new JSONObject();
- organizations = new JSONArray();
- addresses = new JSONArray();
- phones = new JSONArray();
- emails = new JSONArray();
- ims = new JSONArray();
- websites = new JSONArray();
- photos = new JSONArray();
-
- // Set newContact to true as we are starting to populate a new contact
- newContact = true;
- }
-
- // When we detect a new contact set the ID and display name.
- // These fields are available in every row in the result set returned.
- if (newContact) {
- newContact = false;
- contact.put("id", contactId);
- contact.put("rawId", rawId);
- }
-
- // Grab the mimetype of the current row as it will be used in a lot of comparisons
- mimetype = c.getString(colMimetype);
-
- if (mimetype.equals(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)) {
- contact.put("displayName", c.getString(colDisplayName));
- }
-
- if (mimetype.equals(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
- && isRequired("name", populate)) {
- contact.put("name", nameQuery(c));
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
- && isRequired("phoneNumbers", populate)) {
- phones.put(phoneQuery(c));
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
- && isRequired("emails", populate)) {
- emails.put(emailQuery(c));
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)
- && isRequired("addresses", populate)) {
- addresses.put(addressQuery(c));
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
- && isRequired("organizations", populate)) {
- organizations.put(organizationQuery(c));
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- && isRequired("ims", populate)) {
- ims.put(imQuery(c));
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE)
- && isRequired("note", populate)) {
- contact.put("note", c.getString(colNote));
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE)
- && isRequired("nickname", populate)) {
- contact.put("nickname", c.getString(colNickname));
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE)
- && isRequired("urls", populate)) {
- websites.put(websiteQuery(c));
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE)) {
- if (isRequired("birthday", populate) &&
- ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY == c.getInt(colEventType)) {
- contact.put("birthday", c.getString(colBirthday));
- }
- }
- else if (mimetype.equals(ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
- && isRequired("photos", populate)) {
- photos.put(photoQuery(c, contactId));
- }
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
-
- // Set the old contact ID
- oldContactId = contactId;
-
- }
-
- // Push the last contact into the contacts array
- if (contacts.length() < limit) {
- contacts.put(populateContact(contact, organizations, addresses, phones,
- emails, ims, websites, photos));
- }
- }
- c.close();
- return contacts;
- }
-
- /**
- * Builds a where clause all all the ids passed into the method
- * @param contactIds a set of unique contact ids
- * @param searchTerm what to search for
- * @return an object containing the selection and selection args
- */
- private WhereOptions buildIdClause(Set<String> contactIds, String searchTerm) {
- WhereOptions options = new WhereOptions();
-
- // If the user is searching for every contact then short circuit the method
- // and return a shorter where clause to be searched.
- if (searchTerm.equals("%")) {
- options.setWhere("(" + ContactsContract.Data.CONTACT_ID + " LIKE ? )");
- options.setWhereArgs(new String[] { searchTerm });
- return options;
- }
-
- // This clause means that there are specific ID's to be populated
- Iterator<String> it = contactIds.iterator();
- StringBuffer buffer = new StringBuffer("(");
-
- while (it.hasNext()) {
- buffer.append("'" + it.next() + "'");
- if (it.hasNext()) {
- buffer.append(",");
- }
- }
- buffer.append(")");
-
- options.setWhere(ContactsContract.Data.CONTACT_ID + " IN " + buffer.toString());
- options.setWhereArgs(null);
-
- return options;
- }
-
- /**
- * Create a new contact using a JSONObject to hold all the data.
- * @param contact
- * @param organizations array of organizations
- * @param addresses array of addresses
- * @param phones array of phones
- * @param emails array of emails
- * @param ims array of instant messenger addresses
- * @param websites array of websites
- * @param photos
- * @return
- */
- private JSONObject populateContact(JSONObject contact, JSONArray organizations,
- JSONArray addresses, JSONArray phones, JSONArray emails,
- JSONArray ims, JSONArray websites, JSONArray photos) {
- try {
- // Only return the array if it has at least one entry
- if (organizations.length() > 0) {
- contact.put("organizations", organizations);
- }
- if (addresses.length() > 0) {
- contact.put("addresses", addresses);
- }
- if (phones.length() > 0) {
- contact.put("phoneNumbers", phones);
- }
- if (emails.length() > 0) {
- contact.put("emails", emails);
- }
- if (ims.length() > 0) {
- contact.put("ims", ims);
- }
- if (websites.length() > 0) {
- contact.put("urls", websites);
- }
- if (photos.length() > 0) {
- contact.put("photos", photos);
- }
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return contact;
- }
-
- /**
- * Take the search criteria passed into the method and create a SQL WHERE clause.
- * @param fields the properties to search against
- * @param searchTerm the string to search for
- * @return an object containing the selection and selection args
- */
- private WhereOptions buildWhereClause(JSONArray fields, String searchTerm) {
-
- ArrayList<String> where = new ArrayList<String>();
- ArrayList<String> whereArgs = new ArrayList<String>();
-
- WhereOptions options = new WhereOptions();
-
- /*
- * Special case where the user wants all fields returned
- */
- if (isWildCardSearch(fields)) {
- // Get all contacts with all properties
- if ("%".equals(searchTerm)) {
- options.setWhere("(" + ContactsContract.Contacts.DISPLAY_NAME + " LIKE ? )");
- options.setWhereArgs(new String[] { searchTerm });
- return options;
- } else {
- // Get all contacts that match the filter but return all properties
- where.add("(" + dbMap.get("displayName") + " LIKE ? )");
- whereArgs.add(searchTerm);
- where.add("(" + dbMap.get("name") + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
- where.add("(" + dbMap.get("nickname") + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE);
- where.add("(" + dbMap.get("phoneNumbers") + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
- where.add("(" + dbMap.get("emails") + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
- where.add("(" + dbMap.get("addresses") + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
- where.add("(" + dbMap.get("ims") + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
- where.add("(" + dbMap.get("organizations") + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
- where.add("(" + dbMap.get("note") + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE);
- where.add("(" + dbMap.get("urls") + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE);
- }
- }
-
- /*
- * Special case for when the user wants all the contacts but
- */
- if ("%".equals(searchTerm)) {
- options.setWhere("(" + ContactsContract.Contacts.DISPLAY_NAME + " LIKE ? )");
- options.setWhereArgs(new String[] { searchTerm });
- return options;
- }
-
- String key;
- try {
- //Log.d(LOG_TAG, "How many fields do we have = " + fields.length());
- for (int i = 0; i < fields.length(); i++) {
- key = fields.getString(i);
-
- if (key.equals("id")) {
- where.add("(" + dbMap.get(key) + " = ? )");
- whereArgs.add(searchTerm.substring(1, searchTerm.length() - 1));
- }
- else if (key.startsWith("displayName")) {
- where.add("(" + dbMap.get(key) + " LIKE ? )");
- whereArgs.add(searchTerm);
- }
- else if (key.startsWith("name")) {
- where.add("(" + dbMap.get(key) + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE);
- }
- else if (key.startsWith("nickname")) {
- where.add("(" + dbMap.get(key) + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE);
- }
- else if (key.startsWith("phoneNumbers")) {
- where.add("(" + dbMap.get(key) + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
- }
- else if (key.startsWith("emails")) {
- where.add("(" + dbMap.get(key) + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
- }
- else if (key.startsWith("addresses")) {
- where.add("(" + dbMap.get(key) + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
- }
- else if (key.startsWith("ims")) {
- where.add("(" + dbMap.get(key) + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
- }
- else if (key.startsWith("organizations")) {
- where.add("(" + dbMap.get(key) + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
- }
- // else if (key.startsWith("birthday")) {
-// where.add("(" + dbMap.get(key) + " LIKE ? AND "
-// + ContactsContract.Data.MIMETYPE + " = ? )");
-// }
- else if (key.startsWith("note")) {
- where.add("(" + dbMap.get(key) + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE);
- }
- else if (key.startsWith("urls")) {
- where.add("(" + dbMap.get(key) + " LIKE ? AND "
- + ContactsContract.Data.MIMETYPE + " = ? )");
- whereArgs.add(searchTerm);
- whereArgs.add(ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE);
- }
- }
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
-
- // Creating the where string
- StringBuffer selection = new StringBuffer();
- for (int i = 0; i < where.size(); i++) {
- selection.append(where.get(i));
- if (i != (where.size() - 1)) {
- selection.append(" OR ");
- }
- }
- options.setWhere(selection.toString());
-
- // Creating the where args array
- String[] selectionArgs = new String[whereArgs.size()];
- for (int i = 0; i < whereArgs.size(); i++) {
- selectionArgs[i] = whereArgs.get(i);
- }
- options.setWhereArgs(selectionArgs);
-
- return options;
- }
-
- /**
- * If the user passes in the '*' wildcard character for search then they want all fields for each contact
- *
- * @param fields
- * @return true if wildcard search requested, false otherwise
- */
- private boolean isWildCardSearch(JSONArray fields) {
- // Only do a wildcard search if we are passed ["*"]
- if (fields.length() == 1) {
- try {
- if ("*".equals(fields.getString(0))) {
- return true;
- }
- } catch (JSONException e) {
- return false;
- }
- }
- return false;
- }
-
- /**
- * Create a ContactOrganization JSONObject
- * @param cursor the current database row
- * @return a JSONObject representing a ContactOrganization
- */
- private JSONObject organizationQuery(Cursor cursor) {
- JSONObject organization = new JSONObject();
- try {
- organization.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization._ID)));
- organization.put("pref", false); // Android does not store pref attribute
- organization.put("type", getOrgType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TYPE))));
- organization.put("department", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.DEPARTMENT)));
- organization.put("name", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.COMPANY)));
- organization.put("title", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TITLE)));
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return organization;
- }
-
- /**
- * Create a ContactAddress JSONObject
- * @param cursor the current database row
- * @return a JSONObject representing a ContactAddress
- */
- private JSONObject addressQuery(Cursor cursor) {
- JSONObject address = new JSONObject();
- try {
- address.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal._ID)));
- address.put("pref", false); // Android does not store pref attribute
- address.put("type", getAddressType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Organization.TYPE))));
- address.put("formatted", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS)));
- address.put("streetAddress", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.STREET)));
- address.put("locality", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.CITY)));
- address.put("region", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.REGION)));
- address.put("postalCode", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE)));
- address.put("country", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY)));
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return address;
- }
-
- /**
- * Create a ContactName JSONObject
- * @param cursor the current database row
- * @return a JSONObject representing a ContactName
- */
- private JSONObject nameQuery(Cursor cursor) {
- JSONObject contactName = new JSONObject();
- try {
- String familyName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME));
- String givenName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME));
- String middleName = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME));
- String honorificPrefix = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.PREFIX));
- String honorificSuffix = cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.SUFFIX));
-
- // Create the formatted name
- StringBuffer formatted = new StringBuffer("");
- if (honorificPrefix != null) {
- formatted.append(honorificPrefix + " ");
- }
- if (givenName != null) {
- formatted.append(givenName + " ");
- }
- if (middleName != null) {
- formatted.append(middleName + " ");
- }
- if (familyName != null) {
- formatted.append(familyName);
- }
- if (honorificSuffix != null) {
- formatted.append(" " + honorificSuffix);
- }
-
- contactName.put("familyName", familyName);
- contactName.put("givenName", givenName);
- contactName.put("middleName", middleName);
- contactName.put("honorificPrefix", honorificPrefix);
- contactName.put("honorificSuffix", honorificSuffix);
- contactName.put("formatted", formatted);
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return contactName;
- }
-
- /**
- * Create a ContactField JSONObject
- * @param cursor the current database row
- * @return a JSONObject representing a ContactField
- */
- private JSONObject phoneQuery(Cursor cursor) {
- JSONObject phoneNumber = new JSONObject();
- try {
- phoneNumber.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone._ID)));
- phoneNumber.put("pref", false); // Android does not store pref attribute
- phoneNumber.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
- phoneNumber.put("type", getPhoneType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE))));
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- } catch (Exception excp) {
- Log.e(LOG_TAG, excp.getMessage(), excp);
- }
- return phoneNumber;
- }
-
- /**
- * Create a ContactField JSONObject
- * @param cursor the current database row
- * @return a JSONObject representing a ContactField
- */
- private JSONObject emailQuery(Cursor cursor) {
- JSONObject email = new JSONObject();
- try {
- email.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email._ID)));
- email.put("pref", false); // Android does not store pref attribute
- email.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.DATA)));
- email.put("type", getContactType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Email.TYPE))));
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return email;
- }
-
- /**
- * Create a ContactField JSONObject
- * @param cursor the current database row
- * @return a JSONObject representing a ContactField
- */
- private JSONObject imQuery(Cursor cursor) {
- JSONObject im = new JSONObject();
- try {
- im.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im._ID)));
- im.put("pref", false); // Android does not store pref attribute
- im.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.DATA)));
- im.put("type", getImType(cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Im.PROTOCOL))));
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return im;
- }
-
- /**
- * Create a ContactField JSONObject
- * @param cursor the current database row
- * @return a JSONObject representing a ContactField
- */
- private JSONObject websiteQuery(Cursor cursor) {
- JSONObject website = new JSONObject();
- try {
- website.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website._ID)));
- website.put("pref", false); // Android does not store pref attribute
- website.put("value", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.URL)));
- website.put("type", getContactType(cursor.getInt(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Website.TYPE))));
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return website;
- }
-
- /**
- * Create a ContactField JSONObject
- * @param contactId
- * @return a JSONObject representing a ContactField
- */
- private JSONObject photoQuery(Cursor cursor, String contactId) {
- JSONObject photo = new JSONObject();
- try {
- photo.put("id", cursor.getString(cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo._ID)));
- photo.put("pref", false);
- photo.put("type", "url");
- Uri person = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, (new Long(contactId)));
- Uri photoUri = Uri.withAppendedPath(person, ContactsContract.Contacts.Photo.CONTENT_DIRECTORY);
- photo.put("value", photoUri.toString());
- } catch (JSONException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return photo;
- }
-
- @Override
- /**
- * This method will save a contact object into the devices contacts database.
- *
- * @param contact the contact to be saved.
- * @returns the id if the contact is successfully saved, null otherwise.
- */
- public String save(JSONObject contact) {
- AccountManager mgr = AccountManager.get(mApp.getActivity());
- Account[] accounts = mgr.getAccounts();
- String accountName = null;
- String accountType = null;
-
- if (accounts.length == 1) {
- accountName = accounts[0].name;
- accountType = accounts[0].type;
- }
- else if (accounts.length > 1) {
- for (Account a : accounts) {
- if (a.type.contains("eas") && a.name.matches(EMAIL_REGEXP)) /*Exchange ActiveSync*/{
- accountName = a.name;
- accountType = a.type;
- break;
- }
- }
- if (accountName == null) {
- for (Account a : accounts) {
- if (a.type.contains("com.google") && a.name.matches(EMAIL_REGEXP)) /*Google sync provider*/{
- accountName = a.name;
- accountType = a.type;
- break;
- }
- }
- }
- if (accountName == null) {
- for (Account a : accounts) {
- if (a.name.matches(EMAIL_REGEXP)) /*Last resort, just look for an email address...*/{
- accountName = a.name;
- accountType = a.type;
- break;
- }
- }
- }
- }
-
- String id = getJsonString(contact, "id");
- if (id == null) {
- // Create new contact
- return createNewContact(contact, accountType, accountName);
- } else {
- // Modify existing contact
- return modifyContact(id, contact, accountType, accountName);
- }
- }
-
- /**
- * Creates a new contact and stores it in the database
- *
- * @param id the raw contact id which is required for linking items to the contact
- * @param contact the contact to be saved
- * @param account the account to be saved under
- */
- private String modifyContact(String id, JSONObject contact, String accountType, String accountName) {
- // Get the RAW_CONTACT_ID which is needed to insert new values in an already existing contact.
- // But not needed to update existing values.
- int rawId = (new Integer(getJsonString(contact, "rawId"))).intValue();
-
- // Create a list of attributes to add to the contact database
- ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
-
- //Add contact type
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.RawContacts.CONTENT_URI)
- .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
- .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
- .build());
-
- // Modify name
- JSONObject name;
- try {
- String displayName = getJsonString(contact, "displayName");
- name = contact.getJSONObject("name");
- if (displayName != null || name != null) {
- ContentProviderOperation.Builder builder = ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { id, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE });
-
- if (displayName != null) {
- builder.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName);
- }
-
- String familyName = getJsonString(name, "familyName");
- if (familyName != null) {
- builder.withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, familyName);
- }
- String middleName = getJsonString(name, "middleName");
- if (middleName != null) {
- builder.withValue(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, middleName);
- }
- String givenName = getJsonString(name, "givenName");
- if (givenName != null) {
- builder.withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, givenName);
- }
- String honorificPrefix = getJsonString(name, "honorificPrefix");
- if (honorificPrefix != null) {
- builder.withValue(ContactsContract.CommonDataKinds.StructuredName.PREFIX, honorificPrefix);
- }
- String honorificSuffix = getJsonString(name, "honorificSuffix");
- if (honorificSuffix != null) {
- builder.withValue(ContactsContract.CommonDataKinds.StructuredName.SUFFIX, honorificSuffix);
- }
-
- ops.add(builder.build());
- }
- } catch (JSONException e1) {
- Log.d(LOG_TAG, "Could not get name");
- }
-
- // Modify phone numbers
- JSONArray phones = null;
- try {
- phones = contact.getJSONArray("phoneNumbers");
- if (phones != null) {
- // Delete all the phones
- if (phones.length() == 0) {
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { "" + rawId, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE })
- .build());
- }
- // Modify or add a phone
- else {
- for (int i = 0; i < phones.length(); i++) {
- JSONObject phone = (JSONObject) phones.get(i);
- String phoneId = getJsonString(phone, "id");
- // This is a new phone so do a DB insert
- if (phoneId == null) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
- contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE);
- contentValues.put(ContactsContract.CommonDataKinds.Phone.NUMBER, getJsonString(phone, "value"));
- contentValues.put(ContactsContract.CommonDataKinds.Phone.TYPE, getPhoneType(getJsonString(phone, "type")));
-
- ops.add(ContentProviderOperation.newInsert(
- ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
- }
- // This is an existing phone so do a DB update
- else {
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.CommonDataKinds.Phone._ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { phoneId, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE })
- .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, getJsonString(phone, "value"))
- .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, getPhoneType(getJsonString(phone, "type")))
- .build());
- }
- }
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get phone numbers");
- }
-
- // Modify emails
- JSONArray emails = null;
- try {
- emails = contact.getJSONArray("emails");
- if (emails != null) {
- // Delete all the emails
- if (emails.length() == 0) {
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { "" + rawId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE })
- .build());
- }
- // Modify or add a email
- else {
- for (int i = 0; i < emails.length(); i++) {
- JSONObject email = (JSONObject) emails.get(i);
- String emailId = getJsonString(email, "id");
- // This is a new email so do a DB insert
- if (emailId == null) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
- contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE);
- contentValues.put(ContactsContract.CommonDataKinds.Email.DATA, getJsonString(email, "value"));
- contentValues.put(ContactsContract.CommonDataKinds.Email.TYPE, getContactType(getJsonString(email, "type")));
-
- ops.add(ContentProviderOperation.newInsert(
- ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
- }
- // This is an existing email so do a DB update
- else {
- String emailValue=getJsonString(email, "value");
- if(!emailValue.isEmpty()) {
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.CommonDataKinds.Email._ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { emailId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE })
- .withValue(ContactsContract.CommonDataKinds.Email.DATA, getJsonString(email, "value"))
- .withValue(ContactsContract.CommonDataKinds.Email.TYPE, getContactType(getJsonString(email, "type")))
- .build());
- } else {
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.CommonDataKinds.Email._ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { emailId, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE })
- .build());
- }
- }
- }
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get emails");
- }
-
- // Modify addresses
- JSONArray addresses = null;
- try {
- addresses = contact.getJSONArray("addresses");
- if (addresses != null) {
- // Delete all the addresses
- if (addresses.length() == 0) {
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { "" + rawId, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE })
- .build());
- }
- // Modify or add a address
- else {
- for (int i = 0; i < addresses.length(); i++) {
- JSONObject address = (JSONObject) addresses.get(i);
- String addressId = getJsonString(address, "id");
- // This is a new address so do a DB insert
- if (addressId == null) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
- contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE);
- contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, getAddressType(getJsonString(address, "type")));
- contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, getJsonString(address, "formatted"));
- contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.STREET, getJsonString(address, "streetAddress"));
- contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.CITY, getJsonString(address, "locality"));
- contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.REGION, getJsonString(address, "region"));
- contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, getJsonString(address, "postalCode"));
- contentValues.put(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, getJsonString(address, "country"));
-
- ops.add(ContentProviderOperation.newInsert(
- ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
- }
- // This is an existing address so do a DB update
- else {
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.CommonDataKinds.StructuredPostal._ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { addressId, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE })
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, getAddressType(getJsonString(address, "type")))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, getJsonString(address, "formatted"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.STREET, getJsonString(address, "streetAddress"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.CITY, getJsonString(address, "locality"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.REGION, getJsonString(address, "region"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, getJsonString(address, "postalCode"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, getJsonString(address, "country"))
- .build());
- }
- }
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get addresses");
- }
-
- // Modify organizations
- JSONArray organizations = null;
- try {
- organizations = contact.getJSONArray("organizations");
- if (organizations != null) {
- // Delete all the organizations
- if (organizations.length() == 0) {
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { "" + rawId, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE })
- .build());
- }
- // Modify or add a organization
- else {
- for (int i = 0; i < organizations.length(); i++) {
- JSONObject org = (JSONObject) organizations.get(i);
- String orgId = getJsonString(org, "id");
- // This is a new organization so do a DB insert
- if (orgId == null) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
- contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE);
- contentValues.put(ContactsContract.CommonDataKinds.Organization.TYPE, getOrgType(getJsonString(org, "type")));
- contentValues.put(ContactsContract.CommonDataKinds.Organization.DEPARTMENT, getJsonString(org, "department"));
- contentValues.put(ContactsContract.CommonDataKinds.Organization.COMPANY, getJsonString(org, "name"));
- contentValues.put(ContactsContract.CommonDataKinds.Organization.TITLE, getJsonString(org, "title"));
-
- ops.add(ContentProviderOperation.newInsert(
- ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
- }
- // This is an existing organization so do a DB update
- else {
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.CommonDataKinds.Organization._ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { orgId, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE })
- .withValue(ContactsContract.CommonDataKinds.Organization.TYPE, getOrgType(getJsonString(org, "type")))
- .withValue(ContactsContract.CommonDataKinds.Organization.DEPARTMENT, getJsonString(org, "department"))
- .withValue(ContactsContract.CommonDataKinds.Organization.COMPANY, getJsonString(org, "name"))
- .withValue(ContactsContract.CommonDataKinds.Organization.TITLE, getJsonString(org, "title"))
- .build());
- }
- }
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get organizations");
- }
-
- // Modify IMs
- JSONArray ims = null;
- try {
- ims = contact.getJSONArray("ims");
- if (ims != null) {
- // Delete all the ims
- if (ims.length() == 0) {
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { "" + rawId, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE })
- .build());
- }
- // Modify or add a im
- else {
- for (int i = 0; i < ims.length(); i++) {
- JSONObject im = (JSONObject) ims.get(i);
- String imId = getJsonString(im, "id");
- // This is a new IM so do a DB insert
- if (imId == null) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
- contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE);
- contentValues.put(ContactsContract.CommonDataKinds.Im.DATA, getJsonString(im, "value"));
- contentValues.put(ContactsContract.CommonDataKinds.Im.TYPE, getImType(getJsonString(im, "type")));
-
- ops.add(ContentProviderOperation.newInsert(
- ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
- }
- // This is an existing IM so do a DB update
- else {
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.CommonDataKinds.Im._ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { imId, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE })
- .withValue(ContactsContract.CommonDataKinds.Im.DATA, getJsonString(im, "value"))
- .withValue(ContactsContract.CommonDataKinds.Im.TYPE, getContactType(getJsonString(im, "type")))
- .build());
- }
- }
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get emails");
- }
-
- // Modify note
- String note = getJsonString(contact, "note");
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { id, ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE })
- .withValue(ContactsContract.CommonDataKinds.Note.NOTE, note)
- .build());
-
- // Modify nickname
- String nickname = getJsonString(contact, "nickname");
- if (nickname != null) {
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { id, ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE })
- .withValue(ContactsContract.CommonDataKinds.Nickname.NAME, nickname)
- .build());
- }
-
- // Modify urls
- JSONArray websites = null;
- try {
- websites = contact.getJSONArray("urls");
- if (websites != null) {
- // Delete all the websites
- if (websites.length() == 0) {
- Log.d(LOG_TAG, "This means we should be deleting all the phone numbers.");
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { "" + rawId, ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE })
- .build());
- }
- // Modify or add a website
- else {
- for (int i = 0; i < websites.length(); i++) {
- JSONObject website = (JSONObject) websites.get(i);
- String websiteId = getJsonString(website, "id");
- // This is a new website so do a DB insert
- if (websiteId == null) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
- contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE);
- contentValues.put(ContactsContract.CommonDataKinds.Website.DATA, getJsonString(website, "value"));
- contentValues.put(ContactsContract.CommonDataKinds.Website.TYPE, getContactType(getJsonString(website, "type")));
-
- ops.add(ContentProviderOperation.newInsert(
- ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
- }
- // This is an existing website so do a DB update
- else {
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.CommonDataKinds.Website._ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { websiteId, ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE })
- .withValue(ContactsContract.CommonDataKinds.Website.DATA, getJsonString(website, "value"))
- .withValue(ContactsContract.CommonDataKinds.Website.TYPE, getContactType(getJsonString(website, "type")))
- .build());
- }
- }
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get websites");
- }
-
- // Modify birthday
- String birthday = getJsonString(contact, "birthday");
- if (birthday != null) {
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=? AND " +
- ContactsContract.CommonDataKinds.Event.TYPE + "=?",
- new String[] { id, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE, new String("" + ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY) })
- .withValue(ContactsContract.CommonDataKinds.Event.TYPE, ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY)
- .withValue(ContactsContract.CommonDataKinds.Event.START_DATE, birthday)
- .build());
- }
-
- // Modify photos
- JSONArray photos = null;
- try {
- photos = contact.getJSONArray("photos");
- if (photos != null) {
- // Delete all the photos
- if (photos.length() == 0) {
- ops.add(ContentProviderOperation.newDelete(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.Data.RAW_CONTACT_ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { "" + rawId, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE })
- .build());
- }
- // Modify or add a photo
- else {
- for (int i = 0; i < photos.length(); i++) {
- JSONObject photo = (JSONObject) photos.get(i);
- String photoId = getJsonString(photo, "id");
- byte[] bytes = getPhotoBytes(getJsonString(photo, "value"));
- // This is a new photo so do a DB insert
- if (photoId == null) {
- ContentValues contentValues = new ContentValues();
- contentValues.put(ContactsContract.Data.RAW_CONTACT_ID, rawId);
- contentValues.put(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE);
- contentValues.put(ContactsContract.Data.IS_SUPER_PRIMARY, 1);
- contentValues.put(ContactsContract.CommonDataKinds.Photo.PHOTO, bytes);
-
- ops.add(ContentProviderOperation.newInsert(
- ContactsContract.Data.CONTENT_URI).withValues(contentValues).build());
- }
- // This is an existing photo so do a DB update
- else {
- ops.add(ContentProviderOperation.newUpdate(ContactsContract.Data.CONTENT_URI)
- .withSelection(ContactsContract.CommonDataKinds.Photo._ID + "=? AND " +
- ContactsContract.Data.MIMETYPE + "=?",
- new String[] { photoId, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE })
- .withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
- .withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, bytes)
- .build());
- }
- }
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get photos");
- }
-
- boolean retVal = true;
-
- //Modify contact
- try {
- mApp.getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
- } catch (RemoteException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- Log.e(LOG_TAG, Log.getStackTraceString(e), e);
- retVal = false;
- } catch (OperationApplicationException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- Log.e(LOG_TAG, Log.getStackTraceString(e), e);
- retVal = false;
- }
-
- // if the save was a success return the contact ID
- if (retVal) {
- return id;
- } else {
- return null;
- }
- }
-
- /**
- * Add a website to a list of database actions to be performed
- *
- * @param ops the list of database actions
- * @param website the item to be inserted
- */
- private void insertWebsite(ArrayList<ContentProviderOperation> ops,
- JSONObject website) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Website.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Website.DATA, getJsonString(website, "value"))
- .withValue(ContactsContract.CommonDataKinds.Website.TYPE, getContactType(getJsonString(website, "type")))
- .build());
- }
-
- /**
- * Add an im to a list of database actions to be performed
- *
- * @param ops the list of database actions
- * @param im the item to be inserted
- */
- private void insertIm(ArrayList<ContentProviderOperation> ops, JSONObject im) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Im.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Im.DATA, getJsonString(im, "value"))
- .withValue(ContactsContract.CommonDataKinds.Im.TYPE, getImType(getJsonString(im, "type")))
- .build());
- }
-
- /**
- * Add an organization to a list of database actions to be performed
- *
- * @param ops the list of database actions
- * @param org the item to be inserted
- */
- private void insertOrganization(ArrayList<ContentProviderOperation> ops,
- JSONObject org) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Organization.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Organization.TYPE, getOrgType(getJsonString(org, "type")))
- .withValue(ContactsContract.CommonDataKinds.Organization.DEPARTMENT, getJsonString(org, "department"))
- .withValue(ContactsContract.CommonDataKinds.Organization.COMPANY, getJsonString(org, "name"))
- .withValue(ContactsContract.CommonDataKinds.Organization.TITLE, getJsonString(org, "title"))
- .build());
- }
-
- /**
- * Add an address to a list of database actions to be performed
- *
- * @param ops the list of database actions
- * @param address the item to be inserted
- */
- private void insertAddress(ArrayList<ContentProviderOperation> ops,
- JSONObject address) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredPostal.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.TYPE, getAddressType(getJsonString(address, "type")))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.FORMATTED_ADDRESS, getJsonString(address, "formatted"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.STREET, getJsonString(address, "streetAddress"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.CITY, getJsonString(address, "locality"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.REGION, getJsonString(address, "region"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.POSTCODE, getJsonString(address, "postalCode"))
- .withValue(ContactsContract.CommonDataKinds.StructuredPostal.COUNTRY, getJsonString(address, "country"))
- .build());
- }
-
- /**
- * Add an email to a list of database actions to be performed
- *
- * @param ops the list of database actions
- * @param email the item to be inserted
- */
- private void insertEmail(ArrayList<ContentProviderOperation> ops,
- JSONObject email) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Email.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Email.DATA, getJsonString(email, "value"))
- .withValue(ContactsContract.CommonDataKinds.Email.TYPE, getContactType(getJsonString(email, "type")))
- .build());
- }
-
- /**
- * Add a phone to a list of database actions to be performed
- *
- * @param ops the list of database actions
- * @param phone the item to be inserted
- */
- private void insertPhone(ArrayList<ContentProviderOperation> ops,
- JSONObject phone) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, getJsonString(phone, "value"))
- .withValue(ContactsContract.CommonDataKinds.Phone.TYPE, getPhoneType(getJsonString(phone, "type")))
- .build());
- }
-
- /**
- * Add a phone to a list of database actions to be performed
- *
- * @param ops the list of database actions
- * @param phone the item to be inserted
- */
- private void insertPhoto(ArrayList<ContentProviderOperation> ops,
- JSONObject photo) {
- byte[] bytes = getPhotoBytes(getJsonString(photo, "value"));
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.IS_SUPER_PRIMARY, 1)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, bytes)
- .build());
- }
-
- /**
- * Gets the raw bytes from the supplied filename
- *
- * @param filename the file to read the bytes from
- * @return a byte array
- * @throws IOException
- */
- private byte[] getPhotoBytes(String filename) {
- ByteArrayOutputStream buffer = new ByteArrayOutputStream();
- try {
- int bytesRead = 0;
- long totalBytesRead = 0;
- byte[] data = new byte[8192];
- InputStream in = getPathFromUri(filename);
-
- while ((bytesRead = in.read(data, 0, data.length)) != -1 && totalBytesRead <= MAX_PHOTO_SIZE) {
- buffer.write(data, 0, bytesRead);
- totalBytesRead += bytesRead;
- }
-
- in.close();
- buffer.flush();
- } catch (FileNotFoundException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- } catch (IOException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return buffer.toByteArray();
- }
-
- /**
- * Get an input stream based on file path or uri content://, http://, file://
- *
- * @param path
- * @return an input stream
- * @throws IOException
- */
- private InputStream getPathFromUri(String path) throws IOException {
- if (path.startsWith("content:")) {
- Uri uri = Uri.parse(path);
- return mApp.getActivity().getContentResolver().openInputStream(uri);
- }
- if (path.startsWith("http:") || path.startsWith("https:") || path.startsWith("file:")) {
- URL url = new URL(path);
- return url.openStream();
- }
- else {
- return new FileInputStream(path);
- }
- }
-
- /**
- * Creates a new contact and stores it in the database
- *
- * @param contact the contact to be saved
- * @param account the account to be saved under
- */
- private String createNewContact(JSONObject contact, String accountType, String accountName) {
- // Create a list of attributes to add to the contact database
- ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
-
- //Add contact type
- ops.add(ContentProviderOperation.newInsert(ContactsContract.RawContacts.CONTENT_URI)
- .withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
- .withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
- .build());
-
- // Add name
- try {
- JSONObject name = contact.optJSONObject("name");
- String displayName = contact.getString("displayName");
- if (displayName != null || name != null) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
- .withValue(ContactsContract.CommonDataKinds.StructuredName.FAMILY_NAME, getJsonString(name, "familyName"))
- .withValue(ContactsContract.CommonDataKinds.StructuredName.MIDDLE_NAME, getJsonString(name, "middleName"))
- .withValue(ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME, getJsonString(name, "givenName"))
- .withValue(ContactsContract.CommonDataKinds.StructuredName.PREFIX, getJsonString(name, "honorificPrefix"))
- .withValue(ContactsContract.CommonDataKinds.StructuredName.SUFFIX, getJsonString(name, "honorificSuffix"))
- .build());
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get name object");
- }
-
- //Add phone numbers
- JSONArray phones = null;
- try {
- phones = contact.getJSONArray("phoneNumbers");
- if (phones != null) {
- for (int i = 0; i < phones.length(); i++) {
- JSONObject phone = (JSONObject) phones.get(i);
- insertPhone(ops, phone);
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get phone numbers");
- }
-
- // Add emails
- JSONArray emails = null;
- try {
- emails = contact.getJSONArray("emails");
- if (emails != null) {
- for (int i = 0; i < emails.length(); i++) {
- JSONObject email = (JSONObject) emails.get(i);
- insertEmail(ops, email);
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get emails");
- }
-
- // Add addresses
- JSONArray addresses = null;
- try {
- addresses = contact.getJSONArray("addresses");
- if (addresses != null) {
- for (int i = 0; i < addresses.length(); i++) {
- JSONObject address = (JSONObject) addresses.get(i);
- insertAddress(ops, address);
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get addresses");
- }
-
- // Add organizations
- JSONArray organizations = null;
- try {
- organizations = contact.getJSONArray("organizations");
- if (organizations != null) {
- for (int i = 0; i < organizations.length(); i++) {
- JSONObject org = (JSONObject) organizations.get(i);
- insertOrganization(ops, org);
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get organizations");
- }
-
- // Add IMs
- JSONArray ims = null;
- try {
- ims = contact.getJSONArray("ims");
- if (ims != null) {
- for (int i = 0; i < ims.length(); i++) {
- JSONObject im = (JSONObject) ims.get(i);
- insertIm(ops, im);
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get emails");
- }
-
- // Add note
- String note = getJsonString(contact, "note");
- if (note != null) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Note.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Note.NOTE, note)
- .build());
- }
-
- // Add nickname
- String nickname = getJsonString(contact, "nickname");
- if (nickname != null) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Nickname.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Nickname.NAME, nickname)
- .build());
- }
-
- // Add urls
- JSONArray websites = null;
- try {
- websites = contact.getJSONArray("urls");
- if (websites != null) {
- for (int i = 0; i < websites.length(); i++) {
- JSONObject website = (JSONObject) websites.get(i);
- insertWebsite(ops, website);
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get websites");
- }
-
- // Add birthday
- String birthday = getJsonString(contact, "birthday");
- if (birthday != null) {
- ops.add(ContentProviderOperation.newInsert(ContactsContract.Data.CONTENT_URI)
- .withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
- .withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Event.CONTENT_ITEM_TYPE)
- .withValue(ContactsContract.CommonDataKinds.Event.TYPE, ContactsContract.CommonDataKinds.Event.TYPE_BIRTHDAY)
- .withValue(ContactsContract.CommonDataKinds.Event.START_DATE, birthday)
- .build());
- }
-
- // Add photos
- JSONArray photos = null;
- try {
- photos = contact.getJSONArray("photos");
- if (photos != null) {
- for (int i = 0; i < photos.length(); i++) {
- JSONObject photo = (JSONObject) photos.get(i);
- insertPhoto(ops, photo);
- }
- }
- } catch (JSONException e) {
- Log.d(LOG_TAG, "Could not get photos");
- }
-
- String newId = null;
- //Add contact
- try {
- ContentProviderResult[] cpResults = mApp.getActivity().getContentResolver().applyBatch(ContactsContract.AUTHORITY, ops);
- if (cpResults.length >= 0) {
- newId = cpResults[0].uri.getLastPathSegment();
- }
- } catch (RemoteException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- } catch (OperationApplicationException e) {
- Log.e(LOG_TAG, e.getMessage(), e);
- }
- return newId;
- }
-
- @Override
- /**
- * This method will remove a Contact from the database based on ID.
- * @param id the unique ID of the contact to remove
- */
- public boolean remove(String id) {
- int result = 0;
- Cursor cursor = mApp.getActivity().getContentResolver().query(ContactsContract.Contacts.CONTENT_URI,
- null,
- ContactsContract.Contacts._ID + " = ?",
- new String[] { id }, null);
- if (cursor.getCount() == 1) {
- cursor.moveToFirst();
- String lookupKey = cursor.getString(cursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY));
- Uri uri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey);
- result = mApp.getActivity().getContentResolver().delete(uri, null, null);
- } else {
- Log.d(LOG_TAG, "Could not find contact with ID");
- }
-
- return (result > 0) ? true : false;
- }
-
- /**************************************************************************
- *
- * All methods below this comment are used to convert from JavaScript
- * text types to Android integer types and vice versa.
- *
- *************************************************************************/
-
- /**
- * Converts a string from the W3C Contact API to it's Android int value.
- * @param string
- * @return Android int value
- */
- private int getPhoneType(String string) {
- int type = ContactsContract.CommonDataKinds.Phone.TYPE_OTHER;
- if (string != null) {
- if ("home".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_HOME;
- }
- else if ("mobile".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE;
- }
- else if ("work".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_WORK;
- }
- else if ("work fax".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK;
- }
- else if ("home fax".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME;
- }
- else if ("fax".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK;
- }
- else if ("pager".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_PAGER;
- }
- else if ("other".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_OTHER;
- }
- else if ("car".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_CAR;
- }
- else if ("company main".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_COMPANY_MAIN;
- }
- else if ("isdn".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_ISDN;
- }
- else if ("main".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_MAIN;
- }
- else if ("other fax".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_OTHER_FAX;
- }
- else if ("radio".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_RADIO;
- }
- else if ("telex".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_TELEX;
- }
- else if ("work mobile".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE;
- }
- else if ("work pager".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_WORK_PAGER;
- }
- else if ("assistant".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_ASSISTANT;
- }
- else if ("mms".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_MMS;
- }
- else if ("callback".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_CALLBACK;
- }
- else if ("tty ttd".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_TTY_TDD;
- }
- else if ("custom".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM;
- }
- }
- return type;
- }
-
- /**
- * getPhoneType converts an Android phone type into a string
- * @param type
- * @return phone type as string.
- */
- private String getPhoneType(int type) {
- String stringType;
- switch (type) {
- case ContactsContract.CommonDataKinds.Phone.TYPE_CUSTOM:
- stringType = "custom";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_HOME:
- stringType = "home fax";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_FAX_WORK:
- stringType = "work fax";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_HOME:
- stringType = "home";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_MOBILE:
- stringType = "mobile";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_PAGER:
- stringType = "pager";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_WORK:
- stringType = "work";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_CALLBACK:
- stringType = "callback";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_CAR:
- stringType = "car";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_COMPANY_MAIN:
- stringType = "company main";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_OTHER_FAX:
- stringType = "other fax";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_RADIO:
- stringType = "radio";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_TELEX:
- stringType = "telex";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_TTY_TDD:
- stringType = "tty tdd";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_WORK_MOBILE:
- stringType = "work mobile";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_WORK_PAGER:
- stringType = "work pager";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_ASSISTANT:
- stringType = "assistant";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_MMS:
- stringType = "mms";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_ISDN:
- stringType = "isdn";
- break;
- case ContactsContract.CommonDataKinds.Phone.TYPE_OTHER:
- default:
- stringType = "other";
- break;
- }
- return stringType;
- }
-
- /**
- * Converts a string from the W3C Contact API to it's Android int value.
- * @param string
- * @return Android int value
- */
- private int getContactType(String string) {
- int type = ContactsContract.CommonDataKinds.Email.TYPE_OTHER;
- if (string != null) {
- if ("home".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Email.TYPE_HOME;
- }
- else if ("work".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Email.TYPE_WORK;
- }
- else if ("other".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Email.TYPE_OTHER;
- }
- else if ("mobile".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Email.TYPE_MOBILE;
- }
- else if ("custom".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Email.TYPE_CUSTOM;
- }
- }
- return type;
- }
-
- /**
- * getPhoneType converts an Android phone type into a string
- * @param type
- * @return phone type as string.
- */
- private String getContactType(int type) {
- String stringType;
- switch (type) {
- case ContactsContract.CommonDataKinds.Email.TYPE_CUSTOM:
- stringType = "custom";
- break;
- case ContactsContract.CommonDataKinds.Email.TYPE_HOME:
- stringType = "home";
- break;
- case ContactsContract.CommonDataKinds.Email.TYPE_WORK:
- stringType = "work";
- break;
- case ContactsContract.CommonDataKinds.Email.TYPE_MOBILE:
- stringType = "mobile";
- break;
- case ContactsContract.CommonDataKinds.Email.TYPE_OTHER:
- default:
- stringType = "other";
- break;
- }
- return stringType;
- }
-
- /**
- * Converts a string from the W3C Contact API to it's Android int value.
- * @param string
- * @return Android int value
- */
- private int getOrgType(String string) {
- int type = ContactsContract.CommonDataKinds.Organization.TYPE_OTHER;
- if (string != null) {
- if ("work".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Organization.TYPE_WORK;
- }
- else if ("other".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Organization.TYPE_OTHER;
- }
- else if ("custom".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Organization.TYPE_CUSTOM;
- }
- }
- return type;
- }
-
- /**
- * getPhoneType converts an Android phone type into a string
- * @param type
- * @return phone type as string.
- */
- private String getOrgType(int type) {
- String stringType;
- switch (type) {
- case ContactsContract.CommonDataKinds.Organization.TYPE_CUSTOM:
- stringType = "custom";
- break;
- case ContactsContract.CommonDataKinds.Organization.TYPE_WORK:
- stringType = "work";
- break;
- case ContactsContract.CommonDataKinds.Organization.TYPE_OTHER:
- default:
- stringType = "other";
- break;
- }
- return stringType;
- }
-
- /**
- * Converts a string from the W3C Contact API to it's Android int value.
- * @param string
- * @return Android int value
- */
- private int getAddressType(String string) {
- int type = ContactsContract.CommonDataKinds.StructuredPostal.TYPE_OTHER;
- if (string != null) {
- if ("work".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK;
- }
- else if ("other".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.StructuredPostal.TYPE_OTHER;
- }
- else if ("home".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME;
- }
- }
- return type;
- }
-
- /**
- * getPhoneType converts an Android phone type into a string
- * @param type
- * @return phone type as string.
- */
- private String getAddressType(int type) {
- String stringType;
- switch (type) {
- case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_HOME:
- stringType = "home";
- break;
- case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_WORK:
- stringType = "work";
- break;
- case ContactsContract.CommonDataKinds.StructuredPostal.TYPE_OTHER:
- default:
- stringType = "other";
- break;
- }
- return stringType;
- }
-
- /**
- * Converts a string from the W3C Contact API to it's Android int value.
- * @param string
- * @return Android int value
- */
- private int getImType(String string) {
- int type = ContactsContract.CommonDataKinds.Im.PROTOCOL_CUSTOM;
- if (string != null) {
- if ("aim".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Im.PROTOCOL_AIM;
- }
- else if ("google talk".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Im.PROTOCOL_GOOGLE_TALK;
- }
- else if ("icq".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Im.PROTOCOL_ICQ;
- }
- else if ("jabber".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER;
- }
- else if ("msn".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Im.PROTOCOL_MSN;
- }
- else if ("netmeeting".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Im.PROTOCOL_NETMEETING;
- }
- else if ("qq".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Im.PROTOCOL_QQ;
- }
- else if ("skype".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Im.PROTOCOL_SKYPE;
- }
- else if ("yahoo".equals(string.toLowerCase())) {
- return ContactsContract.CommonDataKinds.Im.PROTOCOL_YAHOO;
- }
- }
- return type;
- }
-
- /**
- * getPhoneType converts an Android phone type into a string
- * @param type
- * @return phone type as string.
- */
- @SuppressWarnings("unused")
- private String getImType(int type) {
- String stringType;
- switch (type) {
- case ContactsContract.CommonDataKinds.Im.PROTOCOL_AIM:
- stringType = "AIM";
- break;
- case ContactsContract.CommonDataKinds.Im.PROTOCOL_GOOGLE_TALK:
- stringType = "Google Talk";
- break;
- case ContactsContract.CommonDataKinds.Im.PROTOCOL_ICQ:
- stringType = "ICQ";
- break;
- case ContactsContract.CommonDataKinds.Im.PROTOCOL_JABBER:
- stringType = "Jabber";
- break;
- case ContactsContract.CommonDataKinds.Im.PROTOCOL_MSN:
- stringType = "MSN";
- break;
- case ContactsContract.CommonDataKinds.Im.PROTOCOL_NETMEETING:
- stringType = "NetMeeting";
- break;
- case ContactsContract.CommonDataKinds.Im.PROTOCOL_QQ:
- stringType = "QQ";
- break;
- case ContactsContract.CommonDataKinds.Im.PROTOCOL_SKYPE:
- stringType = "Skype";
- break;
- case ContactsContract.CommonDataKinds.Im.PROTOCOL_YAHOO:
- stringType = "Yahoo";
- break;
- default:
- stringType = "custom";
- break;
- }
- return stringType;
- }
-}
-
diff --git a/src/android/ContactManager.java b/src/android/ContactManager.java
deleted file mode 100644
index a50d799..0000000
--- a/src/android/ContactManager.java
+++ /dev/null
@@ -1,122 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
-*/
-package org.apache.cordova.contacts;
-
-import org.apache.cordova.CallbackContext;
-import org.apache.cordova.CordovaPlugin;
-import org.apache.cordova.PluginResult;
-import org.json.JSONArray;
-import org.json.JSONException;
-import org.json.JSONObject;
-import android.util.Log;
-
-public class ContactManager extends CordovaPlugin {
-
- private ContactAccessor contactAccessor;
- private static final String LOG_TAG = "Contact Query";
-
- public static final int UNKNOWN_ERROR = 0;
- public static final int INVALID_ARGUMENT_ERROR = 1;
- public static final int TIMEOUT_ERROR = 2;
- public static final int PENDING_OPERATION_ERROR = 3;
- public static final int IO_ERROR = 4;
- public static final int NOT_SUPPORTED_ERROR = 5;
- public static final int PERMISSION_DENIED_ERROR = 20;
-
- /**
- * Constructor.
- */
- public ContactManager() {
- }
-
- /**
- * Executes the request and returns PluginResult.
- *
- * @param action The action to execute.
- * @param args JSONArray of arguments for the plugin.
- * @param callbackContext The callback context used when calling back into JavaScript.
- * @return True if the action was valid, false otherwise.
- */
- public boolean execute(String action, JSONArray args, final CallbackContext callbackContext) throws JSONException {
- /**
- * Check to see if we are on an Android 1.X device. If we are return an error as we
- * do not support this as of Cordova 1.0.
- */
- if (android.os.Build.VERSION.RELEASE.startsWith("1.")) {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, ContactManager.NOT_SUPPORTED_ERROR));
- return true;
- }
-
- /**
- * Only create the contactAccessor after we check the Android version or the program will crash
- * older phones.
- */
- if (this.contactAccessor == null) {
- this.contactAccessor = new ContactAccessorSdk5(this.cordova);
- }
-
- if (action.equals("search")) {
- final JSONArray filter = args.getJSONArray(0);
- final JSONObject options = args.getJSONObject(1);
- this.cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- JSONArray res = contactAccessor.search(filter, options);
- callbackContext.success(res);
- }
- });
- }
- else if (action.equals("save")) {
- final JSONObject contact = args.getJSONObject(0);
- this.cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- JSONObject res = null;
- String id = contactAccessor.save(contact);
- if (id != null) {
- try {
- res = contactAccessor.getContactById(id);
- } catch (JSONException e) {
- Log.e(LOG_TAG, "JSON fail.", e);
- }
- }
- if (res != null) {
- callbackContext.success(res);
- } else {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR));
- }
- }
- });
- }
- else if (action.equals("remove")) {
- final String contactId = args.getString(0);
- this.cordova.getThreadPool().execute(new Runnable() {
- public void run() {
- if (contactAccessor.remove(contactId)) {
- callbackContext.success();
- } else {
- callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.ERROR, UNKNOWN_ERROR));
- }
- }
- });
- }
- else {
- return false;
- }
- return true;
- }
-}
diff --git a/src/blackberry10/ContactActivity.js b/src/blackberry10/ContactActivity.js
deleted file mode 100644
index 0205194..0000000
--- a/src/blackberry10/ContactActivity.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactActivity = function (args) {
- this.direction = args.direction || null;
- this.description = args.description || "";
- this.mimeType = args.mimeType || "";
- this.timestamp = new Date(parseInt(args.timestamp, 10)) || null;
-};
-
-Object.defineProperty(ContactActivity, "INCOMING", {"value": true});
-Object.defineProperty(ContactActivity, "OUTGOING", {"value": false});
-
-module.exports = ContactActivity;
diff --git a/src/blackberry10/ContactAddress.js b/src/blackberry10/ContactAddress.js
deleted file mode 100644
index 30e9cbd..0000000
--- a/src/blackberry10/ContactAddress.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactAddress = function (properties) {
- this.type = properties && properties.type ? properties.type : "";
- this.streetAddress = properties && properties.streetAddress ? properties.streetAddress : "";
- this.streetOther = properties && properties.streetOther ? properties.streetOther : "";
- this.locality = properties && properties.locality ? properties.locality : "";
- this.region = properties && properties.region ? properties.region : "";
- this.postalCode = properties && properties.postalCode ? properties.postalCode : "";
- this.country = properties && properties.country ? properties.country : "";
-};
-
-Object.defineProperty(ContactAddress, "HOME", {"value": "home"});
-Object.defineProperty(ContactAddress, "WORK", {"value": "work"});
-Object.defineProperty(ContactAddress, "OTHER", {"value": "other"});
-
-module.exports = ContactAddress;
diff --git a/src/blackberry10/ContactError.js b/src/blackberry10/ContactError.js
deleted file mode 100644
index a44a546..0000000
--- a/src/blackberry10/ContactError.js
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactError = function (code, msg) {
- this.code = code;
- this.message = msg;
-};
-
-Object.defineProperty(ContactError, "UNKNOWN_ERROR", { "value": 0 });
-Object.defineProperty(ContactError, "INVALID_ARGUMENT_ERROR", { "value": 1 });
-Object.defineProperty(ContactError, "TIMEOUT_ERROR", { "value": 2 });
-Object.defineProperty(ContactError, "PENDING_OPERATION_ERROR", { "value": 3 });
-Object.defineProperty(ContactError, "IO_ERROR", { "value": 4 });
-Object.defineProperty(ContactError, "NOT_SUPPORTED_ERROR", { "value": 5 });
-Object.defineProperty(ContactError, "PERMISSION_DENIED_ERROR", { "value": 20 });
-
-module.exports = ContactError;
-
diff --git a/src/blackberry10/ContactField.js b/src/blackberry10/ContactField.js
deleted file mode 100644
index 9651700..0000000
--- a/src/blackberry10/ContactField.js
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactField = function (type, value) {
- this.type = type || "";
- this.value = value || "";
-};
-
-Object.defineProperty(ContactField, "HOME", {"value": "home"});
-Object.defineProperty(ContactField, "WORK", {"value": "work"});
-Object.defineProperty(ContactField, "OTHER", {"value": "other"});
-Object.defineProperty(ContactField, "MOBILE", {"value": "mobile"});
-Object.defineProperty(ContactField, "DIRECT", {"value": "direct"});
-
-module.exports = ContactField;
diff --git a/src/blackberry10/ContactFindOptions.js b/src/blackberry10/ContactFindOptions.js
deleted file mode 100644
index 6f8ccfe..0000000
--- a/src/blackberry10/ContactFindOptions.js
+++ /dev/null
@@ -1,55 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
- * ContactFindOptions.
- * @constructor
- * @param filter search fields
- * @param sort sort fields and order
- * @param limit max number of contacts to return
- * @param favorite if set, only favorite contacts will be returned
- */
-
-var ContactFindOptions = function (filter, sort, limit, favorite) {
- this.filter = filter || null;
- this.sort = sort || null;
- this.limit = limit || -1; // -1 for returning all results
- this.favorite = favorite || false;
- this.includeAccounts = [];
- this.excludeAccounts = [];
-};
-
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_GIVEN_NAME", { "value": 0 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_FAMILY_NAME", { "value": 1 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_ORGANIZATION_NAME", { "value": 2 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_PHONE", { "value": 3 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_EMAIL", { "value": 4 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_BBMPIN", { "value": 5 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_LINKEDIN", { "value": 6 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_TWITTER", { "value": 7 });
-Object.defineProperty(ContactFindOptions, "SEARCH_FIELD_VIDEO_CHAT", { "value": 8 });
-
-Object.defineProperty(ContactFindOptions, "SORT_FIELD_GIVEN_NAME", { "value": 0 });
-Object.defineProperty(ContactFindOptions, "SORT_FIELD_FAMILY_NAME", { "value": 1 });
-Object.defineProperty(ContactFindOptions, "SORT_FIELD_ORGANIZATION_NAME", { "value": 2 });
-
-module.exports = ContactFindOptions;
-
diff --git a/src/blackberry10/ContactName.js b/src/blackberry10/ContactName.js
deleted file mode 100644
index 80136c9..0000000
--- a/src/blackberry10/ContactName.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-function toFormattedName(properties) {
- var formatted = "";
- if (properties && properties.givenName) {
- formatted = properties.givenName;
- if (properties && properties.familyName) {
- formatted += " " + properties.familyName;
- }
- }
- return formatted;
-}
-
-var ContactName = function (properties) {
- this.familyName = properties && properties.familyName ? properties.familyName : "";
- this.givenName = properties && properties.givenName ? properties.givenName : "";
- this.formatted = toFormattedName(properties);
- this.middleName = properties && properties.middleName ? properties.middleName : "";
- this.honorificPrefix = properties && properties.honorificPrefix ? properties.honorificPrefix : "";
- this.honorificSuffix = properties && properties.honorificSuffix ? properties.honorificSuffix : "";
- this.phoneticFamilyName = properties && properties.phoneticFamilyName ? properties.phoneticFamilyName : "";
- this.phoneticGivenName = properties && properties.phoneticGivenName ? properties.phoneticGivenName : "";
-};
-
-module.exports = ContactName;
diff --git a/src/blackberry10/ContactNews.js b/src/blackberry10/ContactNews.js
deleted file mode 100644
index e47a4cd..0000000
--- a/src/blackberry10/ContactNews.js
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactNews = function (args) {
- this.title = args.title || "";
- this.body = args.body || "";
- this.articleSource = args.articleSource || "";
- this.companies = args.companies || [];
- this.publishedAt = new Date(parseInt(args.publishedAt, 10)) || null;
- this.uri = args.uri || "";
- this.type = args.type || "";
-};
-
-module.exports = ContactNews;
diff --git a/src/blackberry10/ContactOrganization.js b/src/blackberry10/ContactOrganization.js
deleted file mode 100644
index fc953f2..0000000
--- a/src/blackberry10/ContactOrganization.js
+++ /dev/null
@@ -1,27 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactOrganization = function (properties) {
- this.name = properties && properties.name ? properties.name : "";
- this.department = properties && properties.department ? properties.department : "";
- this.title = properties && properties.title ? properties.title : "";
-};
-
-module.exports = ContactOrganization;
diff --git a/src/blackberry10/ContactPhoto.js b/src/blackberry10/ContactPhoto.js
deleted file mode 100644
index 4604710..0000000
--- a/src/blackberry10/ContactPhoto.js
+++ /dev/null
@@ -1,28 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-var ContactPhoto = function (originalFilePath, pref) {
- this.originalFilePath = originalFilePath || "";
- this.pref = pref || false;
- this.largeFilePath = "";
- this.smallFilePath = "";
-};
-
-module.exports = ContactPhoto;
diff --git a/src/blackberry10/contactConsts.js b/src/blackberry10/contactConsts.js
deleted file mode 100644
index ef25206..0000000
--- a/src/blackberry10/contactConsts.js
+++ /dev/null
@@ -1,225 +0,0 @@
-/*
-* Copyright 2012 Research In Motion Limited.
-*
-* Licensed under the Apache License, Version 2.0 (the "License");
-* you may not use this file except in compliance with the License.
-* You may obtain a copy of the License at
-*
-* http://www.apache.org/licenses/LICENSE-2.0
-*
-* Unless required by applicable law or agreed to in writing, software
-* distributed under the License is distributed on an "AS IS" BASIS,
-* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-* See the License for the specific language governing permissions and
-* limitations under the License.
-*/
-
-var ATTRIBUTE_KIND,
- ATTRIBUTE_SUBKIND,
- kindAttributeMap = {},
- subKindAttributeMap = {},
- _TITLE = 26,
- _START_DATE = 43,
- _END_DATE = 44;
-
-function populateKindAttributeMap() {
- ATTRIBUTE_KIND = {
- Invalid: 0,
- Phone: 1,
- Fax: 2,
- Pager: 3,
- Email: 4,
- Website: 5,
- Feed: 6,
- Profile: 7,
- Family: 8,
- Person: 9,
- Date: 10,
- Group: 11,
- Name: 12,
- StockSymbol: 13,
- Ranking: 14,
- OrganizationAffiliation: 15,
- Education: 16,
- Note: 17,
- InstantMessaging: 18,
- VideoChat: 19,
- ConnectionCount: 20,
- Hidden: 21,
- Biography: 22,
- Sound: 23,
- Notification: 24,
- MessageSound: 25,
- MessageNotification: 26
- };
-
- kindAttributeMap[ATTRIBUTE_KIND.Phone] = "phoneNumbers";
- kindAttributeMap[ATTRIBUTE_KIND.Fax] = "faxNumbers";
- kindAttributeMap[ATTRIBUTE_KIND.Pager] = "pagerNumber";
- kindAttributeMap[ATTRIBUTE_KIND.Email] = "emails";
- kindAttributeMap[ATTRIBUTE_KIND.Website] = "urls";
- kindAttributeMap[ATTRIBUTE_KIND.Profile] = "socialNetworks";
- kindAttributeMap[ATTRIBUTE_KIND.OrganizationAffiliation] = "organizations";
- kindAttributeMap[ATTRIBUTE_KIND.Education] = "education";
- kindAttributeMap[ATTRIBUTE_KIND.Note] = "note";
- kindAttributeMap[ATTRIBUTE_KIND.InstantMessaging] = "ims";
- kindAttributeMap[ATTRIBUTE_KIND.VideoChat] = "videoChat";
- kindAttributeMap[ATTRIBUTE_KIND.Sound] = "ringtone";
-}
-
-function populateSubKindAttributeMap() {
- ATTRIBUTE_SUBKIND = {
- Invalid: 0,
- Other: 1,
- Home: 2,
- Work: 3,
- PhoneMobile: 4,
- FaxDirect: 5,
- Blog: 6,
- WebsiteResume: 7,
- WebsitePortfolio: 8,
- WebsitePersonal: 9,
- WebsiteCompany: 10,
- ProfileFacebook: 11,
- ProfileTwitter: 12,
- ProfileLinkedIn: 13,
- ProfileGist: 14,
- ProfileTungle: 15,
- FamilySpouse: 16,
- FamilyChild: 17,
- FamilyParent: 18,
- PersonManager: 19,
- PersonAssistant: 20,
- DateBirthday: 21,
- DateAnniversary: 22,
- GroupDepartment: 23,
- NameGiven: 24,
- NameSurname: 25,
- Title: _TITLE,
- NameSuffix: 27,
- NameMiddle: 28,
- NameNickname: 29,
- NameAlias: 30,
- NameDisplayName: 31,
- NamePhoneticGiven: 32,
- NamePhoneticSurname: 33,
- StockSymbolNyse: 34,
- StockSymbolNasdaq: 35,
- StockSymbolTse: 36,
- StockSymbolLse: 37,
- StockSymbolTsx: 38,
- RankingKlout: 39,
- RankingTrstRank: 40,
- OrganizationAffiliationName: 41,
- OrganizationAffiliationPhoneticName: 42,
- OrganizationAffiliationTitle: _TITLE,
- StartDate: _START_DATE,
- EndDate: _END_DATE,
- OrganizationAffiliationDetails: 45,
- EducationInstitutionName: 46,
- EducationStartDate: _START_DATE,
- EducationEndDate: _END_DATE,
- EducationDegree: 47,
- EducationConcentration: 48,
- EducationActivities: 49,
- EducationNotes: 50,
- InstantMessagingBbmPin: 51,
- InstantMessagingAim: 52,
- InstantMessagingAliwangwang: 53,
- InstantMessagingGoogleTalk: 54,
- InstantMessagingSametime: 55,
- InstantMessagingIcq: 56,
- InstantMessagingIrc: 57,
- InstantMessagingJabber: 58,
- InstantMessagingMsLcs: 59,
- InstantMessagingMsn: 60,
- InstantMessagingQq: 61,
- InstantMessagingSkype: 62,
- InstantMessagingYahooMessenger: 63,
- InstantMessagingYahooMessengerJapan: 64,
- VideoChatBbPlaybook: 65,
- HiddenLinkedIn: 66,
- HiddenFacebook: 67,
- HiddenTwitter: 68,
- ConnectionCountLinkedIn: 69,
- ConnectionCountFacebook: 70,
- ConnectionCountTwitter: 71,
- HiddenChecksum: 72,
- HiddenSpeedDial: 73,
- BiographyFacebook: 74,
- BiographyTwitter: 75,
- BiographyLinkedIn: 76,
- SoundRingtone: 77,
- SimContactType: 78,
- EcoID: 79,
- Personal: 80,
- StockSymbolAll: 81,
- NotificationVibration: 82,
- NotificationLED: 83,
- MessageNotificationVibration: 84,
- MessageNotificationLED: 85,
- MessageNotificationDuringCall: 86,
- VideoChatPin: 87
- };
-
- subKindAttributeMap[ATTRIBUTE_SUBKIND.Other] = "other";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.Home] = "home";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.Work] = "work";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.PhoneMobile] = "mobile";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.FaxDirect] = "direct";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.Blog] = "blog";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.WebsiteResume] = "resume";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.WebsitePortfolio] = "portfolio";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.WebsitePersonal] = "personal";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.WebsiteCompany] = "company";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileFacebook] = "facebook";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileTwitter] = "twitter";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileLinkedIn] = "linkedin";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileGist] = "gist";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.ProfileTungle] = "tungle";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.DateBirthday] = "birthday";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.DateAnniversary] = "anniversary";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.NameGiven] = "givenName";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.NameSurname] = "familyName";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.Title] = "honorificPrefix";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.NameSuffix] = "honorificSuffix";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.NameMiddle] = "middleName";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.NamePhoneticGiven] = "phoneticGivenName";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.NamePhoneticSurname] = "phoneticFamilyName";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.NameNickname] = "nickname";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.NameDisplayName] = "displayName";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.OrganizationAffiliationName] = "name";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.OrganizationAffiliationDetails] = "department";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.Title] = "title";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingBbmPin] = "BbmPin";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingAim] = "Aim";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingAliwangwang] = "Aliwangwang";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingGoogleTalk] = "GoogleTalk";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingSametime] = "Sametime";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingIcq] = "Icq";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingJabber] = "Jabber";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingMsLcs] = "MsLcs";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingSkype] = "Skype";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingYahooMessenger] = "YahooMessenger";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.InstantMessagingYahooMessengerJapan] = "YahooMessegerJapan";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.VideoChatBbPlaybook] = "BbPlaybook";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.SoundRingtone] = "ringtone";
- subKindAttributeMap[ATTRIBUTE_SUBKIND.Personal] = "personal";
-}
-
-module.exports = {
- getKindAttributeMap: function () {
- if (!ATTRIBUTE_KIND) {
- populateKindAttributeMap();
- }
-
- return kindAttributeMap;
- },
- getSubKindAttributeMap: function () {
- if (!ATTRIBUTE_SUBKIND) {
- populateSubKindAttributeMap();
- }
-
- return subKindAttributeMap;
- }
-};
diff --git a/src/blackberry10/contactUtils.js b/src/blackberry10/contactUtils.js
deleted file mode 100644
index e1f7d67..0000000
--- a/src/blackberry10/contactUtils.js
+++ /dev/null
@@ -1,228 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var self,
- ContactFindOptions = require("./ContactFindOptions"),
- ContactError = require("./ContactError"),
- ContactName = require("./ContactName"),
- ContactOrganization = require("./ContactOrganization"),
- ContactAddress = require("./ContactAddress"),
- ContactField = require("./ContactField"),
- contactConsts = require("./contactConsts"),
- ContactPhoto = require("./ContactPhoto"),
- ContactNews = require("./ContactNews"),
- ContactActivity = require("./ContactActivity");
-
-function populateFieldArray(contactProps, field, ClassName) {
- if (contactProps[field]) {
- var list = [],
- obj;
-
- contactProps[field].forEach(function (args) {
- if (ClassName === ContactField) {
- list.push(new ClassName(args.type, args.value));
- } else if (ClassName === ContactPhoto) {
- obj = new ContactPhoto(args.originalFilePath, args.pref);
- obj.largeFilePath = args.largeFilePath;
- obj.smallFilePath = args.smallFilePath;
- list.push(obj);
- } else if (ClassName === ContactNews) {
- obj = new ContactNews(args);
- list.push(obj);
- } else if (ClassName === ContactActivity) {
- obj = new ContactActivity(args);
- list.push(obj);
- } else {
- list.push(new ClassName(args));
- }
- });
- contactProps[field] = list;
- }
-}
-
-function populateDate(contactProps, field) {
- if (contactProps[field]) {
- contactProps[field] = new Date(contactProps[field]);
- }
-}
-
-function validateFindArguments(findOptions) {
- var error = false;
-
- // findOptions is mandatory
- if (!findOptions) {
- error = true;
- } else {
- // findOptions.filter is optional
- if (findOptions.filter) {
- findOptions.filter.forEach(function (f) {
- switch (f.fieldName) {
- case ContactFindOptions.SEARCH_FIELD_GIVEN_NAME:
- case ContactFindOptions.SEARCH_FIELD_FAMILY_NAME:
- case ContactFindOptions.SEARCH_FIELD_ORGANIZATION_NAME:
- case ContactFindOptions.SEARCH_FIELD_PHONE:
- case ContactFindOptions.SEARCH_FIELD_EMAIL:
- case ContactFindOptions.SEARCH_FIELD_BBMPIN:
- case ContactFindOptions.SEARCH_FIELD_LINKEDIN:
- case ContactFindOptions.SEARCH_FIELD_TWITTER:
- case ContactFindOptions.SEARCH_FIELD_VIDEO_CHAT:
- break;
- default:
- error = true;
- }
-
- if (!f.fieldValue) {
- error = true;
- }
- });
- }
-
- //findOptions.limit is optional
- if (findOptions.limit) {
- if (typeof findOptions.limit !== "number") {
- error = true;
- }
- }
-
- //findOptions.favorite is optional
- if (findOptions.favorite) {
- if (typeof findOptions.favorite !== "boolean") {
- error = true;
- }
- }
-
- // findOptions.sort is optional
- if (!error && findOptions.sort && Array.isArray(findOptions.sort)) {
- findOptions.sort.forEach(function (s) {
- switch (s.fieldName) {
- case ContactFindOptions.SORT_FIELD_GIVEN_NAME:
- case ContactFindOptions.SORT_FIELD_FAMILY_NAME:
- case ContactFindOptions.SORT_FIELD_ORGANIZATION_NAME:
- break;
- default:
- error = true;
- }
-
- if (s.desc === undefined || typeof s.desc !== "boolean") {
- error = true;
- }
- });
- }
-
- if (!error && findOptions.includeAccounts) {
- if (!Array.isArray(findOptions.includeAccounts)) {
- error = true;
- } else {
- findOptions.includeAccounts.forEach(function (acct) {
- if (!error && (!acct.id || window.isNaN(window.parseInt(acct.id, 10)))) {
- error = true;
- }
- });
- }
- }
-
- if (!error && findOptions.excludeAccounts) {
- if (!Array.isArray(findOptions.excludeAccounts)) {
- error = true;
- } else {
- findOptions.excludeAccounts.forEach(function (acct) {
- if (!error && (!acct.id || window.isNaN(window.parseInt(acct.id, 10)))) {
- error = true;
- }
- });
- }
- }
- }
- return !error;
-}
-
-function validateContactsPickerFilter(filter) {
- var isValid = true,
- availableFields = {};
-
- if (typeof(filter) === "undefined") {
- isValid = false;
- } else {
- if (filter && Array.isArray(filter)) {
- availableFields = contactConsts.getKindAttributeMap();
- filter.forEach(function (e) {
- isValid = isValid && Object.getOwnPropertyNames(availableFields).reduce(
- function (found, key) {
- return found || availableFields[key] === e;
- }, false);
- });
- }
- }
-
- return isValid;
-}
-
-function validateContactsPickerOptions(options) {
- var isValid = false,
- mode = options.mode;
-
- if (typeof(options) === "undefined") {
- isValid = false;
- } else {
- isValid = mode === ContactPickerOptions.MODE_SINGLE || mode === ContactPickerOptions.MODE_MULTIPLE || mode === ContactPickerOptions.MODE_ATTRIBUTE;
-
- // if mode is attribute, fields must be defined
- if (mode === ContactPickerOptions.MODE_ATTRIBUTE && !validateContactsPickerFilter(options.fields)) {
- isValid = false;
- }
- }
-
- return isValid;
-}
-
-self = module.exports = {
- populateContact: function (contact) {
- if (contact.name) {
- contact.name = new ContactName(contact.name);
- }
-
- populateFieldArray(contact, "addresses", ContactAddress);
- populateFieldArray(contact, "organizations", ContactOrganization);
- populateFieldArray(contact, "emails", ContactField);
- populateFieldArray(contact, "phoneNumbers", ContactField);
- populateFieldArray(contact, "faxNumbers", ContactField);
- populateFieldArray(contact, "pagerNumbers", ContactField);
- populateFieldArray(contact, "ims", ContactField);
- populateFieldArray(contact, "socialNetworks", ContactField);
- populateFieldArray(contact, "urls", ContactField);
- populateFieldArray(contact, "photos", ContactPhoto);
- populateFieldArray(contact, "news", ContactNews);
- populateFieldArray(contact, "activities", ContactActivity);
- // TODO categories
-
- populateDate(contact, "birthday");
- populateDate(contact, "anniversary");
- },
- invokeErrorCallback: function (errorCallback, code) {
- if (errorCallback) {
- errorCallback(new ContactError(code));
- }
- },
- validateFindArguments: validateFindArguments,
- validateContactsPickerFilter: validateContactsPickerFilter,
- validateContactsPickerOptions: validateContactsPickerOptions
-};
-
diff --git a/src/blackberry10/index.js b/src/blackberry10/index.js
deleted file mode 100644
index 09a4bd2..0000000
--- a/src/blackberry10/index.js
+++ /dev/null
@@ -1,374 +0,0 @@
-/*
- * Copyright 2013 Research In Motion Limited.
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-var pimContacts,
- contactUtils = require("./contactUtils"),
- contactConsts = require("./contactConsts"),
- ContactError = require("./ContactError"),
- ContactName = require("./ContactName"),
- ContactFindOptions = require("./ContactFindOptions"),
- noop = function () {};
-
-function getAccountFilters(options) {
- if (options.includeAccounts) {
- options.includeAccounts = options.includeAccounts.map(function (acct) {
- return acct.id.toString();
- });
- }
-
- if (options.excludeAccounts) {
- options.excludeAccounts = options.excludeAccounts.map(function (acct) {
- return acct.id.toString();
- });
- }
-}
-
-function populateSearchFields(fields) {
- var i,
- l,
- key,
- searchFieldsObject = {},
- searchFields = [];
-
- for (i = 0, l = fields.length; i < l; i++) {
- if (fields[i] === "*") {
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_GIVEN_NAME] = true;
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_FAMILY_NAME] = true;
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_PHONE] = true;
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_EMAIL] = true;
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_ORGANIZATION_NAME] = true;
- } else if (fields[i] === "displayName" || fields[i] === "name") {
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_GIVEN_NAME] = true;
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_FAMILY_NAME] = true;
- } else if (fields[i] === "nickname") {
- // not supported by Cascades
- } else if (fields[i] === "phoneNumbers") {
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_PHONE] = true;
- } else if (fields[i] === "emails") {
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_EMAIL] = true;
- } else if (field === "addresses") {
- // not supported by Cascades
- } else if (field === "ims") {
- // not supported by Cascades
- } else if (field === "organizations") {
- searchFieldsObject[ContactFindOptions.SEARCH_FIELD_ORGANIZATION_NAME] = true;
- } else if (field === "birthday") {
- // not supported by Cascades
- } else if (field === "note") {
- // not supported by Cascades
- } else if (field === "photos") {
- // not supported by Cascades
- } else if (field === "categories") {
- // not supported by Cascades
- } else if (field === "urls") {
- // not supported by Cascades
- }
- }
-
- for (key in searchFieldsObject) {
- if (searchFieldsObject.hasOwnProperty(key)) {
- searchFields.push(window.parseInt(key));
- }
- }
-
- return searchFields;
-}
-
-function convertBirthday(birthday) {
- //Convert date string from native to milliseconds since epoch for cordova-js
- var birthdayInfo;
- if (birthday) {
- birthdayInfo = birthday.split("-");
- return new Date(birthdayInfo[0], birthdayInfo[1] - 1, birthdayInfo[2]).getTime();
- } else {
- return null;
- }
-}
-
-function processJnextSaveData(result, JnextData) {
- var data = JnextData,
- birthdayInfo;
-
- if (data._success === true) {
- data.birthday = convertBirthday(data.birthday);
- result.callbackOk(data, false);
- } else {
- result.callbackError(data.code, false);
- }
-}
-
-function processJnextRemoveData(result, JnextData) {
- var data = JnextData;
-
- if (data._success === true) {
- result.callbackOk(data);
- } else {
- result.callbackError(ContactError.UNKNOWN_ERROR, false);
- }
-}
-
-function processJnextFindData(eventId, eventHandler, JnextData) {
- var data = JnextData,
- i,
- l,
- more = false,
- resultsObject = {},
- birthdayInfo;
-
- if (data.contacts) {
- for (i = 0, l = data.contacts.length; i < l; i++) {
- data.contacts[i].birthday = convertBirthday(data.contacts[i].birthday);
- data.contacts[i].name = new ContactName(data.contacts[i].name);
- }
- } else {
- data.contacts = []; // if JnextData.contacts return null, return an empty array
- }
-
- if (data._success === true) {
- eventHandler.error = false;
- }
-
- if (eventHandler.multiple) {
- // Concatenate results; do not add the same contacts
- for (i = 0, l = eventHandler.searchResult.length; i < l; i++) {
- resultsObject[eventHandler.searchResult[i].id] = true;
- }
-
- for (i = 0, l = data.contacts.length; i < l; i++) {
- if (resultsObject[data.contacts[i].id]) {
- // Already existing
- } else {
- eventHandler.searchResult.push(data.contacts[i]);
- }
- }
-
- // check if more search is required
- eventHandler.searchFieldIndex++;
- if (eventHandler.searchFieldIndex < eventHandler.searchFields.length) {
- more = true;
- }
- } else {
- eventHandler.searchResult = data.contacts;
- }
-
- if (more) {
- pimContacts.getInstance().invokeJnextSearch(eventId);
- } else {
- if (eventHandler.error) {
- eventHandler.result.callbackError(data.code, false);
- } else {
- eventHandler.result.callbackOk(eventHandler.searchResult, false);
- }
- }
-}
-
-module.exports = {
- search: function (successCb, failCb, args, env) {
- var cordovaFindOptions = {},
- result = new PluginResult(args, env),
- key;
-
- for (key in args) {
- if (args.hasOwnProperty(key)) {
- cordovaFindOptions[key] = JSON.parse(decodeURIComponent(args[key]));
- }
- }
-
- pimContacts.getInstance().find(cordovaFindOptions, result, processJnextFindData);
- result.noResult(true);
- },
- save: function (successCb, failCb, args, env) {
- var attributes = {},
- result = new PluginResult(args, env),
- key,
- nativeEmails = [];
-
- attributes = JSON.parse(decodeURIComponent(args[0]));
-
- //convert birthday format for our native .so file
- if (attributes.birthday) {
- attributes.birthday = new Date(attributes.birthday).toDateString();
- }
-
- if (attributes.emails) {
- attributes.emails.forEach(function (email) {
- if (email.value) {
- if (email.type) {
- nativeEmails.push({ "type" : email.type, "value" : email.value });
- } else {
- nativeEmails.push({ "type" : "home", "value" : email.value });
- }
- }
- });
- attributes.emails = nativeEmails;
- }
-
- if (attributes.id !== null) {
- attributes.id = window.parseInt(attributes.id);
- }
-
- attributes._eventId = result.callbackId;
- pimContacts.getInstance().save(attributes, result, processJnextSaveData);
- result.noResult(true);
- },
- remove: function (successCb, failCb, args, env) {
- var result = new PluginResult(args, env),
- attributes = {
- "contactId": window.parseInt(JSON.parse(decodeURIComponent(args[0]))),
- "_eventId": result.callbackId
- };
-
- if (!window.isNaN(attributes.contactId)) {
- pimContacts.getInstance().remove(attributes, result, processJnextRemoveData);
- result.noResult(true);
- } else {
- result.error(ContactError.UNKNOWN_ERROR);
- result.noResult(false);
- }
- }
-};
-
-///////////////////////////////////////////////////////////////////
-// JavaScript wrapper for JNEXT plugin
-///////////////////////////////////////////////////////////////////
-
-JNEXT.PimContacts = function ()
-{
- var self = this,
- hasInstance = false;
-
- self.find = function (cordovaFindOptions, pluginResult, handler) {
- //register find eventHandler for when JNEXT onEvent fires
- self.eventHandlers[cordovaFindOptions.callbackId] = {
- "result" : pluginResult,
- "action" : "find",
- "multiple" : cordovaFindOptions[1].filter ? true : false,
- "fields" : cordovaFindOptions[0],
- "searchFilter" : cordovaFindOptions[1].filter,
- "searchFields" : cordovaFindOptions[1].filter ? populateSearchFields(cordovaFindOptions[0]) : null,
- "searchFieldIndex" : 0,
- "searchResult" : [],
- "handler" : handler,
- "error" : true
- };
-
- self.invokeJnextSearch(cordovaFindOptions.callbackId);
- return "";
- };
-
- self.invokeJnextSearch = function(eventId) {
- var jnextArgs = {},
- findHandler = self.eventHandlers[eventId];
-
- jnextArgs._eventId = eventId;
- jnextArgs.fields = findHandler.fields;
- jnextArgs.options = {};
- jnextArgs.options.filter = [];
-
- if (findHandler.multiple) {
- jnextArgs.options.filter.push({
- "fieldName" : findHandler.searchFields[findHandler.searchFieldIndex],
- "fieldValue" : findHandler.searchFilter
- });
- //findHandler.searchFieldIndex++;
- }
-
- JNEXT.invoke(self.m_id, "find " + JSON.stringify(jnextArgs));
- }
-
- self.getContact = function (args) {
- return JSON.parse(JNEXT.invoke(self.m_id, "getContact " + JSON.stringify(args)));
- };
-
- self.save = function (args, pluginResult, handler) {
- //register save eventHandler for when JNEXT onEvent fires
- self.eventHandlers[args._eventId] = {
- "result" : pluginResult,
- "action" : "save",
- "handler" : handler
- };
- JNEXT.invoke(self.m_id, "save " + JSON.stringify(args));
- return "";
- };
-
- self.remove = function (args, pluginResult, handler) {
- //register remove eventHandler for when JNEXT onEvent fires
- self.eventHandlers[args._eventId] = {
- "result" : pluginResult,
- "action" : "remove",
- "handler" : handler
- };
- JNEXT.invoke(self.m_id, "remove " + JSON.stringify(args));
- return "";
- };
-
- self.getId = function () {
- return self.m_id;
- };
-
- self.getContactAccounts = function () {
- var value = JNEXT.invoke(self.m_id, "getContactAccounts");
- return JSON.parse(value);
- };
-
- self.init = function () {
- if (!JNEXT.require("libpimcontacts")) {
- return false;
- }
-
- self.m_id = JNEXT.createObject("libpimcontacts.PimContacts");
-
- if (self.m_id === "") {
- return false;
- }
-
- JNEXT.registerEvents(self);
- };
-
- // Handle data coming back from JNEXT native layer. Each async function registers a handler and a PluginResult object.
- // When JNEXT fires onEvent we parse the result string back into JSON and trigger the appropriate handler (eventHandlers map
- // uses callbackId as key), along with the actual data coming back from the native layer. Each function may have its own way of
- // processing native data so we do not do any processing here.
-
- self.onEvent = function (strData) {
- var arData = strData.split(" "),
- strEventDesc = arData[0],
- eventHandler,
- args = {};
-
- if (strEventDesc === "result") {
- args.result = escape(strData.split(" ").slice(2).join(" "));
- eventHandler = self.eventHandlers[arData[1]];
- if (eventHandler.action === "save" || eventHandler.action === "remove") {
- eventHandler.handler(eventHandler.result, JSON.parse(decodeURIComponent(args.result)));
- } else if (eventHandler.action === "find") {
- eventHandler.handler(arData[1], eventHandler, JSON.parse(decodeURIComponent(args.result)));
- }
- }
- };
-
- self.m_id = "";
- self.eventHandlers = {};
-
- self.getInstance = function () {
- if (!hasInstance) {
- self.init();
- hasInstance = true;
- }
- return self;
- };
-};
-
-pimContacts = new JNEXT.PimContacts();
diff --git a/src/firefoxos/ContactsProxy.js b/src/firefoxos/ContactsProxy.js
deleted file mode 100644
index a5b6667..0000000
--- a/src/firefoxos/ContactsProxy.js
+++ /dev/null
@@ -1,464 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-// Cordova contact definition:
-// http://cordova.apache.org/docs/en/2.5.0/cordova_contacts_contacts.md.html#Contact
-// FxOS contact definition:
-// https://developer.mozilla.org/en-US/docs/Web/API/mozContact
-
-
-var Contact = require('./Contact');
-var ContactField = require('./ContactField');
-var ContactAddress = require('./ContactAddress');
-var ContactName = require('./ContactName');
-
-// XXX: a hack to check if id is "empty". Cordova inserts a
-// string "this string is supposed to be a unique identifier that will
-// never show up on a device" if id is empty
-function _hasId(id) {
- if (!id || id.indexOf(' ') >= 0) {
- return false;
- }
- return true;
-}
-
-// Extend mozContact prototype to provide update from Cordova
-function updateFromCordova(contact, fromContact) {
-
- function exportContactFieldArray(contactFieldArray, key) {
- if (!key) {
- key = 'value';
- }
- var arr = [];
- for (var i=0; i < contactFieldArray.length; i++) {
- arr.push(contactFieldArray[i][key]);
- };
- return arr;
- }
-
- function exportAddress(addresses) {
- // TODO: check moz address format
- var arr = [];
-
- for (var i=0; i < addresses.length; i++) {
- var addr = {};
- for (var key in addresses[i]) {
- if (key == 'formatted' || key == 'id') {
- continue;
- } else if (key == 'type') {
- addr[key] = [addresses[i][key]];
- } else if (key == 'country') {
- addr['countryName'] = addresses[i][key];
- } else {
- addr[key] = addresses[i][key];
- }
- }
- arr.push(addr);
- }
- return arr;
- }
-
- function exportContactField(data) {
- var contactFields = [];
- for (var i=0; i < data.length; i++) {
- var item = data[i];
- if (item.value) {
- var itemData = {value: item.value};
- if (item.type) {
- itemData.type = [item.type];
- }
- if (item.pref) {
- itemData.pref = item.pref;
- }
- contactFields.push(itemData);
- }
- }
- return contactFields;
- }
- // adding simple fields [contactField, eventualMozContactField]
- var nameFields = [['givenName'], ['familyName'],
- ['honorificPrefix'], ['honorificSuffix'],
- ['middleName', 'additionalName']];
- var baseArrayFields = [['displayName', 'name'], ['nickname']];
- var baseStringFields = [];
- var j = 0; while(field = nameFields[j++]) {
- if (fromContact.name[field[0]]) {
- contact[field[1] || field[0]] = fromContact.name[field[0]].split(' ');
- }
- }
- j = 0; while(field = baseArrayFields[j++]) {
- if (fromContact[field[0]]) {
- contact[field[1] || field[0]] = fromContact[field[0]].split(' ');
- }
- }
- j = 0; while(field = baseStringFields[j++]) {
- if (fromContact[field[0]]) {
- contact[field[1] || field[0]] = fromContact[field[0]];
- }
- }
- if (fromContact.birthday) {
- contact.bday = new Date(fromContact.birthday);
- }
- if (fromContact.emails) {
- var emails = exportContactField(fromContact.emails)
- contact.email = emails;
- }
- if (fromContact.categories) {
- contact.category = exportContactFieldArray(fromContact.categories);
- }
- if (fromContact.addresses) {
- contact.adr = exportAddress(fromContact.addresses);
- }
- if (fromContact.phoneNumbers) {
- contact.tel = exportContactField(fromContact.phoneNumbers);
- }
- if (fromContact.organizations) {
- // XXX: organizations are saved in 2 arrays - org and jobTitle
- // depending on the usecase it might generate issues
- // where wrong title will be added to an organization
- contact.org = exportContactFieldArray(fromContact.organizations, 'name');
- contact.jobTitle = exportContactFieldArray(fromContact.organizations, 'title');
- }
- if (fromContact.note) {
- contact.note = [fromContact.note];
- }
-}
-
-
-// Extend Cordova Contact prototype to provide update from FFOS contact
-Contact.prototype.updateFromMozilla = function(moz) {
- function exportContactField(data) {
- var contactFields = [];
- for (var i=0; i < data.length; i++) {
- var item = data[i];
- var itemData = new ContactField(item.type, item.value, item.pref);
- contactFields.push(itemData);
- }
- return contactFields;
- }
-
- function makeContactFieldFromArray(data) {
- var contactFields = [];
- for (var i=0; i < data.length; i++) {
- var itemData = new ContactField(null, data[i]);
- contactFields.push(itemData);
- }
- return contactFields;
- }
-
- function exportAddresses(addresses) {
- // TODO: check moz address format
- var arr = [];
-
- for (var i=0; i < addresses.length; i++) {
- var addr = {};
- for (var key in addresses[i]) {
- if (key == 'countryName') {
- addr['country'] = addresses[i][key];
- } else if (key == 'type') {
- addr[key] = addresses[i][key].join(' ');
- } else {
- addr[key] = addresses[i][key];
- }
- }
- arr.push(addr);
- }
- return arr;
- }
-
- function createOrganizations(orgs, jobs) {
- orgs = (orgs) ? orgs : [];
- jobs = (jobs) ? jobs : [];
- var max_length = Math.max(orgs.length, jobs.length);
- var organizations = [];
- for (var i=0; i < max_length; i++) {
- organizations.push(new ContactOrganization(
- null, null, orgs[i] || null, null, jobs[i] || null));
- }
- return organizations;
- }
-
- function createFormatted(name) {
- var fields = ['honorificPrefix', 'givenName', 'middleName',
- 'familyName', 'honorificSuffix'];
- var f = '';
- for (var i = 0; i < fields.length; i++) {
- if (name[fields[i]]) {
- if (f) {
- f += ' ';
- }
- f += name[fields[i]];
- }
- }
- return f;
- }
-
-
- if (moz.id) {
- this.id = moz.id;
- }
- var nameFields = [['givenName'], ['familyName'],
- ['honorificPrefix'], ['honorificSuffix'],
- ['additionalName', 'middleName']];
- var baseArrayFields = [['name', 'displayName'], 'nickname', ['note']];
- var baseStringFields = [];
- var name = new ContactName();
- var j = 0; while(field = nameFields[j++]) {
- if (moz[field[0]]) {
- name[field[1] || field[0]] = moz[field[0]].join(' ');
- }
- }
- this.name = name;
- j = 0; while(field = baseArrayFields[j++]) {
- if (moz[field[0]]) {
- this[field[1] || field[0]] = moz[field[0]].join(' ');
- }
- }
- j = 0; while(field = baseStringFields[j++]) {
- if (moz[field[0]]) {
- this[field[1] || field[0]] = moz[field[0]];
- }
- }
- // emails
- if (moz.email) {
- this.emails = exportContactField(moz.email);
- }
- // categories
- if (moz.category) {
- this.categories = makeContactFieldFromArray(moz.category);
- }
-
- // addresses
- if (moz.adr) {
- this.addresses = exportAddresses(moz.adr);
- }
-
- // phoneNumbers
- if (moz.tel) {
- this.phoneNumbers = exportContactField(moz.tel);
- }
- // birthday
- if (moz.bday) {
- this.birthday = Date.parse(moz.bday);
- }
- // organizations
- if (moz.org || moz.jobTitle) {
- // XXX: organizations array is created from org and jobTitle
- this.organizations = createOrganizations(moz.org, moz.jobTitle);
- }
- // construct a read-only formatted value
- this.name.formatted = createFormatted(this.name);
-
- /* Find out how to translate these parameters
- // photo: Blob
- // url: Array with metadata (?)
- // impp: exportIM(contact.ims), TODO: find the moz impp definition
- // anniversary
- // sex
- // genderIdentity
- // key
- */
-}
-
-
-function createMozillaFromCordova(successCB, errorCB, contact) {
- var moz;
- // get contact if exists
- if (_hasId(contact.id)) {
- var search = navigator.mozContacts.find({
- filterBy: ['id'], filterValue: contact.id, filterOp: 'equals'});
- search.onsuccess = function() {
- moz = search.result[0];
- updateFromCordova(moz, contact);
- successCB(moz);
- };
- search.onerror = errorCB;
- return;
- }
-
- // create empty contact
- moz = new mozContact();
- // if ('init' in moz) {
- // 1.2 and below compatibility
- // moz.init();
- // }
- updateFromCordova(moz, contact);
- successCB(moz);
-}
-
-
-function createCordovaFromMozilla(moz) {
- var contact = new Contact();
- contact.updateFromMozilla(moz);
- return contact;
-}
-
-
-// However API requires the ability to save multiple contacts, it is
-// used to save only one element array
-function saveContacts(successCB, errorCB, contacts) {
- // a closure which is holding the right moz contact
- function makeSaveSuccessCB(moz) {
- return function(result) {
- // create contact from FXOS contact (might be different than
- // the original one due to differences in API)
- var contact = createCordovaFromMozilla(moz);
- // call callback
- successCB(contact);
- }
- }
- var i=0;
- var contact;
- while(contact = contacts[i++]){
- var moz = createMozillaFromCordova(function(moz) {
- var request = navigator.mozContacts.save(moz);
- // success and/or fail will be called every time a contact is saved
- request.onsuccess = makeSaveSuccessCB(moz);
- request.onerror = errorCB;
- }, function() {}, contact);
- }
-}
-
-
-// API provides a list of ids to be removed
-function remove(successCB, errorCB, ids) {
- var i=0;
- var id;
- for (var i=0; i < ids.length; i++){
- // throw an error if no id provided
- if (!_hasId(ids[i])) {
- console.error('FFOS: Attempt to remove unsaved contact');
- errorCB(0);
- return;
- }
- // check if provided id actually exists
- var search = navigator.mozContacts.find({
- filterBy: ['id'], filterValue: ids[i], filterOp: 'equals'});
- search.onsuccess = function() {
- if (search.result.length === 0) {
- console.error('FFOS: Attempt to remove a non existing contact');
- errorCB(0);
- return;
- }
- var moz = search.result[0];
- var request = navigator.mozContacts.remove(moz);
- request.onsuccess = successCB;
- request.onerror = errorCB;
- };
- search.onerror = errorCB;
- }
-}
-
-
-var mozContactSearchFields = [['name', 'displayName'], ['givenName'],
- ['familyName'], ['email'], ['tel'], ['jobTitle'], ['note'],
- ['tel', 'phoneNumbers'], ['email', 'emails']];
-// Searching by nickname and additionalName is forbidden in 1.3 and below
-// Searching by name is forbidden in 1.2 and below
-
-// finds if a key is allowed and returns FFOS name if different
-function getMozSearchField(key) {
- if (mozContactSearchFields.indexOf([key]) >= 0) {
- return key;
- }
- for (var i=0; i < mozContactSearchFields.length; i++) {
- if (mozContactSearchFields[i].length > 1) {
- if (mozContactSearchFields[i][1] === key) {
- return mozContactSearchFields[i][0];
- }
- }
- }
- return false;
-}
-
-
-function _getAll(successCB, errorCB, params) {
- // [contactField, eventualMozContactField]
- var getall = navigator.mozContacts.getAll({});
- var contacts = [];
-
- getall.onsuccess = function() {
- if (getall.result) {
- contacts.push(createCordovaFromMozilla(getall.result));
- getall.continue();
- } else {
- successCB(contacts);
- }
- };
- getall.onerror = errorCB;
-}
-
-
-function search(successCB, errorCB, params) {
- var options = params[1] || {};
- if (!options.filter) {
- return _getAll(successCB, errorCB, params);
- }
- var filterBy = [];
- // filter and translate fields
- for (var i=0; i < params[0].length; i++) {
- var searchField = params[0][i];
- var mozField = getMozSearchField(searchField);
- if (searchField === 'name') {
- // Cordova uses name for search by all name fields.
- filterBy.push('givenName');
- filterBy.push('familyName');
- continue;
- }
- if (searchField === 'displayName' && 'init' in new mozContact()) {
- // ``init`` in ``mozContact`` indicates FFOS version 1.2 or below
- // Searching by name (in moz) is then forbidden
- console.log('FFOS ContactProxy: Unable to search by displayName on FFOS 1.2');
- continue;
- }
- if (mozField) {
- filterBy.push(mozField);
- } else {
- console.log('FXOS ContactProxy: inallowed field passed to search filtered out: ' + searchField);
- }
- }
-
- var mozOptions = {filterBy: filterBy, filterOp: 'startsWith'};
- if (!options.multiple) {
- mozOptions.filterLimit = 1;
- }
- mozOptions.filterValue = options.filter;
- var request = navigator.mozContacts.find(mozOptions);
- request.onsuccess = function() {
- var contacts = [];
- var mozContacts = request.result;
- var moz = mozContacts[0];
- for (var i=0; i < mozContacts.length; i++) {
- contacts.push(createCordovaFromMozilla(mozContacts[i]));
- }
- successCB(contacts);
- };
- request.onerror = errorCB;
-}
-
-
-module.exports = {
- save: saveContacts,
- remove: remove,
- search: search
-};
-
-require("cordova/firefoxos/commandProxy").add("Contacts", module.exports);
\ No newline at end of file
diff --git a/src/ios/CDVContact.h b/src/ios/CDVContact.h
deleted file mode 100644
index 5187efc..0000000
--- a/src/ios/CDVContact.h
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import <Foundation/Foundation.h>
-#import <AddressBook/ABAddressBook.h>
-#import <AddressBookUI/AddressBookUI.h>
-
-enum CDVContactError {
- UNKNOWN_ERROR = 0,
- INVALID_ARGUMENT_ERROR = 1,
- TIMEOUT_ERROR = 2,
- PENDING_OPERATION_ERROR = 3,
- IO_ERROR = 4,
- NOT_SUPPORTED_ERROR = 5,
- PERMISSION_DENIED_ERROR = 20
-};
-typedef NSUInteger CDVContactError;
-
-@interface CDVContact : NSObject {
- ABRecordRef record; // the ABRecord associated with this contact
- NSDictionary* returnFields; // dictionary of fields to return when performing search
-}
-
-@property (nonatomic, assign) ABRecordRef record;
-@property (nonatomic, strong) NSDictionary* returnFields;
-
-+ (NSDictionary*)defaultABtoW3C;
-+ (NSDictionary*)defaultW3CtoAB;
-+ (NSSet*)defaultW3CtoNull;
-+ (NSDictionary*)defaultObjectAndProperties;
-+ (NSDictionary*)defaultFields;
-
-+ (NSDictionary*)calcReturnFields:(NSArray*)fields;
-- (id)init;
-- (id)initFromABRecord:(ABRecordRef)aRecord;
-- (bool)setFromContactDict:(NSDictionary*)aContact asUpdate:(BOOL)bUpdate;
-
-+ (BOOL)needsConversion:(NSString*)W3Label;
-+ (CFStringRef)convertContactTypeToPropertyLabel:(NSString*)label;
-+ (NSString*)convertPropertyLabelToContactType:(NSString*)label;
-+ (BOOL)isValidW3ContactType:(NSString*)label;
-- (bool)setValue:(id)aValue forProperty:(ABPropertyID)aProperty inRecord:(ABRecordRef)aRecord asUpdate:(BOOL)bUpdate;
-
-- (NSDictionary*)toDictionary:(NSDictionary*)withFields;
-- (NSNumber*)getDateAsNumber:(ABPropertyID)datePropId;
-- (NSObject*)extractName;
-- (NSObject*)extractMultiValue:(NSString*)propertyId;
-- (NSObject*)extractAddresses;
-- (NSObject*)extractIms;
-- (NSObject*)extractOrganizations;
-- (NSObject*)extractPhotos;
-
-- (NSMutableDictionary*)translateW3Dict:(NSDictionary*)dict forProperty:(ABPropertyID)prop;
-- (bool)setMultiValueStrings:(NSArray*)fieldArray forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate;
-- (bool)setMultiValueDictionary:(NSArray*)array forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate;
-- (ABMultiValueRef)allocStringMultiValueFromArray:array;
-- (ABMultiValueRef)allocDictMultiValueFromArray:array forProperty:(ABPropertyID)prop;
-- (BOOL)foundValue:(NSString*)testValue inFields:(NSDictionary*)searchFields;
-- (BOOL)testStringValue:(NSString*)testValue forW3CProperty:(NSString*)property;
-- (BOOL)testDateValue:(NSString*)testValue forW3CProperty:(NSString*)property;
-- (BOOL)searchContactFields:(NSArray*)fields forMVStringProperty:(ABPropertyID)propId withValue:testValue;
-- (BOOL)testMultiValueStrings:(NSString*)testValue forProperty:(ABPropertyID)propId ofType:(NSString*)type;
-- (NSArray*)valuesForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord;
-- (NSArray*)labelsForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord;
-- (BOOL)searchContactFields:(NSArray*)fields forMVDictionaryProperty:(ABPropertyID)propId withValue:(NSString*)testValue;
-
-@end
-
-// generic ContactField types
-#define kW3ContactFieldType @"type"
-#define kW3ContactFieldValue @"value"
-#define kW3ContactFieldPrimary @"pref"
-// Various labels for ContactField types
-#define kW3ContactWorkLabel @"work"
-#define kW3ContactHomeLabel @"home"
-#define kW3ContactOtherLabel @"other"
-#define kW3ContactPhoneFaxLabel @"fax"
-#define kW3ContactPhoneMobileLabel @"mobile"
-#define kW3ContactPhonePagerLabel @"pager"
-#define kW3ContactUrlBlog @"blog"
-#define kW3ContactUrlProfile @"profile"
-#define kW3ContactImAIMLabel @"aim"
-#define kW3ContactImICQLabel @"icq"
-#define kW3ContactImMSNLabel @"msn"
-#define kW3ContactImYahooLabel @"yahoo"
-#define kW3ContactFieldId @"id"
-// special translation for IM field value and type
-#define kW3ContactImType @"type"
-#define kW3ContactImValue @"value"
-
-// Contact object
-#define kW3ContactId @"id"
-#define kW3ContactName @"name"
-#define kW3ContactFormattedName @"formatted"
-#define kW3ContactGivenName @"givenName"
-#define kW3ContactFamilyName @"familyName"
-#define kW3ContactMiddleName @"middleName"
-#define kW3ContactHonorificPrefix @"honorificPrefix"
-#define kW3ContactHonorificSuffix @"honorificSuffix"
-#define kW3ContactDisplayName @"displayName"
-#define kW3ContactNickname @"nickname"
-#define kW3ContactPhoneNumbers @"phoneNumbers"
-#define kW3ContactAddresses @"addresses"
-#define kW3ContactAddressFormatted @"formatted"
-#define kW3ContactStreetAddress @"streetAddress"
-#define kW3ContactLocality @"locality"
-#define kW3ContactRegion @"region"
-#define kW3ContactPostalCode @"postalCode"
-#define kW3ContactCountry @"country"
-#define kW3ContactEmails @"emails"
-#define kW3ContactIms @"ims"
-#define kW3ContactOrganizations @"organizations"
-#define kW3ContactOrganizationName @"name"
-#define kW3ContactTitle @"title"
-#define kW3ContactDepartment @"department"
-#define kW3ContactBirthday @"birthday"
-#define kW3ContactNote @"note"
-#define kW3ContactPhotos @"photos"
-#define kW3ContactCategories @"categories"
-#define kW3ContactUrls @"urls"
diff --git a/src/ios/CDVContact.m b/src/ios/CDVContact.m
deleted file mode 100644
index 5bf9f3c..0000000
--- a/src/ios/CDVContact.m
+++ /dev/null
@@ -1,1752 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import "CDVContact.h"
-#import <Cordova/NSDictionary+Extensions.h>
-
-#define DATE_OR_NULL(dateObj) ((aDate != nil) ? (id)([aDate descriptionWithLocale:[NSLocale currentLocale]]) : (id)([NSNull null]))
-#define IS_VALID_VALUE(value) ((value != nil) && (![value isKindOfClass:[NSNull class]]))
-
-static NSDictionary* org_apache_cordova_contacts_W3CtoAB = nil;
-static NSDictionary* org_apache_cordova_contacts_ABtoW3C = nil;
-static NSSet* org_apache_cordova_contacts_W3CtoNull = nil;
-static NSDictionary* org_apache_cordova_contacts_objectAndProperties = nil;
-static NSDictionary* org_apache_cordova_contacts_defaultFields = nil;
-
-@implementation CDVContact : NSObject
-
- @synthesize returnFields;
-
-- (id)init
-{
- if ((self = [super init]) != nil) {
- ABRecordRef rec = ABPersonCreate();
- self.record = rec;
- if (rec) {
- CFRelease(rec);
- }
- }
- return self;
-}
-
-- (id)initFromABRecord:(ABRecordRef)aRecord
-{
- if ((self = [super init]) != nil) {
- self.record = aRecord;
- }
- return self;
-}
-
-/* synthesize 'record' ourselves to have retain properties for CF types */
-
-- (void)setRecord:(ABRecordRef)aRecord
-{
- if (record != NULL) {
- CFRelease(record);
- }
- if (aRecord != NULL) {
- record = CFRetain(aRecord);
- }
-}
-
-- (ABRecordRef)record
-{
- return record;
-}
-
-/* Rather than creating getters and setters for each AddressBook (AB) Property, generic methods are used to deal with
- * simple properties, MultiValue properties( phone numbers and emails) and MultiValueDictionary properties (Ims and addresses).
- * The dictionaries below are used to translate between the W3C identifiers and the AB properties. Using the dictionaries,
- * allows looping through sets of properties to extract from or set into the W3C dictionary to/from the ABRecord.
- */
-
-/* The two following dictionaries translate between W3C properties and AB properties. It currently mixes both
- * Properties (kABPersonAddressProperty for example) and Strings (kABPersonAddressStreetKey) so users should be aware of
- * what types of values are expected.
- * a bit.
-*/
-+ (NSDictionary*)defaultABtoW3C
-{
- if (org_apache_cordova_contacts_ABtoW3C == nil) {
- org_apache_cordova_contacts_ABtoW3C = [NSDictionary dictionaryWithObjectsAndKeys:
- kW3ContactNickname, [NSNumber numberWithInt:kABPersonNicknameProperty],
- kW3ContactGivenName, [NSNumber numberWithInt:kABPersonFirstNameProperty],
- kW3ContactFamilyName, [NSNumber numberWithInt:kABPersonLastNameProperty],
- kW3ContactMiddleName, [NSNumber numberWithInt:kABPersonMiddleNameProperty],
- kW3ContactHonorificPrefix, [NSNumber numberWithInt:kABPersonPrefixProperty],
- kW3ContactHonorificSuffix, [NSNumber numberWithInt:kABPersonSuffixProperty],
- kW3ContactPhoneNumbers, [NSNumber numberWithInt:kABPersonPhoneProperty],
- kW3ContactAddresses, [NSNumber numberWithInt:kABPersonAddressProperty],
- kW3ContactStreetAddress, kABPersonAddressStreetKey,
- kW3ContactLocality, kABPersonAddressCityKey,
- kW3ContactRegion, kABPersonAddressStateKey,
- kW3ContactPostalCode, kABPersonAddressZIPKey,
- kW3ContactCountry, kABPersonAddressCountryKey,
- kW3ContactEmails, [NSNumber numberWithInt:kABPersonEmailProperty],
- kW3ContactIms, [NSNumber numberWithInt:kABPersonInstantMessageProperty],
- kW3ContactOrganizations, [NSNumber numberWithInt:kABPersonOrganizationProperty],
- kW3ContactOrganizationName, [NSNumber numberWithInt:kABPersonOrganizationProperty],
- kW3ContactTitle, [NSNumber numberWithInt:kABPersonJobTitleProperty],
- kW3ContactDepartment, [NSNumber numberWithInt:kABPersonDepartmentProperty],
- kW3ContactBirthday, [NSNumber numberWithInt:kABPersonBirthdayProperty],
- kW3ContactUrls, [NSNumber numberWithInt:kABPersonURLProperty],
- kW3ContactNote, [NSNumber numberWithInt:kABPersonNoteProperty],
- nil];
- }
-
- return org_apache_cordova_contacts_ABtoW3C;
-}
-
-+ (NSDictionary*)defaultW3CtoAB
-{
- if (org_apache_cordova_contacts_W3CtoAB == nil) {
- org_apache_cordova_contacts_W3CtoAB = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSNumber numberWithInt:kABPersonNicknameProperty], kW3ContactNickname,
- [NSNumber numberWithInt:kABPersonFirstNameProperty], kW3ContactGivenName,
- [NSNumber numberWithInt:kABPersonLastNameProperty], kW3ContactFamilyName,
- [NSNumber numberWithInt:kABPersonMiddleNameProperty], kW3ContactMiddleName,
- [NSNumber numberWithInt:kABPersonPrefixProperty], kW3ContactHonorificPrefix,
- [NSNumber numberWithInt:kABPersonSuffixProperty], kW3ContactHonorificSuffix,
- [NSNumber numberWithInt:kABPersonPhoneProperty], kW3ContactPhoneNumbers,
- [NSNumber numberWithInt:kABPersonAddressProperty], kW3ContactAddresses,
- kABPersonAddressStreetKey, kW3ContactStreetAddress,
- kABPersonAddressCityKey, kW3ContactLocality,
- kABPersonAddressStateKey, kW3ContactRegion,
- kABPersonAddressZIPKey, kW3ContactPostalCode,
- kABPersonAddressCountryKey, kW3ContactCountry,
- [NSNumber numberWithInt:kABPersonEmailProperty], kW3ContactEmails,
- [NSNumber numberWithInt:kABPersonInstantMessageProperty], kW3ContactIms,
- [NSNumber numberWithInt:kABPersonOrganizationProperty], kW3ContactOrganizations,
- [NSNumber numberWithInt:kABPersonJobTitleProperty], kW3ContactTitle,
- [NSNumber numberWithInt:kABPersonDepartmentProperty], kW3ContactDepartment,
- [NSNumber numberWithInt:kABPersonBirthdayProperty], kW3ContactBirthday,
- [NSNumber numberWithInt:kABPersonNoteProperty], kW3ContactNote,
- [NSNumber numberWithInt:kABPersonURLProperty], kW3ContactUrls,
- kABPersonInstantMessageUsernameKey, kW3ContactImValue,
- kABPersonInstantMessageServiceKey, kW3ContactImType,
- [NSNull null], kW3ContactFieldType, /* include entries in dictionary to indicate ContactField properties */
- [NSNull null], kW3ContactFieldValue,
- [NSNull null], kW3ContactFieldPrimary,
- [NSNull null], kW3ContactFieldId,
- [NSNumber numberWithInt:kABPersonOrganizationProperty], kW3ContactOrganizationName, /* careful, name is used multiple times*/
- nil];
- }
- return org_apache_cordova_contacts_W3CtoAB;
-}
-
-+ (NSSet*)defaultW3CtoNull
-{
- // these are values that have no AddressBook Equivalent OR have not been implemented yet
- if (org_apache_cordova_contacts_W3CtoNull == nil) {
- org_apache_cordova_contacts_W3CtoNull = [NSSet setWithObjects:kW3ContactDisplayName,
- kW3ContactCategories, kW3ContactFormattedName, nil];
- }
- return org_apache_cordova_contacts_W3CtoNull;
-}
-
-/*
- * The objectAndProperties dictionary contains the all of the properties of the W3C Contact Objects specified by the key
- * Used in calcReturnFields, and various extract<Property> methods
- */
-+ (NSDictionary*)defaultObjectAndProperties
-{
- if (org_apache_cordova_contacts_objectAndProperties == nil) {
- org_apache_cordova_contacts_objectAndProperties = [NSDictionary dictionaryWithObjectsAndKeys:
- [NSArray arrayWithObjects:kW3ContactGivenName, kW3ContactFamilyName,
- kW3ContactMiddleName, kW3ContactHonorificPrefix, kW3ContactHonorificSuffix, kW3ContactFormattedName, nil], kW3ContactName,
- [NSArray arrayWithObjects:kW3ContactStreetAddress, kW3ContactLocality, kW3ContactRegion,
- kW3ContactPostalCode, kW3ContactCountry, /*kW3ContactAddressFormatted,*/ nil], kW3ContactAddresses,
- [NSArray arrayWithObjects:kW3ContactOrganizationName, kW3ContactTitle, kW3ContactDepartment, nil], kW3ContactOrganizations,
- [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactPhoneNumbers,
- [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactEmails,
- [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactPhotos,
- [NSArray arrayWithObjects:kW3ContactFieldType, kW3ContactFieldValue, kW3ContactFieldPrimary, nil], kW3ContactUrls,
- [NSArray arrayWithObjects:kW3ContactImValue, kW3ContactImType, nil], kW3ContactIms,
- nil];
- }
- return org_apache_cordova_contacts_objectAndProperties;
-}
-
-+ (NSDictionary*)defaultFields
-{
- if (org_apache_cordova_contacts_defaultFields == nil) {
- org_apache_cordova_contacts_defaultFields = [NSDictionary dictionaryWithObjectsAndKeys:
- [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactName], kW3ContactName,
- [NSNull null], kW3ContactNickname,
- [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactAddresses], kW3ContactAddresses,
- [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactOrganizations], kW3ContactOrganizations,
- [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactPhoneNumbers], kW3ContactPhoneNumbers,
- [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactEmails], kW3ContactEmails,
- [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactIms], kW3ContactIms,
- [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactPhotos], kW3ContactPhotos,
- [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactUrls], kW3ContactUrls,
- [NSNull null], kW3ContactBirthday,
- [NSNull null], kW3ContactNote,
- nil];
- }
- return org_apache_cordova_contacts_defaultFields;
-}
-
-/* Translate W3C Contact data into ABRecordRef
- *
- * New contact information comes in as a NSMutableDictionary. All Null entries in Contact object are set
- * as [NSNull null] in the dictionary when translating from the JSON input string of Contact data. However, if
- * user did not set a value within a Contact object or sub-object (by not using the object constructor) some data
- * may not exist.
- * bUpdate = YES indicates this is a save of an existing record
- */
-- (bool)setFromContactDict:(NSDictionary*)aContact asUpdate:(BOOL)bUpdate
-{
- if (![aContact isKindOfClass:[NSDictionary class]]) {
- return FALSE; // can't do anything if no dictionary!
- }
-
- ABRecordRef person = self.record;
- bool bSuccess = TRUE;
- CFErrorRef error;
-
- // set name info
- // iOS doesn't have displayName - might have to pull parts from it to create name
- bool bName = false;
- NSDictionary* dict = [aContact valueForKey:kW3ContactName];
- if ([dict isKindOfClass:[NSDictionary class]]) {
- bName = true;
- NSArray* propArray = [[CDVContact defaultObjectAndProperties] objectForKey:kW3ContactName];
-
- for (id i in propArray) {
- if (![(NSString*)i isEqualToString : kW3ContactFormattedName]) { // kW3ContactFormattedName is generated from ABRecordCopyCompositeName() and can't be set
- [self setValue:[dict valueForKey:i] forProperty:(ABPropertyID)[(NSNumber*)[[CDVContact defaultW3CtoAB] objectForKey:i] intValue]
- inRecord:person asUpdate:bUpdate];
- }
- }
- }
-
- id nn = [aContact valueForKey:kW3ContactNickname];
- if (![nn isKindOfClass:[NSNull class]]) {
- bName = true;
- [self setValue:nn forProperty:kABPersonNicknameProperty inRecord:person asUpdate:bUpdate];
- }
- if (!bName) {
- // if no name or nickname - try and use displayName as W3Contact must have displayName or ContactName
- [self setValue:[aContact valueForKey:kW3ContactDisplayName] forProperty:kABPersonNicknameProperty
- inRecord:person asUpdate:bUpdate];
- }
-
- // set phoneNumbers
- // NSLog(@"setting phoneNumbers");
- NSArray* array = [aContact valueForKey:kW3ContactPhoneNumbers];
- if ([array isKindOfClass:[NSArray class]]) {
- [self setMultiValueStrings:array forProperty:kABPersonPhoneProperty inRecord:person asUpdate:bUpdate];
- }
- // set Emails
- // NSLog(@"setting emails");
- array = [aContact valueForKey:kW3ContactEmails];
- if ([array isKindOfClass:[NSArray class]]) {
- [self setMultiValueStrings:array forProperty:kABPersonEmailProperty inRecord:person asUpdate:bUpdate];
- }
- // set Urls
- // NSLog(@"setting urls");
- array = [aContact valueForKey:kW3ContactUrls];
- if ([array isKindOfClass:[NSArray class]]) {
- [self setMultiValueStrings:array forProperty:kABPersonURLProperty inRecord:person asUpdate:bUpdate];
- }
-
- // set multivalue dictionary properties
- // set addresses: streetAddress, locality, region, postalCode, country
- // set ims: value = username, type = servicetype
- // iOS addresses and im are a MultiValue Properties with label, value=dictionary of info, and id
- // NSLog(@"setting addresses");
- error = nil;
- array = [aContact valueForKey:kW3ContactAddresses];
- if ([array isKindOfClass:[NSArray class]]) {
- [self setMultiValueDictionary:array forProperty:kABPersonAddressProperty inRecord:person asUpdate:bUpdate];
- }
- // ims
- // NSLog(@"setting ims");
- array = [aContact valueForKey:kW3ContactIms];
- if ([array isKindOfClass:[NSArray class]]) {
- [self setMultiValueDictionary:array forProperty:kABPersonInstantMessageProperty inRecord:person asUpdate:bUpdate];
- }
-
- // organizations
- // W3C ContactOrganization has pref, type, name, title, department
- // iOS only supports name, title, department
- // NSLog(@"setting organizations");
- // TODO this may need work - should Organization information be removed when array is empty??
- array = [aContact valueForKey:kW3ContactOrganizations]; // iOS only supports one organization - use first one
- if ([array isKindOfClass:[NSArray class]]) {
- BOOL bRemove = NO;
- NSDictionary* dict = nil;
- if ([array count] > 0) {
- dict = [array objectAtIndex:0];
- } else {
- // remove the organization info entirely
- bRemove = YES;
- }
- if ([dict isKindOfClass:[NSDictionary class]] || (bRemove == YES)) {
- [self setValue:(bRemove ? @"" : [dict valueForKey:@"name"]) forProperty:kABPersonOrganizationProperty inRecord:person asUpdate:bUpdate];
- [self setValue:(bRemove ? @"" : [dict valueForKey:kW3ContactTitle]) forProperty:kABPersonJobTitleProperty inRecord:person asUpdate:bUpdate];
- [self setValue:(bRemove ? @"" : [dict valueForKey:kW3ContactDepartment]) forProperty:kABPersonDepartmentProperty inRecord:person asUpdate:bUpdate];
- }
- }
- // add dates
- // Dates come in as milliseconds in NSNumber Object
- id ms = [aContact valueForKey:kW3ContactBirthday];
- NSDate* aDate = nil;
- if (ms && [ms isKindOfClass:[NSNumber class]]) {
- double msValue = [ms doubleValue];
- msValue = msValue / 1000;
- aDate = [NSDate dateWithTimeIntervalSince1970:msValue];
- }
- if ((aDate != nil) || [ms isKindOfClass:[NSString class]]) {
- [self setValue:aDate != nil ? aDate:ms forProperty:kABPersonBirthdayProperty inRecord:person asUpdate:bUpdate];
- }
- // don't update creation date
- // modification date will get updated when save
- // anniversary is removed from W3C Contact api Dec 9, 2010 spec - don't waste time on it yet
-
- // kABPersonDateProperty
-
- // kABPersonAnniversaryLabel
-
- // iOS doesn't have gender - ignore
- // note
- [self setValue:[aContact valueForKey:kW3ContactNote] forProperty:kABPersonNoteProperty inRecord:person asUpdate:bUpdate];
-
- // iOS doesn't have preferredName- ignore
-
- // photo
- array = [aContact valueForKey:kW3ContactPhotos];
- if ([array isKindOfClass:[NSArray class]]) {
- if (bUpdate && ([array count] == 0)) {
- // remove photo
- bSuccess = ABPersonRemoveImageData(person, &error);
- } else if ([array count] > 0) {
- NSDictionary* dict = [array objectAtIndex:0]; // currently only support one photo
- if ([dict isKindOfClass:[NSDictionary class]]) {
- id value = [dict objectForKey:kW3ContactFieldValue];
- if ([value isKindOfClass:[NSString class]]) {
- if (bUpdate && ([value length] == 0)) {
- // remove the current image
- bSuccess = ABPersonRemoveImageData(person, &error);
- } else {
- // use this image
- // don't know if string is encoded or not so first unencode it then encode it again
- NSString* cleanPath = [value stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
- NSURL* photoUrl = [NSURL URLWithString:[cleanPath stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
- // caller is responsible for checking for a connection, if no connection this will fail
- NSError* err = nil;
- NSData* data = nil;
- if (photoUrl) {
- data = [NSData dataWithContentsOfURL:photoUrl options:NSDataReadingUncached error:&err];
- }
- if (data && ([data length] > 0)) {
- bSuccess = ABPersonSetImageData(person, (__bridge CFDataRef)data, &error);
- }
- if (!data || !bSuccess) {
- NSLog(@"error setting contact image: %@", (err != nil ? [err localizedDescription] : @""));
- }
- }
- }
- }
- }
- }
-
- // TODO WebURLs
-
- // TODO timezone
-
- return bSuccess;
-}
-
-/* Set item into an AddressBook Record for the specified property.
- * aValue - the value to set into the address book (code checks for null or [NSNull null]
- * aProperty - AddressBook property ID
- * aRecord - the record to update
- * bUpdate - whether this is a possible update vs a new entry
- * RETURN
- * true - property was set (or input value as null)
- * false - property was not set
- */
-- (bool)setValue:(id)aValue forProperty:(ABPropertyID)aProperty inRecord:(ABRecordRef)aRecord asUpdate:(BOOL)bUpdate
-{
- bool bSuccess = true; // if property was null, just ignore and return success
- CFErrorRef error;
-
- if (aValue && ![aValue isKindOfClass:[NSNull class]]) {
- if (bUpdate && ([aValue isKindOfClass:[NSString class]] && ([aValue length] == 0))) { // if updating, empty string means to delete
- aValue = NULL;
- } // really only need to set if different - more efficient to just update value or compare and only set if necessary???
- bSuccess = ABRecordSetValue(aRecord, aProperty, (__bridge CFTypeRef)aValue, &error);
- if (!bSuccess) {
- NSLog(@"error setting %d property", aProperty);
- }
- }
-
- return bSuccess;
-}
-
-- (bool)removeProperty:(ABPropertyID)aProperty inRecord:(ABRecordRef)aRecord
-{
- CFErrorRef err;
- bool bSuccess = ABRecordRemoveValue(aRecord, aProperty, &err);
-
- if (!bSuccess) {
- CFStringRef errDescription = CFErrorCopyDescription(err);
- NSLog(@"Unable to remove property %d: %@", aProperty, errDescription);
- CFRelease(errDescription);
- }
- return bSuccess;
-}
-
-- (bool)addToMultiValue:(ABMultiValueRef)multi fromDictionary:dict
-{
- bool bSuccess = FALSE;
- id value = [dict valueForKey:kW3ContactFieldValue];
-
- if (IS_VALID_VALUE(value)) {
- CFStringRef label = [CDVContact convertContactTypeToPropertyLabel:[dict valueForKey:kW3ContactFieldType]];
- bSuccess = ABMultiValueAddValueAndLabel(multi, (__bridge CFTypeRef)value, label, NULL);
- if (!bSuccess) {
- NSLog(@"Error setting Value: %@ and label: %@", value, label);
- }
- }
- return bSuccess;
-}
-
-- (ABMultiValueRef)allocStringMultiValueFromArray:array
-{
- ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiStringPropertyType);
-
- for (NSDictionary* dict in array) {
- [self addToMultiValue:multi fromDictionary:dict];
- }
-
- return multi; // caller is responsible for releasing multi
-}
-
-- (bool)setValue:(CFTypeRef)value forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person
-{
- CFErrorRef error;
- bool bSuccess = ABRecordSetValue(person, prop, value, &error);
-
- if (!bSuccess) {
- NSLog(@"Error setting value for property: %d", prop);
- }
- return bSuccess;
-}
-
-/* Set MultiValue string properties into Address Book Record.
- * NSArray* fieldArray - array of dictionaries containing W3C properties to be set into record
- * ABPropertyID prop - the property to be set (generally used for phones and emails)
- * ABRecordRef person - the record to set values into
- * BOOL bUpdate - whether or not to update date or set as new.
- * When updating:
- * empty array indicates to remove entire property
- * empty string indicates to remove
- * [NSNull null] do not modify (keep existing record value)
- * RETURNS
- * bool false indicates error
- *
- * used for phones and emails
- */
-- (bool)setMultiValueStrings:(NSArray*)fieldArray forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate
-{
- bool bSuccess = TRUE;
- ABMutableMultiValueRef multi = nil;
-
- if (!bUpdate) {
- multi = [self allocStringMultiValueFromArray:fieldArray];
- bSuccess = [self setValue:multi forProperty:prop inRecord:person];
- } else if (bUpdate && ([fieldArray count] == 0)) {
- // remove entire property
- bSuccess = [self removeProperty:prop inRecord:person];
- } else { // check for and apply changes
- ABMultiValueRef copy = ABRecordCopyValue(person, prop);
- if (copy != nil) {
- multi = ABMultiValueCreateMutableCopy(copy);
- CFRelease(copy);
-
- for (NSDictionary* dict in fieldArray) {
- id val;
- NSString* label = nil;
- val = [dict valueForKey:kW3ContactFieldValue];
- label = (__bridge NSString*)[CDVContact convertContactTypeToPropertyLabel:[dict valueForKey:kW3ContactFieldType]];
- if (IS_VALID_VALUE(val)) {
- // is an update, find index of entry with matching id, if values are different, update.
- id idValue = [dict valueForKey:kW3ContactFieldId];
- int identifier = [idValue isKindOfClass:[NSNumber class]] ? [idValue intValue] : -1;
- CFIndex i = identifier >= 0 ? ABMultiValueGetIndexForIdentifier(multi, identifier) : kCFNotFound;
- if (i != kCFNotFound) {
- if ([val length] == 0) {
- // remove both value and label
- ABMultiValueRemoveValueAndLabelAtIndex(multi, i);
- } else {
- NSString* valueAB = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(multi, i);
- NSString* labelAB = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
- if ((valueAB == nil) || ![val isEqualToString:valueAB]) {
- ABMultiValueReplaceValueAtIndex(multi, (__bridge CFTypeRef)val, i);
- }
- if ((labelAB == nil) || ![label isEqualToString:labelAB]) {
- ABMultiValueReplaceLabelAtIndex(multi, (__bridge CFStringRef)label, i);
- }
- }
- } else {
- // is a new value - insert
- [self addToMultiValue:multi fromDictionary:dict];
- }
- } // end of if value
- } // end of for
- } else { // adding all new value(s)
- multi = [self allocStringMultiValueFromArray:fieldArray];
- }
- // set the (updated) copy as the new value
- bSuccess = [self setValue:multi forProperty:prop inRecord:person];
- }
-
- if (multi) {
- CFRelease(multi);
- }
-
- return bSuccess;
-}
-
-// used for ims and addresses
-- (ABMultiValueRef)allocDictMultiValueFromArray:array forProperty:(ABPropertyID)prop
-{
- ABMutableMultiValueRef multi = ABMultiValueCreateMutable(kABMultiDictionaryPropertyType);
- NSMutableDictionary* newDict;
- NSMutableDictionary* addDict;
-
- for (NSDictionary* dict in array) {
- newDict = [self translateW3Dict:dict forProperty:prop];
- addDict = [NSMutableDictionary dictionaryWithCapacity:2];
- if (newDict) { // create a new dictionary with a Label and Value, value is the dictionary previously created
- // June, 2011 W3C Contact spec adds type into ContactAddress book
- // get the type out of the original dictionary for address
- NSString* addrType = (NSString*)[dict valueForKey:kW3ContactFieldType];
- if (!addrType) {
- addrType = (NSString*)kABOtherLabel;
- }
- NSObject* typeValue = ((prop == kABPersonInstantMessageProperty) ? (NSObject*)kABOtherLabel : addrType);
- // NSLog(@"typeValue: %@", typeValue);
- [addDict setObject:typeValue forKey:kW3ContactFieldType]; // im labels will be set as Other and address labels as type from dictionary
- [addDict setObject:newDict forKey:kW3ContactFieldValue];
- [self addToMultiValue:multi fromDictionary:addDict];
- }
- }
-
- return multi; // caller is responsible for releasing
-}
-
-// used for ims and addresses to convert W3 dictionary of values to AB Dictionary
-// got messier when June, 2011 W3C Contact spec added type field into ContactAddress
-- (NSMutableDictionary*)translateW3Dict:(NSDictionary*)dict forProperty:(ABPropertyID)prop
-{
- NSArray* propArray = [[CDVContact defaultObjectAndProperties] valueForKey:[[CDVContact defaultABtoW3C] objectForKey:[NSNumber numberWithInt:prop]]];
-
- NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:1];
- id value;
-
- for (NSString* key in propArray) { // for each W3 Contact key get the value
- if (((value = [dict valueForKey:key]) != nil) && ![value isKindOfClass:[NSNull class]]) {
- // if necessary convert the W3 value to AB Property label
- NSString* setValue = value;
- if ([CDVContact needsConversion:key]) { // IM types must be converted
- setValue = (NSString*)[CDVContact convertContactTypeToPropertyLabel:value];
- // IMs must have a valid AB value!
- if ((prop == kABPersonInstantMessageProperty) && [setValue isEqualToString:(NSString*)kABOtherLabel]) {
- setValue = @""; // try empty string
- }
- }
- // set the AB value into the dictionary
- [newDict setObject:setValue forKey:(NSString*)[[CDVContact defaultW3CtoAB] valueForKey:(NSString*)key]];
- }
- }
-
- if ([newDict count] == 0) {
- newDict = nil; // no items added
- }
- return newDict;
-}
-
-/* set multivalue dictionary properties into an AddressBook Record
- * NSArray* array - array of dictionaries containing the W3C properties to set into the record
- * ABPropertyID prop - the property id for the multivalue dictionary (addresses and ims)
- * ABRecordRef person - the record to set the values into
- * BOOL bUpdate - YES if this is an update to an existing record
- * When updating:
- * empty array indicates to remove entire property
- * value/label == "" indicates to remove
- * value/label == [NSNull null] do not modify (keep existing record value)
- * RETURN
- * bool false indicates fatal error
- *
- * iOS addresses and im are a MultiValue Properties with label, value=dictionary of info, and id
- * set addresses: streetAddress, locality, region, postalCode, country
- * set ims: value = username, type = servicetype
- * there are some special cases in here for ims - needs cleanup / simplification
- *
- */
-- (bool)setMultiValueDictionary:(NSArray*)array forProperty:(ABPropertyID)prop inRecord:(ABRecordRef)person asUpdate:(BOOL)bUpdate
-{
- bool bSuccess = FALSE;
- ABMutableMultiValueRef multi = nil;
-
- if (!bUpdate) {
- multi = [self allocDictMultiValueFromArray:array forProperty:prop];
- bSuccess = [self setValue:multi forProperty:prop inRecord:person];
- } else if (bUpdate && ([array count] == 0)) {
- // remove property
- bSuccess = [self removeProperty:prop inRecord:person];
- } else { // check for and apply changes
- ABMultiValueRef copy = ABRecordCopyValue(person, prop);
- if (copy) {
- multi = ABMultiValueCreateMutableCopy(copy);
- CFRelease(copy);
- // get the W3C values for this property
- NSArray* propArray = [[CDVContact defaultObjectAndProperties] valueForKey:[[CDVContact defaultABtoW3C] objectForKey:[NSNumber numberWithInt:prop]]];
- id value;
- id valueAB;
-
- for (NSDictionary* field in array) {
- NSMutableDictionary* dict;
- // find the index for the current property
- id idValue = [field valueForKey:kW3ContactFieldId];
- int identifier = [idValue isKindOfClass:[NSNumber class]] ? [idValue intValue] : -1;
- CFIndex idx = identifier >= 0 ? ABMultiValueGetIndexForIdentifier(multi, identifier) : kCFNotFound;
- BOOL bUpdateLabel = NO;
- if (idx != kCFNotFound) {
- dict = [NSMutableDictionary dictionaryWithCapacity:1];
- // NSDictionary* existingDictionary = (NSDictionary*)ABMultiValueCopyValueAtIndex(multi, idx);
- CFTypeRef existingDictionary = ABMultiValueCopyValueAtIndex(multi, idx);
- NSString* existingABLabel = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, idx);
- NSString* testLabel = [field valueForKey:kW3ContactFieldType];
- // fixes cb-143 where setting empty label could cause address to not be removed
- // (because empty label would become 'other' in convertContactTypeToPropertyLabel
- // which may not have matched existing label thus resulting in an incorrect updating of the label
- // and the address not getting removed at the end of the for loop)
- if (testLabel && [testLabel isKindOfClass:[NSString class]] && ([testLabel length] > 0)) {
- CFStringRef w3cLabel = [CDVContact convertContactTypeToPropertyLabel:testLabel];
- if (w3cLabel && ![existingABLabel isEqualToString:(__bridge NSString*)w3cLabel]) {
- // replace the label
- ABMultiValueReplaceLabelAtIndex(multi, w3cLabel, idx);
- bUpdateLabel = YES;
- }
- } // else was invalid or empty label string so do not update
-
- for (id k in propArray) {
- value = [field valueForKey:k];
- bool bSet = (value != nil && ![value isKindOfClass:[NSNull class]] && ([value isKindOfClass:[NSString class]] && [value length] > 0));
- // if there is a contact value, put it into dictionary
- if (bSet) {
- NSString* setValue = [CDVContact needsConversion:(NSString*)k] ? (NSString*)[CDVContact convertContactTypeToPropertyLabel:value] : value;
- [dict setObject:setValue forKey:(NSString*)[[CDVContact defaultW3CtoAB] valueForKey:(NSString*)k]];
- } else if ((value == nil) || ([value isKindOfClass:[NSString class]] && ([value length] != 0))) {
- // value not provided in contact dictionary - if prop exists in AB dictionary, preserve it
- valueAB = [(__bridge NSDictionary*)existingDictionary valueForKey : [[CDVContact defaultW3CtoAB] valueForKey:k]];
- if (valueAB != nil) {
- [dict setValue:valueAB forKey:[[CDVContact defaultW3CtoAB] valueForKey:k]];
- }
- } // else if value == "" it will not be added into updated dict and thus removed
- } // end of for loop (moving here fixes cb-143, need to end for loop before replacing or removing multivalue)
-
- if ([dict count] > 0) {
- // something was added into new dict,
- ABMultiValueReplaceValueAtIndex(multi, (__bridge CFTypeRef)dict, idx);
- } else if (!bUpdateLabel) {
- // nothing added into new dict and no label change so remove this property entry
- ABMultiValueRemoveValueAndLabelAtIndex(multi, idx);
- }
-
- CFRelease(existingDictionary);
- } else {
- // not found in multivalue so add it
- dict = [self translateW3Dict:field forProperty:prop];
- if (dict) {
- NSMutableDictionary* addDict = [NSMutableDictionary dictionaryWithCapacity:2];
- // get the type out of the original dictionary for address
- NSObject* typeValue = ((prop == kABPersonInstantMessageProperty) ? (NSObject*)kABOtherLabel : (NSString*)[field valueForKey:kW3ContactFieldType]);
- // NSLog(@"typeValue: %@", typeValue);
- [addDict setObject:typeValue forKey:kW3ContactFieldType]; // im labels will be set as Other and address labels as type from dictionary
- [addDict setObject:dict forKey:kW3ContactFieldValue];
- [self addToMultiValue:multi fromDictionary:addDict];
- }
- }
- } // end of looping through dictionaries
-
- // set the (updated) copy as the new value
- bSuccess = [self setValue:multi forProperty:prop inRecord:person];
- }
- } // end of copy and apply changes
- if (multi) {
- CFRelease(multi);
- }
-
- return bSuccess;
-}
-
-/* Determine which W3C labels need to be converted
- */
-+ (BOOL)needsConversion:(NSString*)W3Label
-{
- BOOL bConvert = NO;
-
- if ([W3Label isEqualToString:kW3ContactFieldType] || [W3Label isEqualToString:kW3ContactImType]) {
- bConvert = YES;
- }
- return bConvert;
-}
-
-/* Translation of property type labels contact API ---> iPhone
- *
- * phone: work, home, other, mobile, fax, pager -->
- * kABWorkLabel, kABHomeLabel, kABOtherLabel, kABPersonPhoneMobileLabel, kABPersonHomeFAXLabel || kABPersonHomeFAXLabel, kABPersonPhonePagerLabel
- * emails: work, home, other ---> kABWorkLabel, kABHomeLabel, kABOtherLabel
- * ims: aim, gtalk, icq, xmpp, msn, skype, qq, yahoo --> kABPersonInstantMessageService + (AIM, ICG, MSN, Yahoo). No support for gtalk, xmpp, skype, qq
- * addresses: work, home, other --> kABWorkLabel, kABHomeLabel, kABOtherLabel
- *
- *
- */
-+ (CFStringRef)convertContactTypeToPropertyLabel:(NSString*)label
-{
- CFStringRef type;
-
- if ([label isKindOfClass:[NSNull class]] || ![label isKindOfClass:[NSString class]]) {
- type = NULL; // no label
- } else if ([label caseInsensitiveCompare:kW3ContactWorkLabel] == NSOrderedSame) {
- type = kABWorkLabel;
- } else if ([label caseInsensitiveCompare:kW3ContactHomeLabel] == NSOrderedSame) {
- type = kABHomeLabel;
- } else if ([label caseInsensitiveCompare:kW3ContactOtherLabel] == NSOrderedSame) {
- type = kABOtherLabel;
- } else if ([label caseInsensitiveCompare:kW3ContactPhoneMobileLabel] == NSOrderedSame) {
- type = kABPersonPhoneMobileLabel;
- } else if ([label caseInsensitiveCompare:kW3ContactPhonePagerLabel] == NSOrderedSame) {
- type = kABPersonPhonePagerLabel;
- } else if ([label caseInsensitiveCompare:kW3ContactImAIMLabel] == NSOrderedSame) {
- type = kABPersonInstantMessageServiceAIM;
- } else if ([label caseInsensitiveCompare:kW3ContactImICQLabel] == NSOrderedSame) {
- type = kABPersonInstantMessageServiceICQ;
- } else if ([label caseInsensitiveCompare:kW3ContactImMSNLabel] == NSOrderedSame) {
- type = kABPersonInstantMessageServiceMSN;
- } else if ([label caseInsensitiveCompare:kW3ContactImYahooLabel] == NSOrderedSame) {
- type = kABPersonInstantMessageServiceYahoo;
- } else if ([label caseInsensitiveCompare:kW3ContactUrlProfile] == NSOrderedSame) {
- type = kABPersonHomePageLabel;
- } else {
- type = kABOtherLabel;
- }
-
- return type;
-}
-
-+ (NSString*)convertPropertyLabelToContactType:(NSString*)label
-{
- NSString* type = nil;
-
- if (label != nil) { // improve efficiency......
- if ([label isEqualToString:(NSString*)kABPersonPhoneMobileLabel]) {
- type = kW3ContactPhoneMobileLabel;
- } else if ([label isEqualToString:(NSString*)kABPersonPhoneHomeFAXLabel] ||
- [label isEqualToString:(NSString*)kABPersonPhoneWorkFAXLabel]) {
- type = kW3ContactPhoneFaxLabel;
- } else if ([label isEqualToString:(NSString*)kABPersonPhonePagerLabel]) {
- type = kW3ContactPhonePagerLabel;
- } else if ([label isEqualToString:(NSString*)kABHomeLabel]) {
- type = kW3ContactHomeLabel;
- } else if ([label isEqualToString:(NSString*)kABWorkLabel]) {
- type = kW3ContactWorkLabel;
- } else if ([label isEqualToString:(NSString*)kABOtherLabel]) {
- type = kW3ContactOtherLabel;
- } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceAIM]) {
- type = kW3ContactImAIMLabel;
- } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceICQ]) {
- type = kW3ContactImICQLabel;
- } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceJabber]) {
- type = kW3ContactOtherLabel;
- } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceMSN]) {
- type = kW3ContactImMSNLabel;
- } else if ([label isEqualToString:(NSString*)kABPersonInstantMessageServiceYahoo]) {
- type = kW3ContactImYahooLabel;
- } else if ([label isEqualToString:(NSString*)kABPersonHomePageLabel]) {
- type = kW3ContactUrlProfile;
- } else {
- type = kW3ContactOtherLabel;
- }
- }
- return type;
-}
-
-/* Check if the input label is a valid W3C ContactField.type. This is used when searching,
- * only search field types if the search string is a valid type. If we converted any search
- * string to a ABPropertyLabel it could convert to kABOtherLabel which is probably not want
- * the user wanted to search for and could skew the results.
- */
-+ (BOOL)isValidW3ContactType:(NSString*)label
-{
- BOOL isValid = NO;
-
- if ([label isKindOfClass:[NSNull class]] || ![label isKindOfClass:[NSString class]]) {
- isValid = NO; // no label
- } else if ([label caseInsensitiveCompare:kW3ContactWorkLabel] == NSOrderedSame) {
- isValid = YES;
- } else if ([label caseInsensitiveCompare:kW3ContactHomeLabel] == NSOrderedSame) {
- isValid = YES;
- } else if ([label caseInsensitiveCompare:kW3ContactOtherLabel] == NSOrderedSame) {
- isValid = YES;
- } else if ([label caseInsensitiveCompare:kW3ContactPhoneMobileLabel] == NSOrderedSame) {
- isValid = YES;
- } else if ([label caseInsensitiveCompare:kW3ContactPhonePagerLabel] == NSOrderedSame) {
- isValid = YES;
- } else if ([label caseInsensitiveCompare:kW3ContactImAIMLabel] == NSOrderedSame) {
- isValid = YES;
- } else if ([label caseInsensitiveCompare:kW3ContactImICQLabel] == NSOrderedSame) {
- isValid = YES;
- } else if ([label caseInsensitiveCompare:kW3ContactImMSNLabel] == NSOrderedSame) {
- isValid = YES;
- } else if ([label caseInsensitiveCompare:kW3ContactImYahooLabel] == NSOrderedSame) {
- isValid = YES;
- } else {
- isValid = NO;
- }
-
- return isValid;
-}
-
-/* Create a new Contact Dictionary object from an ABRecordRef that contains information in a format such that
- * it can be returned to JavaScript callback as JSON object string.
- * Uses:
- * ABRecordRef set into Contact Object
- * NSDictionary withFields indicates which fields to return from the AddressBook Record
- *
- * JavaScript Contact:
- * @param {DOMString} id unique identifier
- * @param {DOMString} displayName
- * @param {ContactName} name
- * @param {DOMString} nickname
- * @param {ContactField[]} phoneNumbers array of phone numbers
- * @param {ContactField[]} emails array of email addresses
- * @param {ContactAddress[]} addresses array of addresses
- * @param {ContactField[]} ims instant messaging user ids
- * @param {ContactOrganization[]} organizations
- * @param {DOMString} published date contact was first created
- * @param {DOMString} updated date contact was last updated
- * @param {DOMString} birthday contact's birthday
- * @param (DOMString} anniversary contact's anniversary
- * @param {DOMString} gender contact's gender
- * @param {DOMString} note user notes about contact
- * @param {DOMString} preferredUsername
- * @param {ContactField[]} photos
- * @param {ContactField[]} tags
- * @param {ContactField[]} relationships
- * @param {ContactField[]} urls contact's web sites
- * @param {ContactAccounts[]} accounts contact's online accounts
- * @param {DOMString} timezone UTC time zone offset
- * @param {DOMString} connected
- */
-
-- (NSDictionary*)toDictionary:(NSDictionary*)withFields
-{
- // if not a person type record bail out for now
- if (ABRecordGetRecordType(self.record) != kABPersonType) {
- return NULL;
- }
- id value = nil;
- self.returnFields = withFields;
-
- NSMutableDictionary* nc = [NSMutableDictionary dictionaryWithCapacity:1]; // new contact dictionary to fill in from ABRecordRef
- // id
- [nc setObject:[NSNumber numberWithInt:ABRecordGetRecordID(self.record)] forKey:kW3ContactId];
- if (self.returnFields == nil) {
- // if no returnFields specified, W3C says to return empty contact (but Cordova will at least return id)
- return nc;
- }
- if ([self.returnFields objectForKey:kW3ContactDisplayName]) {
- // displayname requested - iOS doesn't have so return null
- [nc setObject:[NSNull null] forKey:kW3ContactDisplayName];
- // may overwrite below if requested ContactName and there are no values
- }
- // nickname
- if ([self.returnFields valueForKey:kW3ContactNickname]) {
- value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, kABPersonNicknameProperty);
- [nc setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactNickname];
- }
-
- // name dictionary
- // NSLog(@"getting name info");
- NSObject* data = [self extractName];
- if (data != nil) {
- [nc setObject:data forKey:kW3ContactName];
- }
- if ([self.returnFields objectForKey:kW3ContactDisplayName] && ((data == nil) || ([(NSDictionary*)data objectForKey : kW3ContactFormattedName] == [NSNull null]))) {
- // user asked for displayName which iOS doesn't support but there is no other name data being returned
- // try and use Composite Name so some name is returned
- id tryName = (__bridge_transfer NSString*)ABRecordCopyCompositeName(self.record);
- if (tryName != nil) {
- [nc setObject:tryName forKey:kW3ContactDisplayName];
- } else {
- // use nickname or empty string
- value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, kABPersonNicknameProperty);
- [nc setObject:(value != nil) ? value:@"" forKey:kW3ContactDisplayName];
- }
- }
- // phoneNumbers array
- // NSLog(@"getting phoneNumbers");
- value = [self extractMultiValue:kW3ContactPhoneNumbers];
- if (value != nil) {
- [nc setObject:value forKey:kW3ContactPhoneNumbers];
- }
- // emails array
- // NSLog(@"getting emails");
- value = [self extractMultiValue:kW3ContactEmails];
- if (value != nil) {
- [nc setObject:value forKey:kW3ContactEmails];
- }
- // urls array
- value = [self extractMultiValue:kW3ContactUrls];
- if (value != nil) {
- [nc setObject:value forKey:kW3ContactUrls];
- }
- // addresses array
- // NSLog(@"getting addresses");
- value = [self extractAddresses];
- if (value != nil) {
- [nc setObject:value forKey:kW3ContactAddresses];
- }
- // im array
- // NSLog(@"getting ims");
- value = [self extractIms];
- if (value != nil) {
- [nc setObject:value forKey:kW3ContactIms];
- }
- // organization array (only info for one organization in iOS)
- // NSLog(@"getting organizations");
- value = [self extractOrganizations];
- if (value != nil) {
- [nc setObject:value forKey:kW3ContactOrganizations];
- }
-
- // for simple properties, could make this a bit more efficient by storing all simple properties in a single
- // array in the returnFields dictionary and setting them via a for loop through the array
-
- // add dates
- // NSLog(@"getting dates");
- NSNumber* ms;
-
- /** Contact Revision field removed from June 16, 2011 version of specification
-
- if ([self.returnFields valueForKey:kW3ContactUpdated]){
- ms = [self getDateAsNumber: kABPersonModificationDateProperty];
- if (!ms){
- // try and get published date
- ms = [self getDateAsNumber: kABPersonCreationDateProperty];
- }
- if (ms){
- [nc setObject: ms forKey:kW3ContactUpdated];
- }
-
- }
- */
-
- if ([self.returnFields valueForKey:kW3ContactBirthday]) {
- ms = [self getDateAsNumber:kABPersonBirthdayProperty];
- if (ms) {
- [nc setObject:ms forKey:kW3ContactBirthday];
- }
- }
-
- /* Anniversary removed from 12-09-2010 W3C Contacts api spec
- if ([self.returnFields valueForKey:kW3ContactAnniversary]){
- // Anniversary date is stored in a multivalue property
- ABMultiValueRef multi = ABRecordCopyValue(self.record, kABPersonDateProperty);
- if (multi){
- CFStringRef label = nil;
- CFIndex count = ABMultiValueGetCount(multi);
- // see if contains an Anniversary date
- for(CFIndex i=0; i<count; i++){
- label = ABMultiValueCopyLabelAtIndex(multi, i);
- if(label && [(NSString*)label isEqualToString:(NSString*)kABPersonAnniversaryLabel]){
- CFDateRef aDate = ABMultiValueCopyValueAtIndex(multi, i);
- if(aDate){
- [nc setObject: (NSString*)aDate forKey: kW3ContactAnniversary];
- CFRelease(aDate);
- }
- CFRelease(label);
- break;
- }
- }
- CFRelease(multi);
- }
- }*/
-
- if ([self.returnFields valueForKey:kW3ContactNote]) {
- // note
- value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, kABPersonNoteProperty);
- [nc setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactNote];
- }
-
- if ([self.returnFields valueForKey:kW3ContactPhotos]) {
- value = [self extractPhotos];
- [nc setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactPhotos];
- }
-
- /* TimeZone removed from June 16, 2011 Contacts spec
- *
- if ([self.returnFields valueForKey:kW3ContactTimezone]){
- [NSTimeZone resetSystemTimeZone];
- NSTimeZone* currentTZ = [NSTimeZone localTimeZone];
- NSInteger seconds = [currentTZ secondsFromGMT];
- NSString* tz = [NSString stringWithFormat:@"%2d:%02u", seconds/3600, seconds % 3600 ];
- [nc setObject:tz forKey:kW3ContactTimezone];
- }
- */
- // TODO WebURLs
- // [nc setObject:[NSNull null] forKey:kW3ContactUrls];
- // online accounts - not available on iOS
-
- return nc;
-}
-
-- (NSNumber*)getDateAsNumber:(ABPropertyID)datePropId
-{
- NSNumber* msDate = nil;
- NSDate* aDate = nil;
- CFTypeRef cfDate = ABRecordCopyValue(self.record, datePropId);
-
- if (cfDate) {
- aDate = (__bridge NSDate*)cfDate;
- msDate = [NSNumber numberWithDouble:([aDate timeIntervalSince1970] * 1000)];
- CFRelease(cfDate);
- }
- return msDate;
-}
-
-/* Create Dictionary to match JavaScript ContactName object:
- * formatted - ABRecordCopyCompositeName
- * familyName
- * givenName
- * middleName
- * honorificPrefix
- * honorificSuffix
-*/
-
-- (NSObject*)extractName
-{
- NSArray* fields = [self.returnFields objectForKey:kW3ContactName];
-
- if (fields == nil) { // no name fields requested
- return nil;
- }
-
- NSMutableDictionary* newName = [NSMutableDictionary dictionaryWithCapacity:6];
- id value;
-
- for (NSString* i in fields) {
- if ([i isEqualToString:kW3ContactFormattedName]) {
- value = (__bridge_transfer NSString*)ABRecordCopyCompositeName(self.record);
- [newName setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFormattedName];
- } else {
- // W3CtoAB returns NSNumber for AB name properties, get intValue and cast to ABPropertyID)
- value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, (ABPropertyID)[[[CDVContact defaultW3CtoAB] valueForKey:i] intValue]);
- [newName setObject:(value != nil) ? value:[NSNull null] forKey:(NSString*)i];
- }
- }
-
- return newName;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactField object for simple multiValue properties phoneNumbers, emails
- * Input: (NSString*) W3Contact Property name
- * type
- * for phoneNumbers type is one of (work,home,other, mobile, fax, pager)
- * for emails type is one of (work,home, other)
- * value - phone number or email address
- * (bool) primary (not supported on iphone)
- * id
-*/
-- (NSObject*)extractMultiValue:(NSString*)propertyId
-{
- NSArray* fields = [self.returnFields objectForKey:propertyId];
-
- if (fields == nil) {
- return nil;
- }
- ABMultiValueRef multi = nil;
- NSObject* valuesArray = nil;
- NSNumber* propNumber = [[CDVContact defaultW3CtoAB] valueForKey:propertyId];
- ABPropertyID propId = [propNumber intValue];
- multi = ABRecordCopyValue(self.record, propId);
- // multi = ABRecordCopyValue(self.record, (ABPropertyID)[[[Contact defaultW3CtoAB] valueForKey:propertyId] intValue]);
- CFIndex count = multi != nil ? ABMultiValueGetCount(multi) : 0;
- id value;
- if (count) {
- valuesArray = [NSMutableArray arrayWithCapacity:count];
-
- for (CFIndex i = 0; i < count; i++) {
- NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:4];
- if ([fields containsObject:kW3ContactFieldType]) {
- NSString* label = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
- value = [CDVContact convertPropertyLabelToContactType:label];
- [newDict setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFieldType];
- }
- if ([fields containsObject:kW3ContactFieldValue]) {
- value = (__bridge_transfer NSString*)ABMultiValueCopyValueAtIndex(multi, i);
- [newDict setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFieldValue];
- }
- if ([fields containsObject:kW3ContactFieldPrimary]) {
- [newDict setObject:[NSNumber numberWithBool:(BOOL)NO] forKey:kW3ContactFieldPrimary]; // iOS doesn't support primary so set all to false
- }
- // always set id
- value = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
- [newDict setObject:(value != nil) ? value:[NSNull null] forKey:kW3ContactFieldId];
- [(NSMutableArray*)valuesArray addObject : newDict];
- }
- } else {
- valuesArray = [NSNull null];
- }
- if (multi) {
- CFRelease(multi);
- }
-
- return valuesArray;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactAddress object for addresses
- * pref - not supported
- * type - address type
- * formatted - formatted for mailing label (what about localization?)
- * streetAddress
- * locality
- * region;
- * postalCode
- * country
- * id
- *
- * iOS addresses are a MultiValue Properties with label, value=dictionary of address info, and id
- */
-- (NSObject*)extractAddresses
-{
- NSArray* fields = [self.returnFields objectForKey:kW3ContactAddresses];
-
- if (fields == nil) { // no name fields requested
- return nil;
- }
- CFStringRef value;
- NSObject* addresses;
- ABMultiValueRef multi = ABRecordCopyValue(self.record, kABPersonAddressProperty);
- CFIndex count = multi ? ABMultiValueGetCount(multi) : 0;
- if (count) {
- addresses = [NSMutableArray arrayWithCapacity:count];
-
- for (CFIndex i = 0; i < count; i++) {
- NSMutableDictionary* newAddress = [NSMutableDictionary dictionaryWithCapacity:7];
- // if we got this far, at least some address info is being requested.
-
- // Always set id
- id identifier = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
- [newAddress setObject:(identifier != nil) ? identifier:[NSNull null] forKey:kW3ContactFieldId];
- // set the type label
- NSString* label = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
-
- [newAddress setObject:(label != nil) ? (NSObject*)[[CDVContact class] convertPropertyLabelToContactType:label]:[NSNull null] forKey:kW3ContactFieldType];
- // set the pref - iOS doesn't support so set to default of false
- [newAddress setObject:@"false" forKey:kW3ContactFieldPrimary];
- // get dictionary of values for this address
- CFDictionaryRef dict = (CFDictionaryRef)ABMultiValueCopyValueAtIndex(multi, i);
-
- for (id k in fields) {
- bool bFound;
- id key = [[CDVContact defaultW3CtoAB] valueForKey:k];
- if (key && ![k isKindOfClass:[NSNull class]]) {
- bFound = CFDictionaryGetValueIfPresent(dict, (__bridge const void*)key, (void*)&value);
- if (bFound && (value != NULL)) {
- CFRetain(value);
- [newAddress setObject:(__bridge id)value forKey:k];
- CFRelease(value);
- } else {
- [newAddress setObject:[NSNull null] forKey:k];
- }
- } else {
- // was a property that iPhone doesn't support
- [newAddress setObject:[NSNull null] forKey:k];
- }
- }
-
- if ([newAddress count] > 0) { // ?? this will always be true since we set id,label,primary field??
- [(NSMutableArray*)addresses addObject : newAddress];
- }
- CFRelease(dict);
- } // end of loop through addresses
- } else {
- addresses = [NSNull null];
- }
- if (multi) {
- CFRelease(multi);
- }
-
- return addresses;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactField object for ims
- * type one of [aim, gtalk, icq, xmpp, msn, skype, qq, yahoo] needs other as well
- * value
- * (bool) primary
- * id
- *
- * iOS IMs are a MultiValue Properties with label, value=dictionary of IM details (service, username), and id
- */
-- (NSObject*)extractIms
-{
- NSArray* fields = [self.returnFields objectForKey:kW3ContactIms];
-
- if (fields == nil) { // no name fields requested
- return nil;
- }
- NSObject* imArray;
- ABMultiValueRef multi = ABRecordCopyValue(self.record, kABPersonInstantMessageProperty);
- CFIndex count = multi ? ABMultiValueGetCount(multi) : 0;
- if (count) {
- imArray = [NSMutableArray arrayWithCapacity:count];
-
- for (CFIndex i = 0; i < ABMultiValueGetCount(multi); i++) {
- NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:3];
- // iOS has label property (work, home, other) for each IM but W3C contact API doesn't use
- CFDictionaryRef dict = (CFDictionaryRef)ABMultiValueCopyValueAtIndex(multi, i);
- CFStringRef value; // all values should be CFStringRefs / NSString*
- bool bFound;
- if ([fields containsObject:kW3ContactFieldValue]) {
- // value = user name
- bFound = CFDictionaryGetValueIfPresent(dict, kABPersonInstantMessageUsernameKey, (void*)&value);
- if (bFound && (value != NULL)) {
- CFRetain(value);
- [newDict setObject:(__bridge id)value forKey:kW3ContactFieldValue];
- CFRelease(value);
- } else {
- [newDict setObject:[NSNull null] forKey:kW3ContactFieldValue];
- }
- }
- if ([fields containsObject:kW3ContactFieldType]) {
- bFound = CFDictionaryGetValueIfPresent(dict, kABPersonInstantMessageServiceKey, (void*)&value);
- if (bFound && (value != NULL)) {
- CFRetain(value);
- [newDict setObject:(id)[[CDVContact class] convertPropertyLabelToContactType : (__bridge NSString*)value] forKey:kW3ContactFieldType];
- CFRelease(value);
- } else {
- [newDict setObject:[NSNull null] forKey:kW3ContactFieldType];
- }
- }
- // always set ID
- id identifier = [NSNumber numberWithUnsignedInt:ABMultiValueGetIdentifierAtIndex(multi, i)];
- [newDict setObject:(identifier != nil) ? identifier:[NSNull null] forKey:kW3ContactFieldId];
-
- [(NSMutableArray*)imArray addObject : newDict];
- CFRelease(dict);
- }
- } else {
- imArray = [NSNull null];
- }
-
- if (multi) {
- CFRelease(multi);
- }
- return imArray;
-}
-
-/* Create array of Dictionaries to match JavaScript ContactOrganization object
- * pref - not supported in iOS
- * type - not supported in iOS
- * name
- * department
- * title
- */
-
-- (NSObject*)extractOrganizations
-{
- NSArray* fields = [self.returnFields objectForKey:kW3ContactOrganizations];
-
- if (fields == nil) { // no name fields requested
- return nil;
- }
- NSObject* array = nil;
- NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:5];
- id value;
- int validValueCount = 0;
-
- for (id i in fields) {
- id key = [[CDVContact defaultW3CtoAB] valueForKey:i];
- if (key && [key isKindOfClass:[NSNumber class]]) {
- value = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, (ABPropertyID)[[[CDVContact defaultW3CtoAB] valueForKey:i] intValue]);
- if (value != nil) {
- // if there are no organization values we should return null for organization
- // this counter keeps indicates if any organization values have been set
- validValueCount++;
- }
- [newDict setObject:(value != nil) ? value:[NSNull null] forKey:i];
- } else { // not a key iOS supports, set to null
- [newDict setObject:[NSNull null] forKey:i];
- }
- }
-
- if (([newDict count] > 0) && (validValueCount > 0)) {
- // add pref and type
- // they are not supported by iOS and thus these values never change
- [newDict setObject:@"false" forKey:kW3ContactFieldPrimary];
- [newDict setObject:[NSNull null] forKey:kW3ContactFieldType];
- array = [NSMutableArray arrayWithCapacity:1];
- [(NSMutableArray*)array addObject : newDict];
- } else {
- array = [NSNull null];
- }
- return array;
-}
-
-// W3C Contacts expects an array of photos. Can return photos in more than one format, currently
-// just returning the default format
-// Save the photo data into tmp directory and return FileURI - temp directory is deleted upon application exit
-- (NSObject*)extractPhotos
-{
- NSMutableArray* photos = nil;
-
- if (ABPersonHasImageData(self.record)) {
- CFDataRef photoData = ABPersonCopyImageData(self.record);
- NSData* data = (__bridge NSData*)photoData;
- // write to temp directory and store URI in photos array
- // get the temp directory path
- NSString* docsPath = [NSTemporaryDirectory()stringByStandardizingPath];
- NSError* err = nil;
- NSString* filePath = [NSString stringWithFormat:@"%@/photo_XXXXX", docsPath];
- char template[filePath.length + 1];
- strcpy(template, [filePath cStringUsingEncoding:NSASCIIStringEncoding]);
- mkstemp(template);
- filePath = [[NSFileManager defaultManager]
- stringWithFileSystemRepresentation:template
- length:strlen(template)];
-
- // save file
- if ([data writeToFile:filePath options:NSAtomicWrite error:&err]) {
- photos = [NSMutableArray arrayWithCapacity:1];
- NSMutableDictionary* newDict = [NSMutableDictionary dictionaryWithCapacity:2];
- [newDict setObject:filePath forKey:kW3ContactFieldValue];
- [newDict setObject:@"url" forKey:kW3ContactFieldType];
- [newDict setObject:@"false" forKey:kW3ContactFieldPrimary];
- [photos addObject:newDict];
- }
-
- CFRelease(photoData);
- }
- return photos;
-}
-
-/**
- * given an array of W3C Contact field names, create a dictionary of field names to extract
- * if field name represents an object, return all properties for that object: "name" - returns all properties in ContactName
- * if field name is an explicit property, return only those properties: "name.givenName - returns a ContactName with only ContactName.givenName
- * if field contains ONLY ["*"] return all fields
- * dictionary format:
- * key is W3Contact #define
- * value is NSMutableArray* for complex keys: name,addresses,organizations, phone, emails, ims
- * value is [NSNull null] for simple keys
-*/
-+ (NSDictionary*)calcReturnFields:(NSArray*)fieldsArray // NSLog(@"getting self.returnFields");
-{
- NSMutableDictionary* d = [NSMutableDictionary dictionaryWithCapacity:1];
-
- if ((fieldsArray != nil) && [fieldsArray isKindOfClass:[NSArray class]]) {
- if (([fieldsArray count] == 1) && [[fieldsArray objectAtIndex:0] isEqualToString:@"*"]) {
- return [CDVContact defaultFields]; // return all fields
- }
-
- for (id i in fieldsArray) {
- NSMutableArray* keys = nil;
- NSString* fieldStr = nil;
- if ([i isKindOfClass:[NSNumber class]]) {
- fieldStr = [i stringValue];
- } else {
- fieldStr = i;
- }
-
- // see if this is specific property request in object - object.property
- NSArray* parts = [fieldStr componentsSeparatedByString:@"."]; // returns original string if no separator found
- NSString* name = [parts objectAtIndex:0];
- NSString* property = nil;
- if ([parts count] > 1) {
- property = [parts objectAtIndex:1];
- }
- // see if this is a complex field by looking for its array of properties in objectAndProperties dictionary
- id fields = [[CDVContact defaultObjectAndProperties] objectForKey:name];
-
- // if find complex name (name,addresses,organizations, phone, emails, ims) in fields, add name as key
- // with array of associated properties as the value
- if ((fields != nil) && (property == nil)) { // request was for full object
- keys = [NSMutableArray arrayWithArray:fields];
- if (keys != nil) {
- [d setObject:keys forKey:name]; // will replace if prop array already exists
- }
- } else if ((fields != nil) && (property != nil)) {
- // found an individual property request in form of name.property
- // verify is real property name by using it as key in W3CtoAB
- id abEquiv = [[CDVContact defaultW3CtoAB] objectForKey:property];
- if (abEquiv || [[CDVContact defaultW3CtoNull] containsObject:property]) {
- // if existing array add to it
- if ((keys = [d objectForKey:name]) != nil) {
- [keys addObject:property];
- } else {
- keys = [NSMutableArray arrayWithObject:property];
- [d setObject:keys forKey:name];
- }
- } else {
- NSLog(@"Contacts.find -- request for invalid property ignored: %@.%@", name, property);
- }
- } else { // is an individual property, verify is real property name by using it as key in W3CtoAB
- id valid = [[CDVContact defaultW3CtoAB] objectForKey:name];
- if (valid || [[CDVContact defaultW3CtoNull] containsObject:name]) {
- [d setObject:[NSNull null] forKey:name];
- }
- }
- }
- }
- if ([d count] == 0) {
- // no array or nothing in the array. W3C spec says to return nothing
- return nil; // [Contact defaultFields];
- }
- return d;
-}
-
-/*
- * Search for the specified value in each of the fields specified in the searchFields dictionary.
- * NSString* value - the string value to search for (need clarification from W3C on how to search for dates)
- * NSDictionary* searchFields - a dictionary created via calcReturnFields where the key is the top level W3C
- * object and the object is the array of specific fields within that object or null if it is a single property
- * RETURNS
- * YES as soon as a match is found in any of the fields
- * NO - the specified value does not exist in any of the fields in this contact
- *
- * Note: I'm not a fan of returning in the middle of methods but have done it some in this method in order to
- * keep the code simpler. bgibson
- */
-- (BOOL)foundValue:(NSString*)testValue inFields:(NSDictionary*)searchFields
-{
- BOOL bFound = NO;
-
- if ((testValue == nil) || ![testValue isKindOfClass:[NSString class]] || ([testValue length] == 0)) {
- // nothing to find so return NO
- return NO;
- }
- NSInteger valueAsInt = [testValue integerValue];
-
- // per W3C spec, always include id in search
- int recordId = ABRecordGetRecordID(self.record);
- if (valueAsInt && (recordId == valueAsInt)) {
- return YES;
- }
-
- if (searchFields == nil) {
- // no fields to search
- return NO;
- }
-
- if ([searchFields valueForKey:kW3ContactNickname]) {
- bFound = [self testStringValue:testValue forW3CProperty:kW3ContactNickname];
- if (bFound == YES) {
- return bFound;
- }
- }
-
- if ([searchFields valueForKeyIsArray:kW3ContactName]) {
- // test name fields. All are string properties obtained via ABRecordCopyValue except kW3ContactFormattedName
- NSArray* fields = [searchFields valueForKey:kW3ContactName];
-
- for (NSString* testItem in fields) {
- if ([testItem isEqualToString:kW3ContactFormattedName]) {
- NSString* propValue = (__bridge_transfer NSString*)ABRecordCopyCompositeName(self.record);
- if ((propValue != nil) && ([propValue length] > 0)) {
- NSRange range = [propValue rangeOfString:testValue options:NSCaseInsensitiveSearch];
- bFound = (range.location != NSNotFound);
- propValue = nil;
- }
- } else {
- bFound = [self testStringValue:testValue forW3CProperty:testItem];
- }
-
- if (bFound) {
- break;
- }
- }
- }
- if (!bFound && [searchFields valueForKeyIsArray:kW3ContactPhoneNumbers]) {
- bFound = [self searchContactFields:(NSArray*)[searchFields valueForKey:kW3ContactPhoneNumbers]
- forMVStringProperty:kABPersonPhoneProperty withValue:testValue];
- }
- if (!bFound && [searchFields valueForKeyIsArray:kW3ContactEmails]) {
- bFound = [self searchContactFields:(NSArray*)[searchFields valueForKey:kW3ContactEmails]
- forMVStringProperty:kABPersonEmailProperty withValue:testValue];
- }
-
- if (!bFound && [searchFields valueForKeyIsArray:kW3ContactAddresses]) {
- bFound = [self searchContactFields:[searchFields valueForKey:kW3ContactAddresses]
- forMVDictionaryProperty:kABPersonAddressProperty withValue:testValue];
- }
-
- if (!bFound && [searchFields valueForKeyIsArray:kW3ContactIms]) {
- bFound = [self searchContactFields:[searchFields valueForKey:kW3ContactIms]
- forMVDictionaryProperty:kABPersonInstantMessageProperty withValue:testValue];
- }
-
- if (!bFound && [searchFields valueForKeyIsArray:kW3ContactOrganizations]) {
- NSArray* fields = [searchFields valueForKey:kW3ContactOrganizations];
-
- for (NSString* testItem in fields) {
- bFound = [self testStringValue:testValue forW3CProperty:testItem];
- if (bFound == YES) {
- break;
- }
- }
- }
- if (!bFound && [searchFields valueForKey:kW3ContactNote]) {
- bFound = [self testStringValue:testValue forW3CProperty:kW3ContactNote];
- }
-
- // if searching for a date field is requested, get the date field as a localized string then look for match against testValue in date string
- // searching for photos is not supported
- if (!bFound && [searchFields valueForKey:kW3ContactBirthday]) {
- bFound = [self testDateValue:testValue forW3CProperty:kW3ContactBirthday];
- }
- if (!bFound && [searchFields valueForKeyIsArray:kW3ContactUrls]) {
- bFound = [self searchContactFields:(NSArray*)[searchFields valueForKey:kW3ContactUrls]
- forMVStringProperty:kABPersonURLProperty withValue:testValue];
- }
-
- return bFound;
-}
-
-/*
- * Test for the existence of a given string within the value of a ABPersonRecord string property based on the W3c property name.
- *
- * IN:
- * NSString* testValue - the value to find - search is case insensitive
- * NSString* property - the W3c property string
- * OUT:
- * BOOL YES if the given string was found within the property value
- * NO if the testValue was not found, W3C property string was invalid or the AddressBook property was not a string
- */
-- (BOOL)testStringValue:(NSString*)testValue forW3CProperty:(NSString*)property
-{
- BOOL bFound = NO;
-
- if ([[CDVContact defaultW3CtoAB] valueForKeyIsNumber:property]) {
- ABPropertyID propId = [[[CDVContact defaultW3CtoAB] objectForKey:property] intValue];
- if (ABPersonGetTypeOfProperty(propId) == kABStringPropertyType) {
- NSString* propValue = (__bridge_transfer NSString*)ABRecordCopyValue(self.record, propId);
- if ((propValue != nil) && ([propValue length] > 0)) {
- NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testValue];
- bFound = [containPred evaluateWithObject:propValue];
- // NSRange range = [propValue rangeOfString:testValue options: NSCaseInsensitiveSearch];
- // bFound = (range.location != NSNotFound);
- }
- }
- }
- return bFound;
-}
-
-/*
- * Test for the existence of a given Date string within the value of a ABPersonRecord datetime property based on the W3c property name.
- *
- * IN:
- * NSString* testValue - the value to find - search is case insensitive
- * NSString* property - the W3c property string
- * OUT:
- * BOOL YES if the given string was found within the localized date string value
- * NO if the testValue was not found, W3C property string was invalid or the AddressBook property was not a DateTime
- */
-- (BOOL)testDateValue:(NSString*)testValue forW3CProperty:(NSString*)property
-{
- BOOL bFound = NO;
-
- if ([[CDVContact defaultW3CtoAB] valueForKeyIsNumber:property]) {
- ABPropertyID propId = [[[CDVContact defaultW3CtoAB] objectForKey:property] intValue];
- if (ABPersonGetTypeOfProperty(propId) == kABDateTimePropertyType) {
- NSDate* date = (__bridge_transfer NSDate*)ABRecordCopyValue(self.record, propId);
- if (date != nil) {
- NSString* dateString = [date descriptionWithLocale:[NSLocale currentLocale]];
- NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testValue];
- bFound = [containPred evaluateWithObject:dateString];
- }
- }
- }
- return bFound;
-}
-
-/*
- * Search the specified fields within an AddressBook multivalue string property for the specified test value.
- * Used for phoneNumbers, emails and urls.
- * IN:
- * NSArray* fields - the fields to search for within the multistring property (value and/or type)
- * ABPropertyID - the property to search
- * NSString* testValue - the value to search for. Will convert between W3C types and AB types. Will only
- * search for types if the testValue is a valid ContactField type.
- * OUT:
- * YES if the test value was found in one of the specified fields
- * NO if the test value was not found
- */
-- (BOOL)searchContactFields:(NSArray*)fields forMVStringProperty:(ABPropertyID)propId withValue:testValue
-{
- BOOL bFound = NO;
-
- for (NSString* type in fields) {
- NSString* testString = nil;
- if ([type isEqualToString:kW3ContactFieldType]) {
- if ([CDVContact isValidW3ContactType:testValue]) {
- // only search types if the filter string is a valid ContactField.type
- testString = (NSString*)[CDVContact convertContactTypeToPropertyLabel:testValue];
- }
- } else {
- testString = testValue;
- }
-
- if (testString != nil) {
- bFound = [self testMultiValueStrings:testString forProperty:propId ofType:type];
- }
- if (bFound == YES) {
- break;
- }
- }
-
- return bFound;
-}
-
-/*
- * Searches a multiString value of the specified type for the specified test value.
- *
- * IN:
- * NSString* testValue - the value to test for
- * ABPropertyID propId - the property id of the multivalue property to search
- * NSString* type - the W3C contact type to search for (value or type)
- * OUT:
- * YES is the test value was found
- * NO if the test value was not found
- */
-- (BOOL)testMultiValueStrings:(NSString*)testValue forProperty:(ABPropertyID)propId ofType:(NSString*)type
-{
- BOOL bFound = NO;
-
- if (ABPersonGetTypeOfProperty(propId) == kABMultiStringPropertyType) {
- NSArray* valueArray = nil;
- if ([type isEqualToString:kW3ContactFieldType]) {
- valueArray = [self labelsForProperty:propId inRecord:self.record];
- } else if ([type isEqualToString:kW3ContactFieldValue]) {
- valueArray = [self valuesForProperty:propId inRecord:self.record];
- }
- if (valueArray) {
- NSString* valuesAsString = [valueArray componentsJoinedByString:@" "];
- NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testValue];
- bFound = [containPred evaluateWithObject:valuesAsString];
- }
- }
- return bFound;
-}
-
-/*
- * Returns the array of values for a multivalue string property of the specified property id
- */
-- (__autoreleasing NSArray*)valuesForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord
-{
- ABMultiValueRef multi = ABRecordCopyValue(aRecord, propId);
- NSArray* values = (__bridge_transfer NSArray*)ABMultiValueCopyArrayOfAllValues(multi);
-
- CFRelease(multi);
- return values;
-}
-
-/*
- * Returns the array of labels for a multivalue string property of the specified property id
- */
-- (NSArray*)labelsForProperty:(ABPropertyID)propId inRecord:(ABRecordRef)aRecord
-{
- ABMultiValueRef multi = ABRecordCopyValue(aRecord, propId);
- CFIndex count = ABMultiValueGetCount(multi);
- NSMutableArray* labels = [NSMutableArray arrayWithCapacity:count];
-
- for (int i = 0; i < count; i++) {
- NSString* label = (__bridge_transfer NSString*)ABMultiValueCopyLabelAtIndex(multi, i);
- if (label) {
- [labels addObject:label];
- }
- }
-
- CFRelease(multi);
- return labels;
-}
-
-/* search for values within MultiValue Dictionary properties Address or IM property
- * IN:
- * (NSArray*) fields - the array of W3C field names to search within
- * (ABPropertyID) propId - the AddressBook property that returns a multivalue dictionary
- * (NSString*) testValue - the string to search for within the specified fields
- *
- */
-- (BOOL)searchContactFields:(NSArray*)fields forMVDictionaryProperty:(ABPropertyID)propId withValue:(NSString*)testValue
-{
- BOOL bFound = NO;
-
- NSArray* values = [self valuesForProperty:propId inRecord:self.record]; // array of dictionaries (as CFDictionaryRef)
- NSUInteger dictCount = [values count];
-
- // for ims dictionary contains with service (w3C type) and username (W3c value)
- // for addresses dictionary contains street, city, state, zip, country
- for (int i = 0; i < dictCount; i++) {
- CFDictionaryRef dict = (__bridge CFDictionaryRef)[values objectAtIndex:i];
-
- for (NSString* member in fields) {
- NSString* abKey = [[CDVContact defaultW3CtoAB] valueForKey:member]; // im and address fields are all strings
- CFStringRef abValue = nil;
- if (abKey) {
- NSString* testString = nil;
- if ([member isEqualToString:kW3ContactImType]) {
- if ([CDVContact isValidW3ContactType:testValue]) {
- // only search service/types if the filter string is a valid ContactField.type
- testString = (NSString*)[CDVContact convertContactTypeToPropertyLabel:testValue];
- }
- } else {
- testString = testValue;
- }
- if (testString != nil) {
- BOOL bExists = CFDictionaryGetValueIfPresent(dict, (__bridge const void*)abKey, (void*)&abValue);
- if (bExists) {
- CFRetain(abValue);
- NSPredicate* containPred = [NSPredicate predicateWithFormat:@"SELF contains[cd] %@", testString];
- bFound = [containPred evaluateWithObject:(__bridge id)abValue];
- CFRelease(abValue);
- }
- }
- }
- if (bFound == YES) {
- break;
- }
- } // end of for each member in fields
-
- if (bFound == YES) {
- break;
- }
- } // end of for each dictionary
-
- return bFound;
-}
-
-@end
diff --git a/src/ios/CDVContacts.h b/src/ios/CDVContacts.h
deleted file mode 100644
index e3deb21..0000000
--- a/src/ios/CDVContacts.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import <Foundation/Foundation.h>
-#import <AddressBook/ABAddressBook.h>
-#import <AddressBookUI/AddressBookUI.h>
-#import <Cordova/CDVPlugin.h>
-#import "CDVContact.h"
-
-@interface CDVContacts : CDVPlugin <ABNewPersonViewControllerDelegate,
- ABPersonViewControllerDelegate,
- ABPeoplePickerNavigationControllerDelegate
- >
-{
- ABAddressBookRef addressBook;
-}
-
-/*
- * newContact - create a new contact via the GUI
- *
- * arguments:
- * 1: successCallback: this is the javascript function that will be called with the newly created contactId
- */
-- (void)newContact:(CDVInvokedUrlCommand*)command;
-
-/*
- * displayContact - IN PROGRESS
- *
- * arguments:
- * 1: recordID of the contact to display in the iPhone contact display
- * 2: successCallback - currently not used
- * 3: error callback
- * options:
- * allowsEditing: set to true to allow the user to edit the contact - currently not supported
- */
-- (void)displayContact:(CDVInvokedUrlCommand*)command;
-
-/*
- * chooseContact
- *
- * arguments:
- * 1: this is the javascript function that will be called with the contact data as a JSON object (as the first param)
- * options:
- * allowsEditing: set to true to not choose the contact, but to edit it in the iPhone contact editor
- */
-- (void)chooseContact:(CDVInvokedUrlCommand*)command;
-
-- (void)newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person;
-- (BOOL)personViewController:(ABPersonViewController*)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person
- property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue;
-
-/*
- * search - searches for contacts. Only person records are currently supported.
- *
- * arguments:
- * 1: successcallback - this is the javascript function that will be called with the array of found contacts
- * 2: errorCallback - optional javascript function to be called in the event of an error with an error code.
- * options: dictionary containing ContactFields and ContactFindOptions
- * fields - ContactFields array
- * findOptions - ContactFindOptions object as dictionary
- *
- */
-- (void)search:(CDVInvokedUrlCommand*)command;
-
-/*
- * save - saves a new contact or updates and existing contact
- *
- * arguments:
- * 1: success callback - this is the javascript function that will be called with the JSON representation of the saved contact
- * search calls a fixed navigator.service.contacts._findCallback which then calls the success callback stored before making the call into obj-c
- */
-- (void)save:(CDVInvokedUrlCommand*)command;
-
-/*
- * remove - removes a contact from the address book
- *
- * arguments:
- * 1: 1: successcallback - this is the javascript function that will be called with a (now) empty contact object
- *
- * options: dictionary containing Contact object to remove
- * contact - Contact object as dictionary
- */
-- (void)remove:(CDVInvokedUrlCommand*)command;
-
-// - (void) dealloc;
-
-@end
-
-@interface CDVContactsPicker : ABPeoplePickerNavigationController
-{
- BOOL allowsEditing;
- NSString* callbackId;
- NSDictionary* options;
- NSDictionary* pickedContactDictionary;
-}
-
-@property BOOL allowsEditing;
-@property (copy) NSString* callbackId;
-@property (nonatomic, strong) NSDictionary* options;
-@property (nonatomic, strong) NSDictionary* pickedContactDictionary;
-
-@end
-
-@interface CDVNewContactsController : ABNewPersonViewController
-{
- NSString* callbackId;
-}
-@property (copy) NSString* callbackId;
-@end
-
-/* ABPersonViewController does not have any UI to dismiss. Adding navigationItems to it does not work properly, the navigationItems are lost when the app goes into the background.
- The solution was to create an empty NavController in front of the ABPersonViewController. This
- causes the ABPersonViewController to have a back button. By subclassing the ABPersonViewController,
- we can override viewWillDisappear and take down the entire NavigationController at that time.
- */
-@interface CDVDisplayContactViewController : ABPersonViewController
-{}
-@property (nonatomic, strong) CDVPlugin* contactsPlugin;
-
-@end
-@interface CDVAddressBookAccessError : NSObject
-{}
-@property (assign) CDVContactError errorCode;
-- (CDVAddressBookAccessError*)initWithCode:(CDVContactError)code;
-@end
-
-typedef void (^ CDVAddressBookWorkerBlock)(
- ABAddressBookRef addressBook,
- CDVAddressBookAccessError* error
- );
-@interface CDVAddressBookHelper : NSObject
-{}
-
-- (void)createAddressBook:(CDVAddressBookWorkerBlock)workerBlock;
-@end
diff --git a/src/ios/CDVContacts.m b/src/ios/CDVContacts.m
deleted file mode 100644
index 56ca2ab..0000000
--- a/src/ios/CDVContacts.m
+++ /dev/null
@@ -1,604 +0,0 @@
-/*
- Licensed to the Apache Software Foundation (ASF) under one
- or more contributor license agreements. See the NOTICE file
- distributed with this work for additional information
- regarding copyright ownership. The ASF licenses this file
- to you under the Apache License, Version 2.0 (the
- "License"); you may not use this file except in compliance
- with the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing,
- software distributed under the License is distributed on an
- "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- KIND, either express or implied. See the License for the
- specific language governing permissions and limitations
- under the License.
- */
-
-#import "CDVContacts.h"
-#import <UIKit/UIKit.h>
-#import <Cordova/NSArray+Comparisons.h>
-#import <Cordova/NSDictionary+Extensions.h>
-//#import "CDVNotification.h"
-
-@implementation CDVContactsPicker
-
-@synthesize allowsEditing;
-@synthesize callbackId;
-@synthesize options;
-@synthesize pickedContactDictionary;
-
-@end
-@implementation CDVNewContactsController
-
-@synthesize callbackId;
-
-@end
-
-@implementation CDVContacts
-
-// no longer used since code gets AddressBook for each operation.
-// If address book changes during save or remove operation, may get error but not much we can do about it
-// If address book changes during UI creation, display or edit, we don't control any saves so no need for callback
-
-/*void addressBookChanged(ABAddressBookRef addressBook, CFDictionaryRef info, void* context)
-{
- // note that this function is only called when another AddressBook instance modifies
- // the address book, not the current one. For example, through an OTA MobileMe sync
- Contacts* contacts = (Contacts*)context;
- [contacts addressBookDirty];
- }*/
-
-- (CDVPlugin*)initWithWebView:(UIWebView*)theWebView
-{
- self = (CDVContacts*)[super initWithWebView:(UIWebView*)theWebView];
-
- /*if (self) {
- addressBook = ABAddressBookCreate();
- ABAddressBookRegisterExternalChangeCallback(addressBook, addressBookChanged, self);
- }*/
-
- return self;
-}
-
-// overridden to clean up Contact statics
-- (void)onAppTerminate
-{
- // NSLog(@"Contacts::onAppTerminate");
-}
-
-// iPhone only method to create a new contact through the GUI
-- (void)newContact:(CDVInvokedUrlCommand*)command
-{
- NSString* callbackId = command.callbackId;
-
- CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
- CDVContacts* __weak weakSelf = self; // play it safe to avoid retain cycles
-
- [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
- if (addrBook == NULL) {
- // permission was denied or other error just return (no error callback)
- return;
- }
- CDVNewContactsController* npController = [[CDVNewContactsController alloc] init];
- npController.addressBook = addrBook; // a CF retaining assign
- CFRelease(addrBook);
-
- npController.newPersonViewDelegate = self;
- npController.callbackId = callbackId;
-
- UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:npController];
-
- SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
- if ([weakSelf.viewController respondsToSelector:selector]) {
- [weakSelf.viewController presentViewController:navController animated:YES completion:nil];
- } else {
- // deprecated as of iOS >= 6.0
- [weakSelf.viewController presentModalViewController:navController animated:YES];
- }
- }];
-}
-
-- (void)newPersonViewController:(ABNewPersonViewController*)newPersonViewController didCompleteWithNewPerson:(ABRecordRef)person
-{
- ABRecordID recordId = kABRecordInvalidID;
- CDVNewContactsController* newCP = (CDVNewContactsController*)newPersonViewController;
- NSString* callbackId = newCP.callbackId;
-
- if (person != NULL) {
- // return the contact id
- recordId = ABRecordGetRecordID(person);
- }
-
- if ([newPersonViewController respondsToSelector:@selector(presentingViewController)]) {
- [[newPersonViewController presentingViewController] dismissViewControllerAnimated:YES completion:nil];
- } else {
- [[newPersonViewController parentViewController] dismissModalViewControllerAnimated:YES];
- }
-
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsInt:recordId];
- [self.commandDelegate sendPluginResult:result callbackId:callbackId];
-}
-
-- (void)displayContact:(CDVInvokedUrlCommand*)command
-{
- NSString* callbackId = command.callbackId;
- ABRecordID recordID = [[command.arguments objectAtIndex:0] intValue];
- NSDictionary* options = [command.arguments objectAtIndex:1 withDefault:[NSNull null]];
- bool bEdit = [options isKindOfClass:[NSNull class]] ? false : [options existsValue:@"true" forKey:@"allowsEditing"];
-
- CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
- CDVContacts* __weak weakSelf = self; // play it safe to avoid retain cycles
-
- [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
- if (addrBook == NULL) {
- // permission was denied or other error - return error
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? (int)errCode.errorCode:UNKNOWN_ERROR];
- [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
- return;
- }
- ABRecordRef rec = ABAddressBookGetPersonWithRecordID(addrBook, recordID);
-
- if (rec) {
- CDVDisplayContactViewController* personController = [[CDVDisplayContactViewController alloc] init];
- personController.displayedPerson = rec;
- personController.personViewDelegate = self;
- personController.allowsEditing = NO;
-
- // create this so DisplayContactViewController will have a "back" button.
- UIViewController* parentController = [[UIViewController alloc] init];
- UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:parentController];
-
- [navController pushViewController:personController animated:YES];
-
- SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
- if ([self.viewController respondsToSelector:selector]) {
- [self.viewController presentViewController:navController animated:YES completion:nil];
- } else {
- // deprecated as of iOS >= 6.0
- [self.viewController presentModalViewController:navController animated:YES];
- }
-
- if (bEdit) {
- // create the editing controller and push it onto the stack
- ABPersonViewController* editPersonController = [[ABPersonViewController alloc] init];
- editPersonController.displayedPerson = rec;
- editPersonController.personViewDelegate = self;
- editPersonController.allowsEditing = YES;
- [navController pushViewController:editPersonController animated:YES];
- }
- } else {
- // no record, return error
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:UNKNOWN_ERROR];
- [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
- }
- CFRelease(addrBook);
- }];
-}
-
-- (BOOL)personViewController:(ABPersonViewController*)personViewController shouldPerformDefaultActionForPerson:(ABRecordRef)person
- property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifierForValue
-{
- return YES;
-}
-
-- (void)chooseContact:(CDVInvokedUrlCommand*)command
-{
- NSString* callbackId = command.callbackId;
- NSDictionary* options = [command.arguments objectAtIndex:0 withDefault:[NSNull null]];
-
- CDVContactsPicker* pickerController = [[CDVContactsPicker alloc] init];
-
- pickerController.peoplePickerDelegate = self;
- pickerController.callbackId = callbackId;
- pickerController.options = options;
- pickerController.pickedContactDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:kABRecordInvalidID], kW3ContactId, nil];
- id allowsEditingValue = [options valueForKey:@"allowsEditing"];
- BOOL allowsEditing = NO;
- if ([allowsEditingValue isKindOfClass:[NSNumber class]]) {
- allowsEditing = [(NSNumber*)allowsEditingValue boolValue];
- }
- pickerController.allowsEditing = allowsEditing;
-
- SEL selector = NSSelectorFromString(@"presentViewController:animated:completion:");
- if ([self.viewController respondsToSelector:selector]) {
- [self.viewController presentViewController:pickerController animated:YES completion:nil];
- } else {
- // deprecated as of iOS >= 6.0
- [self.viewController presentModalViewController:pickerController animated:YES];
- }
-}
-
-- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
- shouldContinueAfterSelectingPerson:(ABRecordRef)person
-{
- CDVContactsPicker* picker = (CDVContactsPicker*)peoplePicker;
- NSNumber* pickedId = [NSNumber numberWithInt:ABRecordGetRecordID(person)];
-
- if (picker.allowsEditing) {
- ABPersonViewController* personController = [[ABPersonViewController alloc] init];
- personController.displayedPerson = person;
- personController.personViewDelegate = self;
- personController.allowsEditing = picker.allowsEditing;
- // store id so can get info in peoplePickerNavigationControllerDidCancel
- picker.pickedContactDictionary = [NSDictionary dictionaryWithObjectsAndKeys:pickedId, kW3ContactId, nil];
-
- [peoplePicker pushViewController:personController animated:YES];
- } else {
- // Retrieve and return pickedContact information
- CDVContact* pickedContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)person];
- NSArray* fields = [picker.options objectForKey:@"fields"];
- NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
- picker.pickedContactDictionary = [pickedContact toDictionary:returnFields];
-
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:picker.pickedContactDictionary];
- [self.commandDelegate sendPluginResult:result callbackId:picker.callbackId];
-
- if ([picker respondsToSelector:@selector(presentingViewController)]) {
- [[picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
- } else {
- [[picker parentViewController] dismissModalViewControllerAnimated:YES];
- }
- }
- return NO;
-}
-
-- (BOOL)peoplePickerNavigationController:(ABPeoplePickerNavigationController*)peoplePicker
- shouldContinueAfterSelectingPerson:(ABRecordRef)person property:(ABPropertyID)property identifier:(ABMultiValueIdentifier)identifier
-{
- return YES;
-}
-
-- (void)peoplePickerNavigationControllerDidCancel:(ABPeoplePickerNavigationController*)peoplePicker
-{
- // return contactId or invalid if none picked
- CDVContactsPicker* picker = (CDVContactsPicker*)peoplePicker;
-
- if (picker.allowsEditing) {
- // get the info after possible edit
- // if we got this far, user has already approved/ disapproved addressBook access
- ABAddressBookRef addrBook = nil;
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
- if (&ABAddressBookCreateWithOptions != NULL) {
- addrBook = ABAddressBookCreateWithOptions(NULL, NULL);
- } else
-#endif
- {
- // iOS 4 & 5
- addrBook = ABAddressBookCreate();
- }
- ABRecordRef person = ABAddressBookGetPersonWithRecordID(addrBook, (int)[[picker.pickedContactDictionary objectForKey:kW3ContactId] integerValue]);
- if (person) {
- CDVContact* pickedContact = [[CDVContact alloc] initFromABRecord:(ABRecordRef)person];
- NSArray* fields = [picker.options objectForKey:@"fields"];
- NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
- picker.pickedContactDictionary = [pickedContact toDictionary:returnFields];
- }
- CFRelease(addrBook);
- }
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:picker.pickedContactDictionary];
- [self.commandDelegate sendPluginResult:result callbackId:picker.callbackId];
-
- if ([peoplePicker respondsToSelector:@selector(presentingViewController)]) {
- [[peoplePicker presentingViewController] dismissViewControllerAnimated:YES completion:nil];
- } else {
- [[peoplePicker parentViewController] dismissModalViewControllerAnimated:YES];
- }
-}
-
-- (void)search:(CDVInvokedUrlCommand*)command
-{
- NSString* callbackId = command.callbackId;
- NSArray* fields = [command.arguments objectAtIndex:0];
- NSDictionary* findOptions = [command.arguments objectAtIndex:1 withDefault:[NSNull null]];
-
- [self.commandDelegate runInBackground:^{
- // from Apple: Important You must ensure that an instance of ABAddressBookRef is used by only one thread.
- // which is why address book is created within the dispatch queue.
- // more details here: http: //blog.byadrian.net/2012/05/05/ios-addressbook-framework-and-gcd/
- CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
- CDVContacts* __weak weakSelf = self; // play it safe to avoid retain cycles
- // it gets uglier, block within block.....
- [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errCode) {
- if (addrBook == NULL) {
- // permission was denied or other error - return error
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageToErrorObject:errCode ? (int)errCode.errorCode:UNKNOWN_ERROR];
- [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
- return;
- }
-
- NSArray* foundRecords = nil;
- // get the findOptions values
- BOOL multiple = NO; // default is false
- NSString* filter = nil;
- if (![findOptions isKindOfClass:[NSNull class]]) {
- id value = nil;
- filter = (NSString*)[findOptions objectForKey:@"filter"];
- value = [findOptions objectForKey:@"multiple"];
- if ([value isKindOfClass:[NSNumber class]]) {
- // multiple is a boolean that will come through as an NSNumber
- multiple = [(NSNumber*)value boolValue];
- // NSLog(@"multiple is: %d", multiple);
- }
- }
-
- NSDictionary* returnFields = [[CDVContact class] calcReturnFields:fields];
-
- NSMutableArray* matches = nil;
- if (!filter || [filter isEqualToString:@""]) {
- // get all records
- foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook);
- if (foundRecords && ([foundRecords count] > 0)) {
- // create Contacts and put into matches array
- // doesn't make sense to ask for all records when multiple == NO but better check
- int xferCount = multiple == YES ? (int)[foundRecords count] : 1;
- matches = [NSMutableArray arrayWithCapacity:xferCount];
-
- for (int k = 0; k < xferCount; k++) {
- CDVContact* xferContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:k]];
- [matches addObject:xferContact];
- xferContact = nil;
- }
- }
- } else {
- foundRecords = (__bridge_transfer NSArray*)ABAddressBookCopyArrayOfAllPeople(addrBook);
- matches = [NSMutableArray arrayWithCapacity:1];
- BOOL bFound = NO;
- int testCount = (int)[foundRecords count];
-
- for (int j = 0; j < testCount; j++) {
- CDVContact* testContact = [[CDVContact alloc] initFromABRecord:(__bridge ABRecordRef)[foundRecords objectAtIndex:j]];
- if (testContact) {
- bFound = [testContact foundValue:filter inFields:returnFields];
- if (bFound) {
- [matches addObject:testContact];
- }
- testContact = nil;
- }
- }
- }
- NSMutableArray* returnContacts = [NSMutableArray arrayWithCapacity:1];
-
- if ((matches != nil) && ([matches count] > 0)) {
- // convert to JS Contacts format and return in callback
- // - returnFields determines what properties to return
- @autoreleasepool {
- int count = multiple == YES ? (int)[matches count] : 1;
-
- for (int i = 0; i < count; i++) {
- CDVContact* newContact = [matches objectAtIndex:i];
- NSDictionary* aContact = [newContact toDictionary:returnFields];
- [returnContacts addObject:aContact];
- }
- }
- }
- // return found contacts (array is empty if no contacts found)
- CDVPluginResult* result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsArray:returnContacts];
- [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
- // NSLog(@"findCallback string: %@", jsString);
-
- if (addrBook) {
- CFRelease(addrBook);
- }
- }];
- }]; // end of workQueue block
-
- return;
-}
-
-- (void)save:(CDVInvokedUrlCommand*)command
-{
- NSString* callbackId = command.callbackId;
- NSDictionary* contactDict = [command.arguments objectAtIndex:0];
-
- [self.commandDelegate runInBackground:^{
- CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
- CDVContacts* __weak weakSelf = self; // play it safe to avoid retain cycles
-
- [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errorCode) {
- CDVPluginResult* result = nil;
- if (addrBook == NULL) {
- // permission was denied or other error - return error
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode ? (int)errorCode.errorCode:UNKNOWN_ERROR];
- [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
- return;
- }
-
- bool bIsError = FALSE, bSuccess = FALSE;
- BOOL bUpdate = NO;
- CDVContactError errCode = UNKNOWN_ERROR;
- CFErrorRef error;
- NSNumber* cId = [contactDict valueForKey:kW3ContactId];
- CDVContact* aContact = nil;
- ABRecordRef rec = nil;
- if (cId && ![cId isKindOfClass:[NSNull class]]) {
- rec = ABAddressBookGetPersonWithRecordID(addrBook, [cId intValue]);
- if (rec) {
- aContact = [[CDVContact alloc] initFromABRecord:rec];
- bUpdate = YES;
- }
- }
- if (!aContact) {
- aContact = [[CDVContact alloc] init];
- }
-
- bSuccess = [aContact setFromContactDict:contactDict asUpdate:bUpdate];
- if (bSuccess) {
- if (!bUpdate) {
- bSuccess = ABAddressBookAddRecord(addrBook, [aContact record], &error);
- }
- if (bSuccess) {
- bSuccess = ABAddressBookSave(addrBook, &error);
- }
- if (!bSuccess) { // need to provide error codes
- bIsError = TRUE;
- errCode = IO_ERROR;
- } else {
- // give original dictionary back? If generate dictionary from saved contact, have no returnFields specified
- // so would give back all fields (which W3C spec. indicates is not desired)
- // for now (while testing) give back saved, full contact
- NSDictionary* newContact = [aContact toDictionary:[CDVContact defaultFields]];
- // NSString* contactStr = [newContact JSONRepresentation];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary:newContact];
- }
- } else {
- bIsError = TRUE;
- errCode = IO_ERROR;
- }
- CFRelease(addrBook);
-
- if (bIsError) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:(int)errCode];
- }
-
- if (result) {
- [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
- }
- }];
- }]; // end of queue
-}
-
-- (void)remove:(CDVInvokedUrlCommand*)command
-{
- NSString* callbackId = command.callbackId;
- NSNumber* cId = [command.arguments objectAtIndex:0];
-
- CDVAddressBookHelper* abHelper = [[CDVAddressBookHelper alloc] init];
- CDVContacts* __weak weakSelf = self; // play it safe to avoid retain cycles
-
- [abHelper createAddressBook: ^(ABAddressBookRef addrBook, CDVAddressBookAccessError* errorCode) {
- CDVPluginResult* result = nil;
- if (addrBook == NULL) {
- // permission was denied or other error - return error
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:errorCode ? (int)errorCode.errorCode:UNKNOWN_ERROR];
- [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
- return;
- }
-
- bool bIsError = FALSE, bSuccess = FALSE;
- CDVContactError errCode = UNKNOWN_ERROR;
- CFErrorRef error;
- ABRecordRef rec = nil;
- if (cId && ![cId isKindOfClass:[NSNull class]] && ([cId intValue] != kABRecordInvalidID)) {
- rec = ABAddressBookGetPersonWithRecordID(addrBook, [cId intValue]);
- if (rec) {
- bSuccess = ABAddressBookRemoveRecord(addrBook, rec, &error);
- if (!bSuccess) {
- bIsError = TRUE;
- errCode = IO_ERROR;
- } else {
- bSuccess = ABAddressBookSave(addrBook, &error);
- if (!bSuccess) {
- bIsError = TRUE;
- errCode = IO_ERROR;
- } else {
- // set id to null
- // [contactDict setObject:[NSNull null] forKey:kW3ContactId];
- // result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsDictionary: contactDict];
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK];
- // NSString* contactStr = [contactDict JSONRepresentation];
- }
- }
- } else {
- // no record found return error
- bIsError = TRUE;
- errCode = UNKNOWN_ERROR;
- }
- } else {
- // invalid contact id provided
- bIsError = TRUE;
- errCode = INVALID_ARGUMENT_ERROR;
- }
-
- if (addrBook) {
- CFRelease(addrBook);
- }
- if (bIsError) {
- result = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsInt:(int)errCode];
- }
- if (result) {
- [weakSelf.commandDelegate sendPluginResult:result callbackId:callbackId];
- }
- }];
- return;
-}
-
-@end
-
-/* ABPersonViewController does not have any UI to dismiss. Adding navigationItems to it does not work properly
- * The navigationItems are lost when the app goes into the background. The solution was to create an empty
- * NavController in front of the ABPersonViewController. This will cause the ABPersonViewController to have a back button. By subclassing the ABPersonViewController, we can override viewDidDisappear and take down the entire NavigationController.
- */
-@implementation CDVDisplayContactViewController
-@synthesize contactsPlugin;
-
-- (void)viewWillDisappear:(BOOL)animated
-{
- [super viewWillDisappear:animated];
-
- if ([self respondsToSelector:@selector(presentingViewController)]) {
- [[self presentingViewController] dismissViewControllerAnimated:YES completion:nil];
- } else {
- [[self parentViewController] dismissModalViewControllerAnimated:YES];
- }
-}
-
-@end
-@implementation CDVAddressBookAccessError
-
-@synthesize errorCode;
-
-- (CDVAddressBookAccessError*)initWithCode:(CDVContactError)code
-{
- self = [super init];
- if (self) {
- self.errorCode = code;
- }
- return self;
-}
-
-@end
-
-@implementation CDVAddressBookHelper
-
-/**
- * NOTE: workerBlock is responsible for releasing the addressBook that is passed to it
- */
-- (void)createAddressBook:(CDVAddressBookWorkerBlock)workerBlock
-{
- // TODO: this probably should be reworked - seems like the workerBlock can just create and release its own AddressBook,
- // and also this important warning from (http://developer.apple.com/library/ios/#documentation/ContactData/Conceptual/AddressBookProgrammingGuideforiPhone/Chapters/BasicObjects.html):
- // "Important: Instances of ABAddressBookRef cannot be used by multiple threads. Each thread must make its own instance."
- ABAddressBookRef addressBook;
-
-#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 60000
- if (&ABAddressBookCreateWithOptions != NULL) {
- CFErrorRef error = nil;
- // CFIndex status = ABAddressBookGetAuthorizationStatus();
- addressBook = ABAddressBookCreateWithOptions(NULL, &error);
- // NSLog(@"addressBook access: %lu", status);
- ABAddressBookRequestAccessWithCompletion(addressBook, ^(bool granted, CFErrorRef error) {
- // callback can occur in background, address book must be accessed on thread it was created on
- dispatch_sync(dispatch_get_main_queue(), ^{
- if (error) {
- workerBlock(NULL, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
- } else if (!granted) {
- workerBlock(NULL, [[CDVAddressBookAccessError alloc] initWithCode:PERMISSION_DENIED_ERROR]);
- } else {
- // access granted
- workerBlock(addressBook, [[CDVAddressBookAccessError alloc] initWithCode:UNKNOWN_ERROR]);
- }
- });
- });
- } else
-#endif
- {
- // iOS 4 or 5 no checks needed
- addressBook = ABAddressBookCreate();
- workerBlock(addressBook, NULL);
- }
-}
-
-@end
diff --git a/src/ubuntu/contacts.cpp b/src/ubuntu/contacts.cpp
deleted file mode 100644
index 373a276..0000000
--- a/src/ubuntu/contacts.cpp
+++ /dev/null
@@ -1,576 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-#include "contacts.h"
-
-#if defined QTCONTACTS_USE_NAMESPACE
-QTCONTACTS_USE_NAMESPACE
-#endif
-
-Contacts::Contacts(Cordova *cordova): CPlugin(cordova) {
- m_fieldNamePairs.clear();
-
- m_fieldNamePairs["displayName"] = QContactDetail::TypeDisplayLabel;
- m_fieldNamePairs["name"] = QContactDetail::TypeName;
- m_fieldNamePairs["nickname"] = QContactDetail::TypeNickname;
- m_fieldNamePairs["phoneNumbers"] = QContactDetail::TypePhoneNumber;
- m_fieldNamePairs["emails"] = QContactDetail::TypeEmailAddress;
- m_fieldNamePairs["addresses"] = QContactDetail::TypeAddress;
- m_fieldNamePairs["ims"] = QContactDetail::TypeOnlineAccount;
- m_fieldNamePairs["organizations"] = QContactDetail::TypeOrganization;
- m_fieldNamePairs["birthday"] = QContactDetail::TypeBirthday;
- m_fieldNamePairs["note"] = QContactDetail::TypeNote;
- m_fieldNamePairs["photos"] = QContactDetail::TypeAvatar;
- m_fieldNamePairs["urls"] = QContactDetail::TypeUrl;
-
- m_notSupportedFields.clear();
- m_notSupportedFields << "categories";
- m_manager.clear();
- m_manager = QSharedPointer<QContactManager>(new QContactManager());
-}
-
-void Contacts::save(int scId, int ecId, const QVariantMap ¶ms) {
- QContact result;
- QList<QContactDetail *> detailsToDelete;
-
- if (params.find("id") != params.end()) {
- QString id = params.find("id")->toString();
- if (!id.isEmpty()) {
- result = m_manager->contact(QContactId::fromString(id));
- result.clearDetails();
- }
- }
-
- foreach (QString field, params.keys()) {
- QContactDetail::DetailType qtDefinition = cordovaFieldNameToQtDefinition(field);
- if (qtDefinition == QContactDetail::TypeUndefined)
- continue;
-
- if (field == "nickname") {
- QContactNickname *detail = new QContactNickname;
- detail->setNickname(params[field].toString());
- detailsToDelete << detail;
- result.saveDetail(detail);
- } else if (field == "note") {
- QContactNote *detail = new QContactNote;
- detail->setNote(params[field].toString());
- detailsToDelete << detail;
- result.saveDetail(detail);
- } else if (field == "phoneNumbers") {
- if (params[field].type() != QVariant::List)
- continue;
- QVariantList phonesList = params[field].toList();
- foreach (const QVariant &phoneDesc, phonesList) {
- if (phoneDesc.type() != QVariant::Map)
- continue;
- QContactPhoneNumber *detail = new QContactPhoneNumber;
- detail->setNumber(phoneDesc.toMap()["value"].toString());
- if (!phoneDesc.toMap()["type"].toString().isEmpty() &&
- phoneDesc.toMap()["type"].toString() != "phone")
- detail->setSubTypes(QList<int>() <<
- subTypePhoneFromString(phoneDesc.toMap()["type"].toString()));
- detailsToDelete << detail;
- result.saveDetail(detail);
- }
- } else if (field == "emails") {
- if (params[field].type() != QVariant::List)
- continue;
- QVariantList emailsList = params[field].toList();
- foreach (const QVariant &emailDesc, emailsList) {
- if (emailDesc.type() != QVariant::Map)
- continue;
- if (emailDesc.toMap()["value"].toString().isEmpty())
- continue;
- QContactEmailAddress *detail = new QContactEmailAddress;
- detail->setEmailAddress(emailDesc.toMap()["value"].toString());
- detailsToDelete << detail;
- result.saveDetail(detail);
- }
- } else if (field == "ims") {
- if (params[field].type() != QVariant::List)
- continue;
- QVariantList imsList = params[field].toList();
- foreach (const QVariant &imDesc, imsList) {
- if (imDesc.type() != QVariant::Map)
- continue;
- QContactOnlineAccount *detail = new QContactOnlineAccount;
- detail->setAccountUri(imDesc.toMap()["value"].toString());
- if (!imDesc.toMap()["type"].toString().isEmpty())
- detail->setSubTypes(QList<int>() <<
- subTypeOnlineAccountFromString(imDesc.toMap()["type"].toString()));
- detailsToDelete << detail;
- result.saveDetail(detail);
- }
- } else if (field == "photos") {
- if (params[field].type() != QVariant::List)
- continue;
- QVariantList photosList = params[field].toList();
- foreach (const QVariant &photoDesc, photosList) {
- if (photoDesc.type() != QVariant::Map)
- continue;
- //TODO: we need to decide should we support base64 images or not
- if (photoDesc.toMap()["type"].toString() != "url")
- continue;
- QContactAvatar *detail = new QContactAvatar;
- detail->setImageUrl(QUrl(photoDesc.toMap()["value"].toString()));
- detailsToDelete << detail;
- result.saveDetail(detail);
- }
- } else if (field == "urls") {
- if (params[field].type() != QVariant::List)
- continue;
- QVariantList urlsList = params[field].toList();
- foreach (const QVariant &urlDesc, urlsList) {
- if (urlDesc.type() != QVariant::Map)
- continue;
- QContactUrl *detail = new QContactUrl;
- detail->setUrl(urlDesc.toMap()["value"].toString());
- if (!urlDesc.toMap()["type"].toString().isEmpty())
- detail->setSubType((QContactUrl::SubType) subTypeUrlFromString(urlDesc.toMap()["type"].toString()));
- detailsToDelete << detail;
- result.saveDetail(detail);
- }
- } else if (field == "birthday") {
- QDateTime birthday;
- birthday.setTime_t(params[field].toLongLong() / 1000);
-
- QContactBirthday *detail = new QContactBirthday;
- detail->setDateTime(birthday);
- detailsToDelete << detail;
- result.saveDetail(detail);
- } else if (field == "organizations") {
-
- if (params[field].type() != QVariant::List)
- continue;
- QVariantList organizationsList = params[field].toList();
- foreach (const QVariant &organizationDesc, organizationsList) {
- if (organizationDesc.type() != QVariant::Map)
- continue;
- QContactOrganization *detail = new QContactOrganization;
- detail->setName(organizationDesc.toMap()["name"].toString());
- detail->setDepartment(QStringList() << organizationDesc.toMap()["department"].toString());
- detail->setRole(organizationDesc.toMap()["title"].toString());
- detailsToDelete << detail;
- result.saveDetail(detail);
- }
-
- } else if (field == "name") {
- QContactName *detail = new QContactName;
- QVariantMap nameMap = params[field].toMap();
- detail->setLastName(nameMap["familyName"].toString());
- detail->setFirstName(nameMap["givenName"].toString());
- detail->setMiddleName(nameMap["middleName"].toString());
- detail->setPrefix(nameMap["honorificPrefix"].toString());
- detail->setSuffix(nameMap["honorificSuffix"].toString());
- detailsToDelete << detail;
- result.saveDetail(detail);
- }
-
- }
- if (!m_manager->saveContact(&result)) {
- switch (m_manager->error()) {
- case QContactManager::DoesNotExistError:
- case QContactManager::AlreadyExistsError:
- case QContactManager::InvalidDetailError:
- case QContactManager::InvalidRelationshipError:
- case QContactManager::BadArgumentError:
- case QContactManager::InvalidContactTypeError:
- callback(ecId, "ContactError.INVALID_ARGUMENT_ERROR");
- break;
- case QContactManager::DetailAccessError:
- case QContactManager::PermissionsError:
- callback(ecId, "ContactError.PERMISSION_DENIED_ERROR");
- break;
- case QContactManager::NotSupportedError:
- callback(ecId, "ContactError.NOT_SUPPORTED_ERROR");
- break;
- case QContactManager::TimeoutError:
- callback(ecId, "ContactError.TIMEOUT_ERROR");
- break;
- case QContactManager::UnspecifiedError:
- case QContactManager::LockedError:
- case QContactManager::OutOfMemoryError:
- case QContactManager::VersionMismatchError:
- case QContactManager::LimitReachedError:
- case QContactManager::NoError:
- default:
- callback(ecId, "ContactError.UNKNOWN_ERROR");
- break;
- }
- } else {
- callback(scId, jsonedContact(result));
- }
- qDeleteAll(detailsToDelete);
-}
-
-void Contacts::remove(int scId, int ecId, const QString &localId) {
- QContactId id = QContactId::fromString(localId);
-
- if (!m_manager->removeContact(id)) {
- switch (m_manager->error()) {
- case QContactManager::AlreadyExistsError:
- case QContactManager::InvalidDetailError:
- case QContactManager::InvalidRelationshipError:
- case QContactManager::BadArgumentError:
- case QContactManager::InvalidContactTypeError:
- callback(ecId, "ContactError.INVALID_ARGUMENT_ERROR");
- break;
- case QContactManager::DetailAccessError:
- case QContactManager::PermissionsError:
- callback(ecId, "ContactError.PERMISSION_DENIED_ERROR");
- break;
- case QContactManager::NotSupportedError:
- callback(ecId, "ContactError.NOT_SUPPORTED_ERROR");
- break;
- case QContactManager::TimeoutError:
- callback(ecId, "ContactError.TIMEOUT_ERROR");
- break;
- case QContactManager::UnspecifiedError:
- case QContactManager::LockedError:
- case QContactManager::OutOfMemoryError:
- case QContactManager::VersionMismatchError:
- case QContactManager::LimitReachedError:
- case QContactManager::NoError:
- case QContactManager::DoesNotExistError:
- default:
- callback(ecId, "ContactError.UNKNOWN_ERROR");
- break;
- }
-
- } else {
- cb(scId);
- }
-}
-
-void Contacts::search(int scId, int ecId, const QStringList &fields, const QVariantMap ¶ms) {
- QString filter;
- bool multiple = true;
-
- if (params.find("filter") != params.end()) {
- filter = params["filter"].toString();
- }
- if (params.find("multiple") != params.end()) {
- multiple = params["multiple"].toBool();
- }
-
- findContacts(scId, ecId, fields, filter, multiple);
-}
-
-void Contacts::findContacts(int scId, int ecId, const QStringList &fields, const QString &filter, bool multiple) {
- if (fields.length() <= 0){
- callback(ecId, "new ContactError(ContactError.INVALID_ARGUMENT_ERROR)");
- }
-
- QContactUnionFilter unionFilter;
-
- QMap<QContactDetail::DetailType, QList<int> > fieldNames;
- fieldNames[QContactDetail::TypeDisplayLabel] << QContactDisplayLabel::FieldLabel;
- fieldNames[QContactDetail::TypeName] << QContactName::FieldFirstName << QContactName::FieldLastName << QContactName::FieldMiddleName << QContactName::FieldPrefix << QContactName::FieldSuffix;
- fieldNames[QContactDetail::TypeNickname] << QContactNickname::FieldNickname;
- fieldNames[QContactDetail::TypePhoneNumber] << QContactPhoneNumber::FieldNumber;
- fieldNames[QContactDetail::TypeEmailAddress] << QContactEmailAddress::FieldEmailAddress;
- fieldNames[QContactDetail::TypeAddress] << QContactAddress::FieldCountry << QContactAddress::FieldLocality << QContactAddress::FieldPostcode << QContactAddress::FieldPostOfficeBox << QContactAddress::FieldRegion << QContactAddress::FieldStreet;
- fieldNames[QContactDetail::TypeOnlineAccount] << QContactOnlineAccount::FieldAccountUri;
- fieldNames[QContactDetail::TypeOrganization] << QContactOrganization::FieldAssistantName << QContactOrganization::FieldDepartment << QContactOrganization::FieldLocation << QContactOrganization::FieldName << QContactOrganization::FieldRole << QContactOrganization::FieldTitle;
- fieldNames[QContactDetail::TypeBirthday] << QContactBirthday::FieldBirthday;
- fieldNames[QContactDetail::TypeNote] << QContactNote::FieldNote;
- fieldNames[QContactDetail::TypeUrl] << QContactUrl::FieldUrl;
-
- foreach (const QContactDetail::DetailType &defName, fieldNames.keys()) {
- foreach(int fieldName, fieldNames[defName]) {
- QContactDetailFilter subFilter;
- subFilter.setDetailType(defName, fieldName);
- subFilter.setValue(filter);
- subFilter.setMatchFlags(QContactFilter::MatchContains);
- unionFilter.append(subFilter);
- }
- }
-
- QList<QContact> contacts = m_manager->contacts(unionFilter);
- if (contacts.empty()) {
- callback(scId, "[]");
- } else {
- QStringList stringifiedContacts;
- foreach (const QContact &contact, contacts) {
- stringifiedContacts << jsonedContact(contact, fields);
-
- if (!multiple)
- break;
- }
- callback(scId, QString("[%1]").arg(stringifiedContacts.join(", ")));
- }
-}
-
-QContactDetail::DetailType Contacts::cordovaFieldNameToQtDefinition(const QString &cordovaFieldName) const {
- if (m_fieldNamePairs.contains(cordovaFieldName))
- return m_fieldNamePairs[cordovaFieldName];
-
- return QContactDetail::TypeUndefined;
-}
-
-int Contacts::subTypePhoneFromString(const QString &cordovaSubType) const
-{
- QString preparedSubType = cordovaSubType.toLower();
- if (preparedSubType == "mobile")
- return QContactPhoneNumber::SubTypeMobile;
- else if (preparedSubType == "fax")
- return QContactPhoneNumber::SubTypeFax;
- else if (preparedSubType == "pager")
- return QContactPhoneNumber::SubTypePager;
- else if (preparedSubType == "voice")
- return QContactPhoneNumber::SubTypeVoice;
- else if (preparedSubType == "modem")
- return QContactPhoneNumber::SubTypeModem;
- else if (preparedSubType == "video")
- return QContactPhoneNumber::SubTypeVideo;
- else if (preparedSubType == "car")
- return QContactPhoneNumber::SubTypeCar;
- else if (preparedSubType == "assistant")
- return QContactPhoneNumber::SubTypeAssistant;
- return QContactPhoneNumber::SubTypeLandline;
-}
-
-int Contacts::subTypeOnlineAccountFromString(const QString &cordovaSubType) const {
- QString preparedSubType = cordovaSubType.toLower();
- if (preparedSubType == "aim")
- return QContactOnlineAccount::ProtocolAim;
- else if (preparedSubType == "icq")
- return QContactOnlineAccount::ProtocolIcq;
- else if (preparedSubType == "irc")
- return QContactOnlineAccount::ProtocolIrc;
- else if (preparedSubType == "jabber")
- return QContactOnlineAccount::ProtocolJabber;
- else if (preparedSubType == "msn")
- return QContactOnlineAccount::ProtocolMsn;
- else if (preparedSubType == "qq")
- return QContactOnlineAccount::ProtocolQq;
- else if (preparedSubType == "skype")
- return QContactOnlineAccount::ProtocolSkype;
- else if (preparedSubType == "yahoo")
- return QContactOnlineAccount::ProtocolYahoo;
- return QContactOnlineAccount::ProtocolUnknown;
-}
-
-int Contacts::subTypeUrlFromString(const QString &cordovaSubType) const {
- QString preparedSubType = cordovaSubType.toLower();
- if (preparedSubType == "blog")
- return QContactUrl::SubTypeBlog;
- else if (preparedSubType == "favourite")
- return QContactUrl::SubTypeFavourite;
- return QContactUrl::SubTypeHomePage;
-}
-
-QString Contacts::subTypePhoneToString(int qtSubType) const {
- if (qtSubType == QContactPhoneNumber::SubTypeMobile)
- return "mobile";
- else if (qtSubType == QContactPhoneNumber::SubTypeFax)
- return "fax";
- else if (qtSubType == QContactPhoneNumber::SubTypePager)
- return "pager";
- else if (qtSubType == QContactPhoneNumber::SubTypeVoice)
- return "voice";
- else if (qtSubType == QContactPhoneNumber::SubTypeModem)
- return "modem";
- else if (qtSubType == QContactPhoneNumber::SubTypeVideo)
- return "video";
- else if (qtSubType == QContactPhoneNumber::SubTypeCar)
- return "car";
- else if (qtSubType == QContactPhoneNumber::SubTypeAssistant)
- return "assistant";
- return "home";
-}
-
-QString Contacts::subTypeOnlineAccountToString(int qtSubType) const {
- if (qtSubType == QContactOnlineAccount::ProtocolAim)
- return "aim";
- else if (qtSubType == QContactOnlineAccount::ProtocolIcq)
- return "icq";
- else if (qtSubType == QContactOnlineAccount::ProtocolIrc)
- return "irc";
- else if (qtSubType == QContactOnlineAccount::ProtocolJabber)
- return "jabber";
- else if (qtSubType == QContactOnlineAccount::ProtocolMsn)
- return "msn";
- else if (qtSubType == QContactOnlineAccount::ProtocolQq)
- return "qq";
- else if (qtSubType == QContactOnlineAccount::ProtocolSkype)
- return "skype";
- else if (qtSubType == QContactOnlineAccount::ProtocolYahoo)
- return "yahoo";
- return "unknown";
-}
-
-QString Contacts::subTypeUrlToString(int qtSubType) const {
- if (qtSubType == QContactUrl::SubTypeBlog)
- return "blog";
- else if (qtSubType == QContactUrl::SubTypeFavourite)
- return "favourite";
- return "homepage";
-}
-
-QString Contacts::jsonedContact(const QContact &contact, const QStringList &fields) const {
- QStringList resultingFields = fields;
- if (resultingFields.empty())
- resultingFields.append(m_fieldNamePairs.keys());
- if (!resultingFields.contains("id"))
- resultingFields << "id";
- QStringList fieldValuesList;
- foreach (const QString &field, resultingFields) {
- QContactDetail::DetailType qtDefinitionName = cordovaFieldNameToQtDefinition(field);
- if (field == "id") {
- fieldValuesList << QString("%1: \"%2\"")
- .arg(field)
- .arg(contact.id().toString());
- } else if (field == "displayName") {
- QContactDisplayLabel detail = contact.detail(qtDefinitionName);
- fieldValuesList << QString("%1: \"%2\"")
- .arg(field)
- .arg(detail.label());
- } else if (field == "nickname") {
- QContactNickname detail = contact.detail(qtDefinitionName);
- fieldValuesList << QString("%1: \"%2\"")
- .arg(field)
- .arg(detail.nickname());
- } else if (field == "note") {
- QContactNote detail = contact.detail(qtDefinitionName);
- fieldValuesList << QString("%1: \"%2\"")
- .arg(field)
- .arg(detail.note());
- } else if (field == "phoneNumbers") {
- QStringList fieldValues;
- QList<QContactDetail> details = contact.details(qtDefinitionName);
- foreach (const QContactDetail &detail, details) {
- QContactPhoneNumber castedDetail = detail;
- QStringList subTypes;
- foreach (int subType, castedDetail.subTypes())
- subTypes << subTypePhoneToString(subType);
-
- if (subTypes.isEmpty())
- subTypes << "phone";
- foreach(const QString &subType, subTypes) {
- fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
- .arg(subType)
- .arg(castedDetail.number())
- .arg("false");
- }
- }
- fieldValuesList << QString("%1: [%2]")
- .arg(field)
- .arg(fieldValues.join(", "));
- } else if (field == "emails") {
- QStringList fieldValues;
- QList<QContactDetail> details = contact.details(qtDefinitionName);
- foreach (const QContactDetail &detail, details) {
- QContactEmailAddress castedDetail = detail;
- fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
- .arg("email")
- .arg(castedDetail.emailAddress())
- .arg("false");
- }
- fieldValuesList << QString("%1: [%2]")
- .arg(field)
- .arg(fieldValues.join(", "));
- } else if (field == "ims") {
- QStringList fieldValues;
- QList<QContactDetail> details = contact.details(qtDefinitionName);
- foreach (const QContactDetail &detail, details) {
- QContactOnlineAccount castedDetail = detail;
- QStringList subTypes;
- foreach (int subType, castedDetail.subTypes())
- subTypes << subTypeOnlineAccountToString(subType);
-
- if (subTypes.isEmpty())
- subTypes << "IM";
- foreach(const QString &subType, subTypes) {
- fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
- .arg(subType)
- .arg(castedDetail.accountUri())
- .arg("false");
- }
- }
- fieldValuesList << QString("%1: [%2]")
- .arg(field)
- .arg(fieldValues.join(", "));
- } else if (field == "photos") {
- QStringList fieldValues;
- QList<QContactDetail> details = contact.details(qtDefinitionName);
- foreach (const QContactDetail &detail, details) {
- QContactAvatar castedDetail = detail;
- fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
- .arg("url")
- .arg(castedDetail.imageUrl().toString())
- .arg("false");
- }
- fieldValuesList << QString("%1: [%2]")
- .arg(field)
- .arg(fieldValues.join(", "));
- } else if (field == "urls") {
- QStringList fieldValues;
- QList<QContactDetail> details = contact.details(qtDefinitionName);
-
- foreach (const QContactDetail &detail, details) {
- QContactUrl castedDetail = detail;
- QString subType = subTypeUrlToString(castedDetail.subType());
-
- fieldValues << QString("{type: \"%1\", value: \"%2\", pref: %3}")
- .arg(subType)
- .arg(castedDetail.url())
- .arg("false");
- }
- fieldValuesList << QString("%1: [%2]")
- .arg(field)
- .arg(fieldValues.join(", "));
- } else if (field == "birthday") {
- QContactBirthday detail = contact.detail(qtDefinitionName);
- fieldValuesList << QString("%1: %2")
- .arg(field)
- .arg(detail.dateTime().toMSecsSinceEpoch());
- } else if (field == "organizations") {
- QStringList fieldValues;
- QList<QContactDetail> details = contact.details(qtDefinitionName);
- foreach (const QContactDetail &detail, details) {
- QContactOrganization castedDetail = detail;
- fieldValues << QString("{type: \"%1\", name: \"%2\", department: \"%3\", title: \"%4\", pref: %5}")
- .arg("organization")
- .arg(castedDetail.name())
- .arg(castedDetail.department().join(" "))
- .arg(castedDetail.role())
- .arg("false");
- }
- fieldValuesList << QString("%1: [%2]")
- .arg(field)
- .arg(fieldValues.join(", "));
- } else if (field == "name") {
- QContactName detail = contact.detail(qtDefinitionName);
- fieldValuesList << QString("%1: {familyName: \"%2\", givenName: \"%3\", middleName: \"%4\", honorificPrefix: \"%5\", honorificSuffix: \"%6\"}")
- .arg(field)
- .arg(detail.lastName())
- .arg(detail.firstName())
- .arg(detail.middleName())
- .arg(detail.prefix())
- .arg(detail.suffix());
- }
-
-
- }
-
- return QString("{%1}").arg(fieldValuesList.join(", "));
-}
diff --git a/src/ubuntu/contacts.h b/src/ubuntu/contacts.h
deleted file mode 100644
index 4c1343b..0000000
--- a/src/ubuntu/contacts.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-#ifndef CONTACTS_H_SSSSSSS
-#define CONTACTS_H_SSSSSSS
-
-#include <cplugin.h>
-
-#include <QtContacts>
-#include <QtCore>
-
-QTCONTACTS_USE_NAMESPACE
-
-class Contacts : public CPlugin {
- Q_OBJECT
-public:
- explicit Contacts(Cordova *cordova);
-
- virtual const QString fullName() override {
- return Contacts::fullID();
- }
-
- virtual const QString shortName() override {
- return "Contacts";
- }
-
- static const QString fullID() {
- return "Contacts";
- }
-
-public slots:
- void save(int scId, int ecId, const QVariantMap ¶ms);
- void remove(int scId, int ecId, const QString &localId);
- void search(int scId, int ecId, const QStringList &fields, const QVariantMap ¶ms);
-
-private:
- void findContacts(int scId, int ecId, const QStringList &fields, const QString &filter, bool multiple);
- QContactDetail::DetailType cordovaFieldNameToQtDefinition(const QString &cordovaFieldName) const;
- int subTypePhoneFromString(const QString &cordovaSubType) const;
- int subTypeOnlineAccountFromString(const QString &cordovaSubType) const;
- int subTypeUrlFromString(const QString &cordovaSubType) const;
- QString subTypePhoneToString(int qtSubType) const;
- QString subTypeOnlineAccountToString(int qtSubType) const;
- QString subTypeUrlToString(int qtSubType) const;
- QString jsonedContact(const QContact &contact, const QStringList &fields = QStringList()) const;
-
- QHash<QString, QContactDetail::DetailType> m_fieldNamePairs;
- QSet<QString> m_notSupportedFields;
- QSharedPointer<QContactManager> m_manager;
-};
-
-#endif
diff --git a/src/windows8/ContactProxy.js b/src/windows8/ContactProxy.js
deleted file mode 100644
index 10f9402..0000000
--- a/src/windows8/ContactProxy.js
+++ /dev/null
@@ -1,151 +0,0 @@
-//cordova.define("org.apache.cordova.contacts.ContactProxy", function (require, exports, module) {
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-
-module.exports = {
- search:function(win,fail,args){
- var fields = args[0]; // ignored, always returns entire object
- var options = args[1];
-
- var filter = options.filter; // ignored
- var multiple = true;//options.multiple;
-
- var picker = new Windows.ApplicationModel.Contacts.ContactPicker();
- picker.selectionMode = Windows.ApplicationModel.Contacts.ContactSelectionMode.contacts; // select entire contact
- if (picker.pickContactAsync) {
- // TODO: 8.1 has better contact support via the 'Contact' object
- }
- else {
- // 8.0 use the ContactInformation class
- // decide which function we will call
- var pickerFunkName = multiple ? 'pickMultipleContactsAsync' : 'pickSingleContactAsync';
- picker[pickerFunkName]().done(function (res) {
- if (!res) {
- fail && setTimeout(function () {
- fail(new Error("User did not pick a contact."));
- }, 0);
- return;
- }
-
- var contactResults = [];
-
- for (var i = 0; i < res.length; i++) {
-
-
- var index,
- contactResult = res[i],
- contact = {
- id: "",
- name: { formatted: contactResult.name }, // ContactName
- displayName: contactResult.name, // DOMString
- nickname: contactResult.name, // DOMString
- phoneNumbers: contactResult.phoneNumbers, // ContactField[]
- addresses: contactResult.locations, // ContactAddress[]
- emails: [], // ContactField
- ims: contactResult.instantMessages, // ContactField[]
- organizations: [], // ContactOrganization[]
- birthday: null, // Date
- note: "", // DOMString
- photos: [], // ContactField[]
- categories: [], // ContactField[]
- urls: [] // ContactField[]
- };
-
- // Win8-ContactField is {category, name, type, value};
- // Cordova ContactField is {type,value, pref:bool };
- // Win8 type means 'email' cordova type means 'work|home|...' so we convert them
- if (contact.emails && contact.emails.length) {
- contact.emails[0].pref = true; // add a preferred prop
- for (index = 0; index < contacts.emails.length; index++) {
- contact.emails[index].type = contact.emails[index].category;
- }
- }
-
- if (contact.phoneNumbers && contact.phoneNumbers.length) {
- contact.phoneNumbers[0].pref = true; // cordova contact field needs a 'prefered' property on a contact
- // change the meaning of type from 'telephonenumber' to 'work|home|...'
- for (index = 0; index < contact.phoneNumbers.length; index++) {
- contact.phoneNumbers[index].type = contact.phoneNumbers[index].category;
- }
- }
-
- if (contact.addresses && contact.addresses.length) {
-
- // convert addresses/locations to Cordova.ContactAddresses
- // constr: ContactAddress(pref, type, formatted, streetAddress, locality, region, postalCode, country)
- var address, formatted;
- for (index = 0; index < contact.addresses.length; index++) {
- address = contact.addresses[index]; // make an alias
- var formattedArray = [];
- // get rid of the empty fields.
- var fields = [address.street, address.city, address.region, address.country, address.postalCode];
- for (var n = 0; n < fields.length; n++) {
- if (fields[n].length > 0) {
- formattedArray.push(fields[n]);
- }
- }
- formattedAddress = formattedArray.join(", ");
- console.log(contact.name.formatted + " formatted looks like " + formattedAddress);
- contact.addresses[index] = new ContactAddress(false,
- address.name,
- formattedAddress,
- address.street,
- address.city,
- address.region,
- address.postalCode,
- address.country);
- }
-
- }
-
- // convert ims to ContactField
- if (contact.ims && contact.ims.length) {
- // MS ContactInstantMessageField has : displayText, launchUri, service, userName, category, type
- contact.ims[0].pref = true;
- for (index = 0; index < contact.ims.length; index++) {
- contact.ims[index] = new ContactField(contact.ims[index].type, contact.ims[index].value, false);
- }
- }
-
- contactResults.push(contact);
-
- }
- // send em back
- win(contactResults);
-
- });
- }
- },
-
- save:function(win,fail,args){
- console && console.error && console.error("Error : Windows 8 does not support creating/saving contacts");
- fail && setTimeout(function () {
- fail(new Error("Contact create/save not supported on Windows 8"));
- }, 0);
-
- }
-
-
-}
-
-require("cordova/exec/proxy").add("Contacts", module.exports);
-// });
diff --git a/src/wp/Contacts.cs b/src/wp/Contacts.cs
deleted file mode 100644
index 5ae2144..0000000
--- a/src/wp/Contacts.cs
+++ /dev/null
@@ -1,693 +0,0 @@
-/*
- Licensed under the Apache License, Version 2.0 (the "License");
- you may not use this file except in compliance with the License.
- You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-*/
-
-using Microsoft.Phone.Tasks;
-using Microsoft.Phone.UserData;
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Globalization;
-using System.Linq;
-using System.Runtime.Serialization;
-using System.Windows;
-using DeviceContacts = Microsoft.Phone.UserData.Contacts;
-
-
-namespace WPCordovaClassLib.Cordova.Commands
-{
- [DataContract]
- public class SearchOptions
- {
- [DataMember]
- public string filter { get; set; }
- [DataMember]
- public bool multiple { get; set; }
- }
-
- [DataContract]
- public class ContactSearchParams
- {
- [DataMember]
- public string[] fields { get; set; }
- [DataMember]
- public SearchOptions options { get; set; }
- }
-
- [DataContract]
- public class JSONContactAddress
- {
- [DataMember]
- public string formatted { get; set; }
- [DataMember]
- public string type { get; set; }
- [DataMember]
- public string streetAddress { get; set; }
- [DataMember]
- public string locality { get; set; }
- [DataMember]
- public string region { get; set; }
- [DataMember]
- public string postalCode { get; set; }
- [DataMember]
- public string country { get; set; }
- [DataMember]
- public bool pref { get; set; }
- }
-
- [DataContract]
- public class JSONContactName
- {
- [DataMember]
- public string formatted { get; set; }
- [DataMember]
- public string familyName { get; set; }
- [DataMember]
- public string givenName { get; set; }
- [DataMember]
- public string middleName { get; set; }
- [DataMember]
- public string honorificPrefix { get; set; }
- [DataMember]
- public string honorificSuffix { get; set; }
- }
-
- [DataContract]
- public class JSONContactField
- {
- [DataMember]
- public string type { get; set; }
- [DataMember]
- public string value { get; set; }
- [DataMember]
- public bool pref { get; set; }
- }
-
- [DataContract]
- public class JSONContactOrganization
- {
- [DataMember]
- public string type { get; set; }
- [DataMember]
- public string name { get; set; }
- [DataMember]
- public bool pref { get; set; }
- [DataMember]
- public string department { get; set; }
- [DataMember]
- public string title { get; set; }
- }
-
- [DataContract]
- public class JSONContact
- {
- [DataMember]
- public string id { get; set; }
- [DataMember]
- public string rawId { get; set; }
- [DataMember]
- public string displayName { get; set; }
- [DataMember]
- public string nickname { get; set; }
- [DataMember]
- public string note { get; set; }
-
- [DataMember]
- public JSONContactName name { get; set; }
-
- [DataMember]
- public JSONContactField[] emails { get; set; }
-
- [DataMember]
- public JSONContactField[] phoneNumbers { get; set; }
-
- [DataMember]
- public JSONContactField[] ims { get; set; }
-
- [DataMember]
- public JSONContactField[] photos { get; set; }
-
- [DataMember]
- public JSONContactField[] categories { get; set; }
-
- [DataMember]
- public JSONContactField[] urls { get; set; }
-
- [DataMember]
- public JSONContactOrganization[] organizations { get; set; }
-
- [DataMember]
- public JSONContactAddress[] addresses { get; set; }
- }
-
-
- public class Contacts : BaseCommand
- {
-
- public const int UNKNOWN_ERROR = 0;
- public const int INVALID_ARGUMENT_ERROR = 1;
- public const int TIMEOUT_ERROR = 2;
- public const int PENDING_OPERATION_ERROR = 3;
- public const int IO_ERROR = 4;
- public const int NOT_SUPPORTED_ERROR = 5;
- public const int PERMISSION_DENIED_ERROR = 20;
- public const int SYNTAX_ERR = 8;
-
- public Contacts()
- {
-
- }
-
- // refer here for contact properties we can access: http://msdn.microsoft.com/en-us/library/microsoft.phone.tasks.savecontacttask_members%28v=VS.92%29.aspx
- public void save(string jsonContact)
- {
-
- // jsonContact is actually an array of 1 {contact}
- string[] args = JSON.JsonHelper.Deserialize<string[]>(jsonContact);
-
-
- JSONContact contact = JSON.JsonHelper.Deserialize<JSONContact>(args[0]);
-
- SaveContactTask contactTask = new SaveContactTask();
-
- if (contact.nickname != null)
- {
- contactTask.Nickname = contact.nickname;
- }
- if (contact.urls != null && contact.urls.Length > 0)
- {
- contactTask.Website = contact.urls[0].value;
- }
- if (contact.note != null)
- {
- contactTask.Notes = contact.note;
- }
-
- #region contact.name
- if (contact.name != null)
- {
- if (contact.name.givenName != null)
- contactTask.FirstName = contact.name.givenName;
- if (contact.name.familyName != null)
- contactTask.LastName = contact.name.familyName;
- if (contact.name.middleName != null)
- contactTask.MiddleName = contact.name.middleName;
- if (contact.name.honorificSuffix != null)
- contactTask.Suffix = contact.name.honorificSuffix;
- if (contact.name.honorificPrefix != null)
- contactTask.Title = contact.name.honorificPrefix;
- }
- #endregion
-
- #region contact.org
- if (contact.organizations != null && contact.organizations.Count() > 0)
- {
- contactTask.Company = contact.organizations[0].name;
- contactTask.JobTitle = contact.organizations[0].title;
- }
- #endregion
-
- #region contact.phoneNumbers
- if (contact.phoneNumbers != null && contact.phoneNumbers.Length > 0)
- {
- foreach (JSONContactField field in contact.phoneNumbers)
- {
- string fieldType = field.type.ToLower();
- if (fieldType == "work")
- {
- contactTask.WorkPhone = field.value;
- }
- else if (fieldType == "home")
- {
- contactTask.HomePhone = field.value;
- }
- else if (fieldType == "mobile")
- {
- contactTask.MobilePhone = field.value;
- }
- }
- }
- #endregion
-
- #region contact.emails
-
- if (contact.emails != null && contact.emails.Length > 0)
- {
-
- // set up different email types if they are not explicitly defined
- foreach (string type in new string[] { "personal", "work", "other" })
- {
- foreach (JSONContactField field in contact.emails)
- {
- if (field != null && String.IsNullOrEmpty(field.type))
- {
- field.type = type;
- break;
- }
- }
- }
-
- foreach (JSONContactField field in contact.emails)
- {
- if (field != null)
- {
- if (field.type != null && field.type != "other")
- {
- string fieldType = field.type.ToLower();
- if (fieldType == "work")
- {
- contactTask.WorkEmail = field.value;
- }
- else if (fieldType == "home" || fieldType == "personal")
- {
- contactTask.PersonalEmail = field.value;
- }
- }
- else
- {
- contactTask.OtherEmail = field.value;
- }
- }
-
- }
- }
- #endregion
-
- if (contact.note != null && contact.note.Length > 0)
- {
- contactTask.Notes = contact.note;
- }
-
- #region contact.addresses
- if (contact.addresses != null && contact.addresses.Length > 0)
- {
- foreach (JSONContactAddress address in contact.addresses)
- {
- if (address.type == null)
- {
- address.type = "home"; // set a default
- }
- string fieldType = address.type.ToLower();
- if (fieldType == "work")
- {
- contactTask.WorkAddressCity = address.locality;
- contactTask.WorkAddressCountry = address.country;
- contactTask.WorkAddressState = address.region;
- contactTask.WorkAddressStreet = address.streetAddress;
- contactTask.WorkAddressZipCode = address.postalCode;
- }
- else if (fieldType == "home" || fieldType == "personal")
- {
- contactTask.HomeAddressCity = address.locality;
- contactTask.HomeAddressCountry = address.country;
- contactTask.HomeAddressState = address.region;
- contactTask.HomeAddressStreet = address.streetAddress;
- contactTask.HomeAddressZipCode = address.postalCode;
- }
- else
- {
- // no other address fields available ...
- Debug.WriteLine("Creating contact with unsupported address type :: " + address.type);
- }
- }
- }
- #endregion
-
-
- contactTask.Completed += new EventHandler<SaveContactResult>(ContactSaveTaskCompleted);
- contactTask.Show();
- }
-
- void ContactSaveTaskCompleted(object sender, SaveContactResult e)
- {
- SaveContactTask task = sender as SaveContactTask;
-
- if (e.TaskResult == TaskResult.OK)
- {
-
- Deployment.Current.Dispatcher.BeginInvoke(() =>
- {
- DeviceContacts deviceContacts = new DeviceContacts();
- deviceContacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(postAdd_SearchCompleted);
-
- string displayName = String.Format("{0}{2}{1}", task.FirstName, task.LastName, String.IsNullOrEmpty(task.FirstName) ? "" : " ");
-
- deviceContacts.SearchAsync(displayName, FilterKind.DisplayName, task);
- });
-
-
- }
- else if (e.TaskResult == TaskResult.Cancel)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "Operation cancelled."));
- }
- }
-
- void postAdd_SearchCompleted(object sender, ContactsSearchEventArgs e)
- {
- if (e.Results.Count() > 0)
- {
- List<Contact> foundContacts = new List<Contact>();
-
- int n = (from Contact contact in e.Results select contact.GetHashCode()).Max();
- Contact newContact = (from Contact contact in e.Results
- where contact.GetHashCode() == n
- select contact).First();
-
- DispatchCommandResult(new PluginResult(PluginResult.Status.OK, FormatJSONContact(newContact, null)));
- }
- else
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.NO_RESULT));
- }
- }
-
-
-
- public void remove(string id)
- {
- // note id is wrapped in [] and always has exactly one string ...
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, "{\"code\":" + NOT_SUPPORTED_ERROR + "}"));
- }
-
- public void search(string searchCriteria)
- {
- string[] args = JSON.JsonHelper.Deserialize<string[]>(searchCriteria);
-
- ContactSearchParams searchParams = new ContactSearchParams();
- try
- {
- searchParams.fields = JSON.JsonHelper.Deserialize<string[]>(args[0]);
- searchParams.options = JSON.JsonHelper.Deserialize<SearchOptions>(args[1]);
- }
- catch (Exception)
- {
- DispatchCommandResult(new PluginResult(PluginResult.Status.ERROR, INVALID_ARGUMENT_ERROR));
- return;
- }
-
- if (searchParams.options == null)
- {
- searchParams.options = new SearchOptions();
- searchParams.options.filter = "";
- searchParams.options.multiple = true;
- }
- else if (searchParams.options.filter == null)
- {
- searchParams.options.filter = "";
- }
-
- DeviceContacts deviceContacts = new DeviceContacts();
- deviceContacts.SearchCompleted += new EventHandler<ContactsSearchEventArgs>(contacts_SearchCompleted);
-
- // default is to search all fields
- FilterKind filterKind = FilterKind.None;
- // if only one field is specified, we will try the 3 available DeviceContact search filters
- if (searchParams.fields.Count() == 1)
- {
- if (searchParams.fields.Contains("name"))
- {
- filterKind = FilterKind.DisplayName;
- }
- else if (searchParams.fields.Contains("emails"))
- {
- filterKind = FilterKind.EmailAddress;
- }
- else if (searchParams.fields.Contains("phoneNumbers"))
- {
- filterKind = FilterKind.PhoneNumber;
- }
- }
-
- try
- {
-
- deviceContacts.SearchAsync(searchParams.options.filter, filterKind, searchParams);
- }
- catch (Exception ex)
- {
- Debug.WriteLine("search contacts exception :: " + ex.Message);
- }
- }
-
- private void contacts_SearchCompleted(object sender, ContactsSearchEventArgs e)
- {
- ContactSearchParams searchParams = (ContactSearchParams)e.State;
-
- List<Contact> foundContacts = null;
- // used for comparing strings, "" instantiates with InvariantCulture
- CultureInfo culture = new CultureInfo("");
- // make the search comparisons case insensitive.
- CompareOptions compare_option = CompareOptions.IgnoreCase;
-
- // if we have multiple search fields
-
- if (!String.IsNullOrEmpty(searchParams.options.filter) && searchParams.fields.Count() > 1)
- {
- foundContacts = new List<Contact>();
- if (searchParams.fields.Contains("emails"))
- {
- foundContacts.AddRange(from Contact con in e.Results
- from ContactEmailAddress a in con.EmailAddresses
- where culture.CompareInfo.IndexOf(a.EmailAddress, searchParams.options.filter, compare_option) >= 0
- select con);
- }
- if (searchParams.fields.Contains("displayName"))
- {
- foundContacts.AddRange(from Contact con in e.Results
- where culture.CompareInfo.IndexOf(con.DisplayName, searchParams.options.filter, compare_option) >= 0
- select con);
- }
- if (searchParams.fields.Contains("name"))
- {
- foundContacts.AddRange(
- from Contact con in e.Results
- where con.CompleteName != null && (
- (con.CompleteName.FirstName != null && culture.CompareInfo.IndexOf(con.CompleteName.FirstName, searchParams.options.filter, compare_option) >= 0) ||
- (con.CompleteName.LastName != null && culture.CompareInfo.IndexOf(con.CompleteName.LastName, searchParams.options.filter, compare_option) >= 0) ||
- (con.CompleteName.MiddleName != null && culture.CompareInfo.IndexOf(con.CompleteName.MiddleName, searchParams.options.filter, compare_option) >= 0) ||
- (con.CompleteName.Nickname != null && culture.CompareInfo.IndexOf(con.CompleteName.Nickname, searchParams.options.filter, compare_option) >= 0) ||
- (con.CompleteName.Suffix != null && culture.CompareInfo.IndexOf(con.CompleteName.Suffix, searchParams.options.filter, compare_option) >= 0) ||
- (con.CompleteName.Title != null && culture.CompareInfo.IndexOf(con.CompleteName.Title, searchParams.options.filter, compare_option) >= 0) ||
- (con.CompleteName.YomiFirstName != null && culture.CompareInfo.IndexOf(con.CompleteName.YomiFirstName, searchParams.options.filter, compare_option) >= 0) ||
- (con.CompleteName.YomiLastName != null && culture.CompareInfo.IndexOf(con.CompleteName.YomiLastName, searchParams.options.filter, compare_option) >= 0))
- select con);
- }
- if (searchParams.fields.Contains("phoneNumbers"))
- {
- foundContacts.AddRange(from Contact con in e.Results
- from ContactPhoneNumber a in con.PhoneNumbers
- where culture.CompareInfo.IndexOf(a.PhoneNumber, searchParams.options.filter, compare_option) >= 0
- select con);
- }
- if (searchParams.fields.Contains("urls"))
- {
- foundContacts.AddRange(from Contact con in e.Results
- from string a in con.Websites
- where culture.CompareInfo.IndexOf(a, searchParams.options.filter, compare_option) >= 0
- select con);
- }
- }
- else
- {
- foundContacts = new List<Contact>(e.Results);
- }
-
- //List<string> contactList = new List<string>();
-
- string strResult = "";
-
- IEnumerable<Contact> distinctContacts = foundContacts.Distinct();
-
- foreach (Contact contact in distinctContacts)
- {
- strResult += FormatJSONContact(contact, null) + ",";
- //contactList.Add(FormatJSONContact(contact, null));
- if (!searchParams.options.multiple)
- {
- break; // just return the first item
- }
- }
- PluginResult result = new PluginResult(PluginResult.Status.OK);
- result.Message = "[" + strResult.TrimEnd(',') + "]";
- DispatchCommandResult(result);
-
- }
-
- private string FormatJSONPhoneNumbers(Contact con)
- {
- string retVal = "";
- string contactFieldFormat = "\"type\":\"{0}\",\"value\":\"{1}\",\"pref\":\"false\"";
- foreach (ContactPhoneNumber number in con.PhoneNumbers)
- {
-
- string contactField = string.Format(contactFieldFormat,
- number.Kind.ToString(),
- number.PhoneNumber);
-
- retVal += "{" + contactField + "},";
- }
- return retVal.TrimEnd(',');
- }
-
- private string FormatJSONEmails(Contact con)
- {
- string retVal = "";
- string contactFieldFormat = "\"type\":\"{0}\",\"value\":\"{1}\",\"pref\":\"false\"";
- foreach (ContactEmailAddress address in con.EmailAddresses)
- {
- string contactField = string.Format(contactFieldFormat,
- address.Kind.ToString(),
- EscapeJson(address.EmailAddress));
-
- retVal += "{" + contactField + "},";
- }
- return retVal.TrimEnd(',');
- }
-
- private string getFormattedJSONAddress(ContactAddress address, bool isPrefered)
- {
-
- string addressFormatString = "\"pref\":{0}," + // bool
- "\"type\":\"{1}\"," +
- "\"formatted\":\"{2}\"," +
- "\"streetAddress\":\"{3}\"," +
- "\"locality\":\"{4}\"," +
- "\"region\":\"{5}\"," +
- "\"postalCode\":\"{6}\"," +
- "\"country\":\"{7}\"";
-
- string formattedAddress = EscapeJson(address.PhysicalAddress.AddressLine1 + " "
- + address.PhysicalAddress.AddressLine2 + " "
- + address.PhysicalAddress.City + " "
- + address.PhysicalAddress.StateProvince + " "
- + address.PhysicalAddress.CountryRegion + " "
- + address.PhysicalAddress.PostalCode);
-
- string jsonAddress = string.Format(addressFormatString,
- isPrefered ? "\"true\"" : "\"false\"",
- address.Kind.ToString(),
- formattedAddress,
- EscapeJson(address.PhysicalAddress.AddressLine1 + " " + address.PhysicalAddress.AddressLine2),
- address.PhysicalAddress.City,
- address.PhysicalAddress.StateProvince,
- address.PhysicalAddress.PostalCode,
- address.PhysicalAddress.CountryRegion);
-
- //Debug.WriteLine("getFormattedJSONAddress returning :: " + jsonAddress);
-
- return "{" + jsonAddress + "}";
- }
-
- private string FormatJSONAddresses(Contact con)
- {
- string retVal = "";
- foreach (ContactAddress address in con.Addresses)
- {
- retVal += this.getFormattedJSONAddress(address, false) + ",";
- }
-
- //Debug.WriteLine("FormatJSONAddresses returning :: " + retVal);
- return retVal.TrimEnd(',');
- }
-
- private string FormatJSONWebsites(Contact con)
- {
- string retVal = "";
- foreach (string website in con.Websites)
- {
- retVal += "\"" + EscapeJson(website) + "\",";
- }
- return retVal.TrimEnd(',');
- }
-
- /*
- * formatted: The complete name of the contact. (DOMString)
- familyName: The contacts family name. (DOMString)
- givenName: The contacts given name. (DOMString)
- middleName: The contacts middle name. (DOMString)
- honorificPrefix: The contacts prefix (example Mr. or Dr.) (DOMString)
- honorificSuffix: The contacts suffix (example Esq.). (DOMString)
- */
- private string FormatJSONName(Contact con)
- {
- string retVal = "";
- string formatStr = "\"formatted\":\"{0}\"," +
- "\"familyName\":\"{1}\"," +
- "\"givenName\":\"{2}\"," +
- "\"middleName\":\"{3}\"," +
- "\"honorificPrefix\":\"{4}\"," +
- "\"honorificSuffix\":\"{5}\"";
-
- if (con.CompleteName != null)
- {
- retVal = string.Format(formatStr,
- EscapeJson(con.CompleteName.FirstName + " " + con.CompleteName.LastName), // TODO: does this need suffix? middlename?
- EscapeJson(con.CompleteName.LastName),
- EscapeJson(con.CompleteName.FirstName),
- EscapeJson(con.CompleteName.MiddleName),
- EscapeJson(con.CompleteName.Title),
- EscapeJson(con.CompleteName.Suffix));
- }
- else
- {
- retVal = string.Format(formatStr,"","","","","","");
- }
-
- return "{" + retVal + "}";
- }
-
- private string FormatJSONContact(Contact con, string[] fields)
- {
-
- string contactFormatStr = "\"id\":\"{0}\"," +
- "\"displayName\":\"{1}\"," +
- "\"nickname\":\"{2}\"," +
- "\"phoneNumbers\":[{3}]," +
- "\"emails\":[{4}]," +
- "\"addresses\":[{5}]," +
- "\"urls\":[{6}]," +
- "\"name\":{7}," +
- "\"note\":\"{8}\"," +
- "\"birthday\":\"{9}\"";
-
-
- string jsonContact = String.Format(contactFormatStr,
- con.GetHashCode(),
- EscapeJson(con.DisplayName),
- EscapeJson(con.CompleteName != null ? con.CompleteName.Nickname : ""),
- FormatJSONPhoneNumbers(con),
- FormatJSONEmails(con),
- FormatJSONAddresses(con),
- FormatJSONWebsites(con),
- FormatJSONName(con),
- EscapeJson(con.Notes.FirstOrDefault()),
- EscapeJson(Convert.ToString(con.Birthdays.FirstOrDefault())));
-
- return "{" + jsonContact + "}";
-
- }
-
-
- private static string EscapeJson(string str)
- {
- if (String.IsNullOrEmpty(str))
- {
- return str;
- }
-
- return str.Replace("\n", "\\n").Replace("\r", "\\r").Replace("\t", "\\t").Replace("\"", "\\\"").Replace("&", "\\&");
- }
- }
-}
diff --git a/www/Contact.js b/www/Contact.js
deleted file mode 100644
index 9c46a0c..0000000
--- a/www/Contact.js
+++ /dev/null
@@ -1,177 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var argscheck = require('cordova/argscheck'),
- exec = require('cordova/exec'),
- ContactError = require('./ContactError'),
- utils = require('cordova/utils');
-
-/**
-* Converts primitives into Complex Object
-* Currently only used for Date fields
-*/
-function convertIn(contact) {
- var value = contact.birthday;
- try {
- contact.birthday = new Date(parseFloat(value));
- } catch (exception){
- console.log("Cordova Contact convertIn error: exception creating date.");
- }
- return contact;
-}
-
-/**
-* Converts Complex objects into primitives
-* Only conversion at present is for Dates.
-**/
-
-function convertOut(contact) {
- var value = contact.birthday;
- if (value !== null) {
- // try to make it a Date object if it is not already
- if (!utils.isDate(value)){
- try {
- value = new Date(value);
- } catch(exception){
- value = null;
- }
- }
- if (utils.isDate(value)){
- value = value.valueOf(); // convert to milliseconds
- }
- contact.birthday = value;
- }
- return contact;
-}
-
-/**
-* Contains information about a single contact.
-* @constructor
-* @param {DOMString} id unique identifier
-* @param {DOMString} displayName
-* @param {ContactName} name
-* @param {DOMString} nickname
-* @param {Array.<ContactField>} phoneNumbers array of phone numbers
-* @param {Array.<ContactField>} emails array of email addresses
-* @param {Array.<ContactAddress>} addresses array of addresses
-* @param {Array.<ContactField>} ims instant messaging user ids
-* @param {Array.<ContactOrganization>} organizations
-* @param {DOMString} birthday contact's birthday
-* @param {DOMString} note user notes about contact
-* @param {Array.<ContactField>} photos
-* @param {Array.<ContactField>} categories
-* @param {Array.<ContactField>} urls contact's web sites
-*/
-var Contact = function (id, displayName, name, nickname, phoneNumbers, emails, addresses,
- ims, organizations, birthday, note, photos, categories, urls) {
- this.id = id || null;
- this.rawId = null;
- this.displayName = displayName || null;
- this.name = name || null; // ContactName
- this.nickname = nickname || null;
- this.phoneNumbers = phoneNumbers || null; // ContactField[]
- this.emails = emails || null; // ContactField[]
- this.addresses = addresses || null; // ContactAddress[]
- this.ims = ims || null; // ContactField[]
- this.organizations = organizations || null; // ContactOrganization[]
- this.birthday = birthday || null;
- this.note = note || null;
- this.photos = photos || null; // ContactField[]
- this.categories = categories || null; // ContactField[]
- this.urls = urls || null; // ContactField[]
-};
-
-/**
-* Removes contact from device storage.
-* @param successCB success callback
-* @param errorCB error callback
-*/
-Contact.prototype.remove = function(successCB, errorCB) {
- argscheck.checkArgs('FF', 'Contact.remove', arguments);
- var fail = errorCB && function(code) {
- errorCB(new ContactError(code));
- };
- if (this.id === null) {
- fail(ContactError.UNKNOWN_ERROR);
- }
- else {
- exec(successCB, fail, "Contacts", "remove", [this.id]);
- }
-};
-
-/**
-* Creates a deep copy of this Contact.
-* With the contact ID set to null.
-* @return copy of this Contact
-*/
-Contact.prototype.clone = function() {
- var clonedContact = utils.clone(this);
- clonedContact.id = null;
- clonedContact.rawId = null;
-
- function nullIds(arr) {
- if (arr) {
- for (var i = 0; i < arr.length; ++i) {
- arr[i].id = null;
- }
- }
- }
-
- // Loop through and clear out any id's in phones, emails, etc.
- nullIds(clonedContact.phoneNumbers);
- nullIds(clonedContact.emails);
- nullIds(clonedContact.addresses);
- nullIds(clonedContact.ims);
- nullIds(clonedContact.organizations);
- nullIds(clonedContact.categories);
- nullIds(clonedContact.photos);
- nullIds(clonedContact.urls);
- return clonedContact;
-};
-
-/**
-* Persists contact to device storage.
-* @param successCB success callback
-* @param errorCB error callback
-*/
-Contact.prototype.save = function(successCB, errorCB) {
- argscheck.checkArgs('FFO', 'Contact.save', arguments);
- var fail = errorCB && function(code) {
- errorCB(new ContactError(code));
- };
- var success = function(result) {
- if (result) {
- if (successCB) {
- var fullContact = require('./contacts').create(result);
- successCB(convertIn(fullContact));
- }
- }
- else {
- // no Entry object returned
- fail(ContactError.UNKNOWN_ERROR);
- }
- };
- var dupContact = convertOut(utils.clone(this));
- exec(success, fail, "Contacts", "save", [dupContact]);
-};
-
-
-module.exports = Contact;
diff --git a/www/ContactAddress.js b/www/ContactAddress.js
deleted file mode 100644
index 3d39086..0000000
--- a/www/ContactAddress.js
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
-* Contact address.
-* @constructor
-* @param {DOMString} id unique identifier, should only be set by native code
-* @param formatted // NOTE: not a W3C standard
-* @param streetAddress
-* @param locality
-* @param region
-* @param postalCode
-* @param country
-*/
-
-var ContactAddress = function(pref, type, formatted, streetAddress, locality, region, postalCode, country) {
- this.id = null;
- this.pref = (typeof pref != 'undefined' ? pref : false);
- this.type = type || null;
- this.formatted = formatted || null;
- this.streetAddress = streetAddress || null;
- this.locality = locality || null;
- this.region = region || null;
- this.postalCode = postalCode || null;
- this.country = country || null;
-};
-
-module.exports = ContactAddress;
diff --git a/www/ContactError.js b/www/ContactError.js
deleted file mode 100644
index 01b229a..0000000
--- a/www/ContactError.js
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
- * ContactError.
- * An error code assigned by an implementation when an error has occurred
- * @constructor
- */
-var ContactError = function(err) {
- this.code = (typeof err != 'undefined' ? err : null);
-};
-
-/**
- * Error codes
- */
-ContactError.UNKNOWN_ERROR = 0;
-ContactError.INVALID_ARGUMENT_ERROR = 1;
-ContactError.TIMEOUT_ERROR = 2;
-ContactError.PENDING_OPERATION_ERROR = 3;
-ContactError.IO_ERROR = 4;
-ContactError.NOT_SUPPORTED_ERROR = 5;
-ContactError.PERMISSION_DENIED_ERROR = 20;
-
-module.exports = ContactError;
diff --git a/www/ContactField.js b/www/ContactField.js
deleted file mode 100644
index e84107a..0000000
--- a/www/ContactField.js
+++ /dev/null
@@ -1,37 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
-* Generic contact field.
-* @constructor
-* @param {DOMString} id unique identifier, should only be set by native code // NOTE: not a W3C standard
-* @param type
-* @param value
-* @param pref
-*/
-var ContactField = function(type, value, pref) {
- this.id = null;
- this.type = (type && type.toString()) || null;
- this.value = (value && value.toString()) || null;
- this.pref = (typeof pref != 'undefined' ? pref : false);
-};
-
-module.exports = ContactField;
diff --git a/www/ContactFindOptions.js b/www/ContactFindOptions.js
deleted file mode 100644
index bd8bf35..0000000
--- a/www/ContactFindOptions.js
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
- * ContactFindOptions.
- * @constructor
- * @param filter used to match contacts against
- * @param multiple boolean used to determine if more than one contact should be returned
- */
-
-var ContactFindOptions = function(filter, multiple) {
- this.filter = filter || '';
- this.multiple = (typeof multiple != 'undefined' ? multiple : false);
-};
-
-module.exports = ContactFindOptions;
diff --git a/www/ContactName.js b/www/ContactName.js
deleted file mode 100644
index 15cf60b..0000000
--- a/www/ContactName.js
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
-* Contact name.
-* @constructor
-* @param formatted // NOTE: not part of W3C standard
-* @param familyName
-* @param givenName
-* @param middle
-* @param prefix
-* @param suffix
-*/
-var ContactName = function(formatted, familyName, givenName, middle, prefix, suffix) {
- this.formatted = formatted || null;
- this.familyName = familyName || null;
- this.givenName = givenName || null;
- this.middleName = middle || null;
- this.honorificPrefix = prefix || null;
- this.honorificSuffix = suffix || null;
-};
-
-module.exports = ContactName;
diff --git a/www/ContactOrganization.js b/www/ContactOrganization.js
deleted file mode 100644
index 5dd242b..0000000
--- a/www/ContactOrganization.js
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-/**
-* Contact organization.
-* @constructor
-* @param {DOMString} id unique identifier, should only be set by native code // NOTE: not a W3C standard
-* @param name
-* @param dept
-* @param title
-* @param startDate
-* @param endDate
-* @param location
-* @param desc
-*/
-
-var ContactOrganization = function(pref, type, name, dept, title) {
- this.id = null;
- this.pref = (typeof pref != 'undefined' ? pref : false);
- this.type = type || null;
- this.name = name || null;
- this.department = dept || null;
- this.title = title || null;
-};
-
-module.exports = ContactOrganization;
diff --git a/www/contacts.js b/www/contacts.js
deleted file mode 100644
index 5e6b4db..0000000
--- a/www/contacts.js
+++ /dev/null
@@ -1,76 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var argscheck = require('cordova/argscheck'),
- exec = require('cordova/exec'),
- ContactError = require('./ContactError'),
- utils = require('cordova/utils'),
- Contact = require('./Contact');
-
-/**
-* Represents a group of Contacts.
-* @constructor
-*/
-var contacts = {
- /**
- * Returns an array of Contacts matching the search criteria.
- * @param fields that should be searched
- * @param successCB success callback
- * @param errorCB error callback
- * @param {ContactFindOptions} options that can be applied to contact searching
- * @return array of Contacts matching search criteria
- */
- find:function(fields, successCB, errorCB, options) {
- argscheck.checkArgs('afFO', 'contacts.find', arguments);
- if (!fields.length) {
- errorCB && errorCB(new ContactError(ContactError.INVALID_ARGUMENT_ERROR));
- } else {
- var win = function(result) {
- var cs = [];
- for (var i = 0, l = result.length; i < l; i++) {
- cs.push(contacts.create(result[i]));
- }
- successCB(cs);
- };
- exec(win, errorCB, "Contacts", "search", [fields, options]);
- }
- },
-
- /**
- * This function creates a new contact, but it does not persist the contact
- * to device storage. To persist the contact to device storage, invoke
- * contact.save().
- * @param properties an object whose properties will be examined to create a new Contact
- * @returns new Contact object
- */
- create:function(properties) {
- argscheck.checkArgs('O', 'contacts.create', arguments);
- var contact = new Contact();
- for (var i in properties) {
- if (typeof contact[i] !== 'undefined' && properties.hasOwnProperty(i)) {
- contact[i] = properties[i];
- }
- }
- return contact;
- }
-};
-
-module.exports = contacts;
diff --git a/www/ios/Contact.js b/www/ios/Contact.js
deleted file mode 100644
index b40c41a..0000000
--- a/www/ios/Contact.js
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var exec = require('cordova/exec'),
- ContactError = require('./ContactError');
-
-/**
- * Provides iOS Contact.display API.
- */
-module.exports = {
- display : function(errorCB, options) {
- /*
- * Display a contact using the iOS Contact Picker UI
- * NOT part of W3C spec so no official documentation
- *
- * @param errorCB error callback
- * @param options object
- * allowsEditing: boolean AS STRING
- * "true" to allow editing the contact
- * "false" (default) display contact
- */
-
- if (this.id === null) {
- if (typeof errorCB === "function") {
- var errorObj = new ContactError(ContactError.UNKNOWN_ERROR);
- errorCB(errorObj);
- }
- }
- else {
- exec(null, errorCB, "Contacts","displayContact", [this.id, options]);
- }
- }
-};
diff --git a/www/ios/contacts.js b/www/ios/contacts.js
deleted file mode 100644
index 67cf421..0000000
--- a/www/ios/contacts.js
+++ /dev/null
@@ -1,62 +0,0 @@
-/*
- *
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- *
-*/
-
-var exec = require('cordova/exec');
-
-/**
- * Provides iOS enhanced contacts API.
- */
-module.exports = {
- newContactUI : function(successCallback) {
- /*
- * Create a contact using the iOS Contact Picker UI
- * NOT part of W3C spec so no official documentation
- *
- * returns: the id of the created contact as param to successCallback
- */
- exec(successCallback, null, "Contacts","newContact", []);
- },
- chooseContact : function(successCallback, options) {
- /*
- * Select a contact using the iOS Contact Picker UI
- * NOT part of W3C spec so no official documentation
- *
- * @param errorCB error callback
- * @param options object
- * allowsEditing: boolean AS STRING
- * "true" to allow editing the contact
- * "false" (default) display contact
- * fields: array of fields to return in contact object (see ContactOptions.fields)
- *
- * @returns
- * id of contact selected
- * ContactObject
- * if no fields provided contact contains just id information
- * if fields provided contact object contains information for the specified fields
- *
- */
- var win = function(result) {
- var fullContact = require('./contacts').create(result);
- successCallback(fullContact.id, fullContact);
- };
- exec(win, null, "Contacts","chooseContact", [options]);
- }
-};