Skip to content

Commit eae8c9a

Browse files
committed
Step 15.4: Implement getContactsFromAddressbook in the phone service
1 parent a953d70 commit eae8c9a

File tree

1 file changed

+59
-1
lines changed

1 file changed

+59
-1
lines changed

src/services/phone.ts

Lines changed: 59 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ import { Accounts } from 'meteor/accounts-base';
33
import { Meteor } from 'meteor/meteor';
44
import { Platform } from 'ionic-angular';
55
import { Sim } from '@ionic-native/sim';
6+
import { Contact, ContactFieldType, Contacts, IContactField, IContactFindOptions } from "@ionic-native/contacts";
67
import { SmsReceiver } from "../ionic/sms-receiver";
78
import * as Bluebird from "bluebird";
89
import { TWILIO_SMS_NUMBERS } from "api/models";
@@ -12,7 +13,8 @@ import { Observable } from "rxjs";
1213
export class PhoneService {
1314
constructor(private platform: Platform,
1415
private sim: Sim,
15-
private smsReceiver: SmsReceiver) {
16+
private smsReceiver: SmsReceiver,
17+
private contacts: Contacts) {
1618
Bluebird.promisifyAll(this.smsReceiver);
1719
}
1820

@@ -64,6 +66,62 @@ export class PhoneService {
6466
}
6567
}
6668

69+
getContactsFromAddressbook(): Promise<string[]> {
70+
const getContacts = (): Promise<Contact[]> => {
71+
if (!this.platform.is('cordova')) {
72+
return Promise.reject(new Error('Cannot get contacts: not cordova.'));
73+
}
74+
75+
const fields: ContactFieldType[] = ["phoneNumbers"];
76+
const options: IContactFindOptions = {
77+
filter: "",
78+
multiple: true,
79+
desiredFields: ["phoneNumbers"],
80+
hasPhoneNumber: true
81+
};
82+
return this.contacts.find(fields, options);
83+
};
84+
85+
const cleanPhoneNumber = (phoneNumber: string): string => {
86+
const phoneNumberNoSpaces: string = phoneNumber.replace(/ /g, '');
87+
88+
if (phoneNumberNoSpaces.charAt(0) === '+') {
89+
return phoneNumberNoSpaces;
90+
} else if (phoneNumberNoSpaces.substring(0, 2) === "00") {
91+
return '+' + phoneNumberNoSpaces.slice(2);
92+
} else {
93+
// Use user's international prefix when absent
94+
// FIXME: update meteor-accounts-phone typings
95+
const prefix: string = (<any>Meteor.user()).phone.number.substring(0, 3);
96+
97+
return prefix + phoneNumberNoSpaces;
98+
}
99+
};
100+
101+
return new Promise((resolve, reject) => {
102+
getContacts()
103+
.then((contacts: Contact[]) => {
104+
const arrayOfArrays: string[][] = contacts
105+
.map((contact: Contact) => {
106+
return contact.phoneNumbers
107+
.filter((phoneNumber: IContactField) => {
108+
return phoneNumber.type === "mobile";
109+
}).map((phoneNumber: IContactField) => {
110+
return cleanPhoneNumber(phoneNumber.value);
111+
}).filter((phoneNumber: string) => {
112+
return phoneNumber.slice(1).match(/^[0-9]+$/) && phoneNumber.length >= 8;
113+
});
114+
});
115+
const flattenedArray: string[] = [].concat(...arrayOfArrays);
116+
const uniqueArray: string[] = [...new Set(flattenedArray)];
117+
resolve(uniqueArray);
118+
})
119+
.catch((e: Error) => {
120+
reject(e);
121+
});
122+
});
123+
}
124+
67125
verify(phoneNumber: string): Promise<void> {
68126
return new Promise<void>((resolve, reject) => {
69127
Accounts.requestPhoneVerification(phoneNumber, (e: Error) => {

0 commit comments

Comments
 (0)