nativescript-contacts-lite
Version:
NativeScript plugin providing pretty fast read-only access to the iOS and Android contact directory
209 lines (171 loc) • 7.11 kB
JavaScript
var constants = require("./constants");
var imageSource = require("image-source");
/*
permissions handling is only relevant for Android, always resolve on iOS
*/
exports.handlePermission = (() => {
return new Promise((resolve, reject) => {
const status = CNAuthorizationStatus[CNContactStore.authorizationStatusForEntityType(CNEntityType.Contacts)];
if (status==="CNAuthorizationStatusAuthorized") { resolve(); }
else if (status==="CNAuthorizationStatusNotDetermined") {
requestPermission()
.then(() => { resolve(); })
.catch((error) => { reject(error); });
} else {
reject(`Unable to obtain permission to read contacts: ${status}`);
}
});
});
let requestPermission = (() => {
return new Promise((resolve, reject) => {
const contactStore = CNContactStore.new();
contactStore.requestAccessForEntityTypeCompletionHandler(CNEntityType.Contacts, () => {
exports.handlePermission()
.then(() => { resolve(); })
.catch((error) => { reject(error); });
});
});
});
let getiOSValue = function(key, contactData){
return contactData.isKeyAvailable(key) ? contactData[key] : null;
};
/*
Takes a native iOS contact row and converts to json object for new contact
Arguments
1: contact - the cursor returned by iOS' data store
2: fields - those the user is interested in (skip irrelevant properties for speedup)
*/
exports.convertNativeCursorToContact = (c,fields) => {
let contact = {}; // contact object to return if creatng a new record
contact.contact_id = getiOSValue("identifier", c);
/* display_name */
if (fields.indexOf("display_name") > -1) {
contact.display_name = `${getiOSValue("givenName", c).trim()} ${getiOSValue("familyName", c).trim()}`.trim();
}
/* name_details */
if (fields.indexOf("name_details") > -1) {
var record = {};
record.family = getiOSValue("familyName", c);
record.given = getiOSValue("givenName", c);
record.middle = getiOSValue("middleName", c);
record.prefix = getiOSValue("namePrefix", c);
record.suffix = getiOSValue("nameSuffix", c);
if (!contact.hasOwnProperty('name_details')) { contact.name_details = []; }
contact.name_details.push(record);
}
/* phone */
if (fields.indexOf("phone") > -1) {
if (!contact.hasOwnProperty('phone')) { contact.phone = []; }
for (var i=0; i < c.phoneNumbers.count; i++) {
var pdata = c.phoneNumbers[i];
contact.phone.push({
//id: pdata.identifier,
type: constants.getPhoneLabel(pdata.label),
number: pdata.value.stringValue
});
}
}
/* photo */
if (fields.indexOf("photo") > -1) {
contact.photo = null;
if (c.imageDataAvailable) {
var photo = imageSource.fromData(c.imageData);
if (photo) { contact.photo = "data:image/png;base64,"+photo.toBase64String("png"); }
}
}
/* thumbnail */
if (fields.indexOf("thumbnail") > -1) {
contact.thumbnail = null;
if (c.imageDataAvailable) {
var thumb = imageSource.fromData(c.thumbnailImageData);
if (thumb) { contact.thumbnail = "data:image/png;base64,"+thumb.toBase64String("png"); }
}
}
/* organization */
if (fields.indexOf("organization") > -1) {
var record = {}
record.title = getiOSValue("jobTitle", c);
record.department = getiOSValue("departmentName", c);
record.company = getiOSValue("organizationName", c);
if (!contact.hasOwnProperty('organization')) { contact.organization = []; }
contact.organization.push(record);
}
/* nickname */
if (fields.indexOf("nickname") > -1) {
var record = {};
record.name = getiOSValue("nickname", c);
if (!contact.hasOwnProperty('nickname')) { contact.nickname = []; }
contact.nickname.push(record);
}
/* note */
if (fields.indexOf("note") > -1) {
var record = {};
var columnValue = getiOSValue("notes", c);
if (columnValue!=null && columnValue!='') { record.note = columnValue; } else { record = null; }
if (!contact.hasOwnProperty('note')) { contact.note = []; }
if (record!=null) { contact.note.push(record); }
}
/* email */
if (fields.indexOf("email") > -1) {
if (!contact.hasOwnProperty('email')) { contact.email = []; }
for (var i=0; i < c.emailAddresses.count; i++) {
var edata = c.emailAddresses[i];
contact.email.push({
type: constants.getGenericLabel(edata.label),
address: edata.value
});
}
}
/* website */
if (fields.indexOf("website") > -1) {
if (!contact.hasOwnProperty('website')) { contact.website = []; }
for (var i=0; i < c.urlAddresses.count; i++) {
var urldata = c.urlAddresses[i];
contact.website.push({
type: constants.getWebsiteLabel(urldata.label),
url: urldata.value
});
}
}
/* address */
if (fields.indexOf("address") > -1) {
if (!contact.hasOwnProperty('address')) { contact.address = []; }
for (var i=0; i < c.postalAddresses.count; i++) {
var postaldata = c.postalAddresses[i];
contact.address.push({
type: constants.getGenericLabel(postaldata.label),
street: postaldata.value.street,
city: postaldata.value.city,
region: postaldata.value.state,
postcode: postaldata.value.postalCode,
country: postaldata.value.country,
street: postaldata.value.street,
formatted_address: null
});
}
}
return contact;
};
/*
returns an array with names of columns to fetch from Android storage backend
constants map to Android's "dataX" fields, e.g.
android.provider.ContactsContract.CommonDataKinds.Phone.NUMBER = "data1"
see: https://developer.android.com/reference/android/provider/ContactsContract.Data.html
*/
exports.getIOSQueryColumns = (fields) => {
let columnsToFetch = [];
//columnsToFetch.push("contact_id","mimetype","account_name");
if (fields.indexOf('display_name') > -1) { columnsToFetch.push("givenName","familyName"); }
if (fields.indexOf('name_details') > -1) { columnsToFetch.push("givenName","familyName","middleName","namePrefix","nameSuffix"); }
if (fields.indexOf('phone') > -1) { columnsToFetch.push("phoneNumbers"); }
if (fields.indexOf('email') > -1) { columnsToFetch.push("emailAddresses"); }
if (fields.indexOf('address') > -1) { columnsToFetch.push("postalAddresses"); }
if (fields.indexOf('nickname') > -1) { columnsToFetch.push("nickname"); }
if (fields.indexOf('organization') > -1) { columnsToFetch.push("jobTitle", "departmentName", "organizationName"); }
if (fields.indexOf('note') > -1) { columnsToFetch.push("notes"); }
if (fields.indexOf('photo') > -1) { columnsToFetch.push(CNContactImageDataAvailableKey, CNContactImageDataKey); }
if (fields.indexOf('thumbnail') > -1) { columnsToFetch.push(CNContactImageDataAvailableKey, CNContactThumbnailImageDataKey); }
if (fields.indexOf('website') > -1) { columnsToFetch.push("urlAddresses"); }
// filter out any nulls & duplicates
return columnsToFetch.filter((item, index, self) => { return (item != null && index == self.indexOf(item)) });
}