Home Reference Source

src/contacts/W3cContacts.js

import {getDeviceId} from '../utils';

const NUM_MAX_PHONES_BY_CONTACT = 10;

function getAvatar(photos) {
	if (photos && photos.length > 0) {
		return photos[0].value;
	}
	return null;
}

function parsePhones(rawPhoneNumbers) {
	return rawPhoneNumbers.slice(0, NUM_MAX_PHONES_BY_CONTACT).map((phone) => {
		const name = phone.type;
		const address = phone.value.replace(/\s/g, '');
		return {name, address};
	});
}

function parseEmails(rawEmails) {
	if (!rawEmails) {
		return [];
	}
	return rawEmails.map(email => ({
		type: email.type,
		email: email.value,
	}));
}

function parseName(contact, phones) {
	return contact.displayName || (contact.name && contact.name.formatted ? contact.name.formatted : phones[0].address);
}

/** @protected */
export const W3cContacts = (stack, window) => {

	const navigator = window.navigator;
	const deviceId = getDeviceId();
	const ContactFindOptions = window.ContactFindOptions;

	function existDeviceId() {
		if (!deviceId) {
			throw Error('W3C Contacts: Can`t get device ID');
		}
	}

	function w3cContactToWacContact(contact) {
		existDeviceId();
		let phones = parsePhones(contact.phoneNumbers);
		let emails = parseEmails(contact.emails);
		let name = parseName(contact, phones);
		return {
			contactDeviceId: `w3c-contact-${contact.id}-${deviceId}`,
			name: name,
			source: 'device',
			phones: phones,
			emails: emails,
			avatar: getAvatar(contact.photos),
			deviceId: deviceId,
		};
	}

	function avatarW3cContactToWacContact(contact) {
		existDeviceId();
		return {
			contactDeviceId: `w3c-contact-${contact.id}-${deviceId}`,
			avatar: getAvatar(contact.photos),
		};
	}

	function getW3cContacts() {
		return new Promise((resolve, reject) => {
			let contactFindOptions = new ContactFindOptions();
			contactFindOptions.multiple = true;
			contactFindOptions.hasPhoneNumber = true;
			contactFindOptions.desiredFields = [
				navigator.contacts.fieldType.displayName,
				navigator.contacts.fieldType.name,
				navigator.contacts.fieldType.phoneNumbers,
				navigator.contacts.fieldType.note,
				navigator.contacts.fieldType.emails,
			];
			navigator.contacts.find(['*'], resolve, reject, contactFindOptions);
		});
	}

	function getAvatarW3cContacts(fields = '*', filter = '') {
		return new Promise((resolve, reject) => {
			let contactFindOptions = new ContactFindOptions();
			contactFindOptions.multiple = true;
			contactFindOptions.hasPhoneNumber = true;
			contactFindOptions.desiredFields = [
				navigator.contacts.fieldType.photos,
			];
			if (filter) {
				contactFindOptions.filter = filter;
			}
			navigator.contacts.find([fields], resolve, reject, contactFindOptions);
		});
	}

	function allowedContacts() {
		return stack.getCapabilities().includes('w3c-contacts-api') && navigator.contacts;
	}

	async function getContacts() {
		if (!allowedContacts()) {
			return [];
		}
		const contacts = await getW3cContacts();
		return contacts
			.filter(contact => contact.phoneNumbers && contact.phoneNumbers.length > 0)
			.map(w3cContactToWacContact);
	}

	async function getAvatarContacts() {
		if (!allowedContacts()) {
			return [];
		}
		const contacts = await getAvatarW3cContacts();
		return contacts.map(avatarW3cContactToWacContact);
	}

	return {
		getContacts: getContacts,
		getAvatarContacts: getAvatarContacts,
	};
};