@aalzehla/capacitor-contacts 0.0.5 → 8.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AalzehlaCapacitorContacts.podspec +2 -2
- package/README.md +69 -45
- package/android/build.gradle +15 -12
- package/android/src/main/java/getcapacitor/community/contacts/BiMap.java +45 -0
- package/android/src/main/java/getcapacitor/community/contacts/ContactPayload.java +286 -0
- package/android/src/main/java/getcapacitor/community/contacts/Contacts.java +384 -0
- package/android/src/main/java/getcapacitor/community/contacts/ContactsPlugin.java +255 -0
- package/android/src/main/java/getcapacitor/community/contacts/CreateContactInput.java +233 -0
- package/android/src/main/java/getcapacitor/community/contacts/GetContactsProjectionInput.java +214 -0
- package/dist/esm/definitions.d.ts +285 -19
- package/dist/esm/definitions.js +47 -1
- package/dist/esm/definitions.js.map +1 -1
- package/dist/esm/index.d.ts +3 -3
- package/dist/esm/index.js +3 -3
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/web.d.ts +9 -7
- package/dist/esm/web.js +21 -7
- package/dist/esm/web.js.map +1 -1
- package/dist/plugin.cjs.js +73 -14
- package/dist/plugin.cjs.js.map +1 -1
- package/dist/plugin.js +74 -15
- package/dist/plugin.js.map +1 -1
- package/ios/Plugin/BiMap.swift +42 -0
- package/ios/Plugin/ContactPayload.swift +227 -0
- package/ios/Plugin/Contacts.swift +227 -0
- package/ios/Plugin/ContactsPlugin.h +10 -0
- package/ios/Plugin/ContactsPlugin.m +14 -0
- package/ios/Plugin/ContactsPlugin.swift +221 -0
- package/ios/Plugin/CreateContactInput.swift +187 -0
- package/ios/Plugin/GetContactsProjectionInput.swift +119 -0
- package/ios/Plugin/Info.plist +24 -0
- package/package.json +32 -29
- package/Package.swift +0 -28
- package/android/src/main/java/com/aalzehla/capacitor/contacts/CapacitorContactsPlugin.java +0 -177
- package/android/src/main/java/com/aalzehla/capacitor/contacts/ContactDataExtractorVisitor.java +0 -122
- package/android/src/main/java/com/aalzehla/capacitor/contacts/ContactExtractorVisitor.java +0 -31
- package/android/src/main/java/com/aalzehla/capacitor/contacts/PluginContactFields.java +0 -17
- package/android/src/main/java/com/aalzehla/capacitor/contacts/contentQuery/ContentQuery.java +0 -83
- package/android/src/main/java/com/aalzehla/capacitor/contacts/contentQuery/ContentQueryService.java +0 -60
- package/android/src/main/java/com/aalzehla/capacitor/contacts/utils/Utils.java +0 -19
- package/android/src/main/java/com/aalzehla/capacitor/contacts/utils/Visitable.java +0 -5
- package/android/src/main/java/com/aalzehla/capacitor/contacts/utils/Visitor.java +0 -5
- package/dist/docs.json +0 -145
- package/ios/Sources/CapacitorContactsPlugin/CapacitorContactsPlugin.swift +0 -168
- package/ios/Tests/CapacitorContactsPluginTests/CapacitorContactsPluginTests.swift +0 -15
package/dist/plugin.js
CHANGED
|
@@ -1,29 +1,88 @@
|
|
|
1
|
-
var
|
|
1
|
+
var capacitorContacts = (function (exports, core) {
|
|
2
2
|
'use strict';
|
|
3
3
|
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
exports.PhoneType = void 0;
|
|
5
|
+
(function (PhoneType) {
|
|
6
|
+
// Home / Work
|
|
7
|
+
PhoneType["Home"] = "home";
|
|
8
|
+
PhoneType["Work"] = "work";
|
|
9
|
+
// Other / Custom
|
|
10
|
+
PhoneType["Other"] = "other";
|
|
11
|
+
PhoneType["Custom"] = "custom";
|
|
12
|
+
// Phone specific
|
|
13
|
+
PhoneType["Mobile"] = "mobile";
|
|
14
|
+
PhoneType["FaxWork"] = "fax_work";
|
|
15
|
+
PhoneType["FaxHome"] = "fax_home";
|
|
16
|
+
PhoneType["Pager"] = "pager";
|
|
17
|
+
PhoneType["Callback"] = "callback";
|
|
18
|
+
PhoneType["Car"] = "car";
|
|
19
|
+
PhoneType["CompanyMain"] = "company_main";
|
|
20
|
+
PhoneType["Isdn"] = "isdn";
|
|
21
|
+
PhoneType["Main"] = "main";
|
|
22
|
+
PhoneType["OtherFax"] = "other_fax";
|
|
23
|
+
PhoneType["Radio"] = "radio";
|
|
24
|
+
PhoneType["Telex"] = "telex";
|
|
25
|
+
PhoneType["TtyTdd"] = "tty_tdd";
|
|
26
|
+
PhoneType["WorkMobile"] = "work_mobile";
|
|
27
|
+
PhoneType["WorkPager"] = "work_pager";
|
|
28
|
+
PhoneType["Assistant"] = "assistant";
|
|
29
|
+
PhoneType["Mms"] = "mms";
|
|
30
|
+
})(exports.PhoneType || (exports.PhoneType = {}));
|
|
31
|
+
exports.EmailType = void 0;
|
|
32
|
+
(function (EmailType) {
|
|
33
|
+
// Home / Work
|
|
34
|
+
EmailType["Home"] = "home";
|
|
35
|
+
EmailType["Work"] = "work";
|
|
36
|
+
// Other / Custom
|
|
37
|
+
EmailType["Other"] = "other";
|
|
38
|
+
EmailType["Custom"] = "custom";
|
|
39
|
+
// Email specific
|
|
40
|
+
EmailType["Mobile"] = "mobile";
|
|
41
|
+
})(exports.EmailType || (exports.EmailType = {}));
|
|
42
|
+
exports.PostalAddressType = void 0;
|
|
43
|
+
(function (PostalAddressType) {
|
|
44
|
+
// Home / Work
|
|
45
|
+
PostalAddressType["Home"] = "home";
|
|
46
|
+
PostalAddressType["Work"] = "work";
|
|
47
|
+
// Other / Custom
|
|
48
|
+
PostalAddressType["Other"] = "other";
|
|
49
|
+
PostalAddressType["Custom"] = "custom";
|
|
50
|
+
})(exports.PostalAddressType || (exports.PostalAddressType = {}));
|
|
51
|
+
|
|
52
|
+
const Contacts = core.registerPlugin('Contacts', {
|
|
53
|
+
web: () => Promise.resolve().then(function () { return web; }).then((m) => new m.ContactsWeb()),
|
|
6
54
|
});
|
|
7
55
|
|
|
8
|
-
class
|
|
9
|
-
|
|
10
|
-
|
|
56
|
+
class ContactsWeb extends core.WebPlugin {
|
|
57
|
+
async checkPermissions() {
|
|
58
|
+
throw this.unimplemented('Not implemented on web.');
|
|
59
|
+
}
|
|
60
|
+
async requestPermissions() {
|
|
61
|
+
throw this.unimplemented('Not implemented on web.');
|
|
62
|
+
}
|
|
63
|
+
async getContact() {
|
|
64
|
+
throw this.unimplemented('Not implemented on web.');
|
|
65
|
+
}
|
|
66
|
+
async getContacts() {
|
|
67
|
+
throw this.unimplemented('Not implemented on web.');
|
|
68
|
+
}
|
|
69
|
+
async createContact() {
|
|
70
|
+
throw this.unimplemented('Not implemented on web.');
|
|
71
|
+
}
|
|
72
|
+
async deleteContact() {
|
|
73
|
+
throw this.unimplemented('Not implemented on web.');
|
|
74
|
+
}
|
|
75
|
+
async pickContact() {
|
|
76
|
+
throw this.unimplemented('Not implemented on web.');
|
|
11
77
|
}
|
|
12
|
-
async close() { }
|
|
13
78
|
}
|
|
14
|
-
const ContactPicker = new CapacitorContactsWeb();
|
|
15
|
-
const CapacitorContacts = ContactPicker;
|
|
16
79
|
|
|
17
80
|
var web = /*#__PURE__*/Object.freeze({
|
|
18
81
|
__proto__: null,
|
|
19
|
-
|
|
20
|
-
ContactPicker: ContactPicker,
|
|
21
|
-
CapacitorContacts: CapacitorContacts
|
|
82
|
+
ContactsWeb: ContactsWeb
|
|
22
83
|
});
|
|
23
84
|
|
|
24
|
-
exports.
|
|
25
|
-
|
|
26
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
85
|
+
exports.Contacts = Contacts;
|
|
27
86
|
|
|
28
87
|
return exports;
|
|
29
88
|
|
package/dist/plugin.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"plugin.js","sources":["esm/index.js","esm/web.js"],"sourcesContent":["import { registerPlugin } from '@capacitor/core';\nconst
|
|
1
|
+
{"version":3,"file":"plugin.js","sources":["esm/definitions.js","esm/index.js","esm/web.js"],"sourcesContent":["export var PhoneType;\n(function (PhoneType) {\n // Home / Work\n PhoneType[\"Home\"] = \"home\";\n PhoneType[\"Work\"] = \"work\";\n // Other / Custom\n PhoneType[\"Other\"] = \"other\";\n PhoneType[\"Custom\"] = \"custom\";\n // Phone specific\n PhoneType[\"Mobile\"] = \"mobile\";\n PhoneType[\"FaxWork\"] = \"fax_work\";\n PhoneType[\"FaxHome\"] = \"fax_home\";\n PhoneType[\"Pager\"] = \"pager\";\n PhoneType[\"Callback\"] = \"callback\";\n PhoneType[\"Car\"] = \"car\";\n PhoneType[\"CompanyMain\"] = \"company_main\";\n PhoneType[\"Isdn\"] = \"isdn\";\n PhoneType[\"Main\"] = \"main\";\n PhoneType[\"OtherFax\"] = \"other_fax\";\n PhoneType[\"Radio\"] = \"radio\";\n PhoneType[\"Telex\"] = \"telex\";\n PhoneType[\"TtyTdd\"] = \"tty_tdd\";\n PhoneType[\"WorkMobile\"] = \"work_mobile\";\n PhoneType[\"WorkPager\"] = \"work_pager\";\n PhoneType[\"Assistant\"] = \"assistant\";\n PhoneType[\"Mms\"] = \"mms\";\n})(PhoneType || (PhoneType = {}));\nexport var EmailType;\n(function (EmailType) {\n // Home / Work\n EmailType[\"Home\"] = \"home\";\n EmailType[\"Work\"] = \"work\";\n // Other / Custom\n EmailType[\"Other\"] = \"other\";\n EmailType[\"Custom\"] = \"custom\";\n // Email specific\n EmailType[\"Mobile\"] = \"mobile\";\n})(EmailType || (EmailType = {}));\nexport var PostalAddressType;\n(function (PostalAddressType) {\n // Home / Work\n PostalAddressType[\"Home\"] = \"home\";\n PostalAddressType[\"Work\"] = \"work\";\n // Other / Custom\n PostalAddressType[\"Other\"] = \"other\";\n PostalAddressType[\"Custom\"] = \"custom\";\n})(PostalAddressType || (PostalAddressType = {}));\n//# sourceMappingURL=definitions.js.map","import { registerPlugin } from '@capacitor/core';\nconst Contacts = registerPlugin('Contacts', {\n web: () => import('./web').then((m) => new m.ContactsWeb()),\n});\nexport * from './definitions';\nexport { Contacts };\n//# sourceMappingURL=index.js.map","import { WebPlugin } from '@capacitor/core';\nexport class ContactsWeb extends WebPlugin {\n async checkPermissions() {\n throw this.unimplemented('Not implemented on web.');\n }\n async requestPermissions() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getContact() {\n throw this.unimplemented('Not implemented on web.');\n }\n async getContacts() {\n throw this.unimplemented('Not implemented on web.');\n }\n async createContact() {\n throw this.unimplemented('Not implemented on web.');\n }\n async deleteContact() {\n throw this.unimplemented('Not implemented on web.');\n }\n async pickContact() {\n throw this.unimplemented('Not implemented on web.');\n }\n}\n//# sourceMappingURL=web.js.map"],"names":["PhoneType","EmailType","PostalAddressType","registerPlugin","WebPlugin"],"mappings":"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"}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
|
|
3
|
+
// Helper to enable bidirectional mapping.
|
|
4
|
+
public class BiMap<K: Hashable, V: Hashable> {
|
|
5
|
+
// The following map can be used for retrieving the key belonging to a certain value.
|
|
6
|
+
// This map is essentially the inverted version of `mapForValues`
|
|
7
|
+
private var mapForKeys: [V: K] = [:]
|
|
8
|
+
// The following map can be used for retrieving the value belonging to a certain key.
|
|
9
|
+
private var mapForValues: [K: V] = [:]
|
|
10
|
+
|
|
11
|
+
private var defaultKey: K
|
|
12
|
+
private var defaultValue: V
|
|
13
|
+
|
|
14
|
+
init(_ map: [K: V], _ defaultKey: K, _ defaultValue: V) {
|
|
15
|
+
self.mapForValues = map
|
|
16
|
+
|
|
17
|
+
for entry in map {
|
|
18
|
+
let key: K = entry.key
|
|
19
|
+
let value: V = entry.value
|
|
20
|
+
self.mapForKeys[value] = key
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
self.defaultKey = defaultKey
|
|
24
|
+
self.defaultValue = defaultValue
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
func getKey(_ v: V?) -> K {
|
|
28
|
+
let k: K? = self.mapForKeys[v ?? "" as! V]
|
|
29
|
+
guard let k = k else {
|
|
30
|
+
return self.defaultKey
|
|
31
|
+
}
|
|
32
|
+
return k
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func getValue(_ k: K?) -> V {
|
|
36
|
+
let v: V? = self.mapForValues[k ?? "" as! K]
|
|
37
|
+
guard let v = v else {
|
|
38
|
+
return self.defaultValue
|
|
39
|
+
}
|
|
40
|
+
return v
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Contacts
|
|
3
|
+
import Capacitor
|
|
4
|
+
|
|
5
|
+
public class ContactPayload {
|
|
6
|
+
|
|
7
|
+
// Id
|
|
8
|
+
private var contactId: String
|
|
9
|
+
|
|
10
|
+
// Name
|
|
11
|
+
private var name: JSObject = JSObject()
|
|
12
|
+
|
|
13
|
+
// Organization
|
|
14
|
+
private var organization: JSObject = JSObject()
|
|
15
|
+
|
|
16
|
+
// Birthday
|
|
17
|
+
private var birthday: JSObject = JSObject()
|
|
18
|
+
|
|
19
|
+
// Note
|
|
20
|
+
private var note: String?
|
|
21
|
+
|
|
22
|
+
// Phones
|
|
23
|
+
private var phones: JSArray = JSArray()
|
|
24
|
+
|
|
25
|
+
// Emails
|
|
26
|
+
private var emails: JSArray = JSArray()
|
|
27
|
+
|
|
28
|
+
// URLs
|
|
29
|
+
private var urls: JSArray = JSArray()
|
|
30
|
+
|
|
31
|
+
// Postal Addresses
|
|
32
|
+
private var postalAddresses: JSArray = JSArray()
|
|
33
|
+
|
|
34
|
+
// Image
|
|
35
|
+
private var image: JSObject = JSObject()
|
|
36
|
+
|
|
37
|
+
init(_ contactId: String) {
|
|
38
|
+
self.contactId = contactId
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
static func getMimetype(_ data: Data) -> String {
|
|
42
|
+
var b: UInt8 = 0
|
|
43
|
+
data.copyBytes(to: &b, count: 1)
|
|
44
|
+
switch b {
|
|
45
|
+
case 0xFF:
|
|
46
|
+
return "image/jpeg"
|
|
47
|
+
default:
|
|
48
|
+
return "image/png"
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
static func getLabel(_ type: String?, _ rawType: String?) -> String? {
|
|
53
|
+
// On Android, a custom label is saved with `type` set to "custom" and a separate `label` attribute.
|
|
54
|
+
// On iOS, on the contrary, the custom value is just saved into the `type` attribute.
|
|
55
|
+
|
|
56
|
+
if type == "custom" {
|
|
57
|
+
return rawType
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
return nil
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
public func fillData(_ contact: CNContact) {
|
|
64
|
+
// Name
|
|
65
|
+
if contact.isKeyAvailable(CNContactGivenNameKey) {
|
|
66
|
+
let displayName = CNContactFormatter.string(from: contact, style: .fullName)
|
|
67
|
+
self.name["display"] = displayName
|
|
68
|
+
self.name["given"] = contact.givenName
|
|
69
|
+
self.name["middle"] = contact.middleName
|
|
70
|
+
self.name["family"] = contact.familyName
|
|
71
|
+
self.name["prefix"] = contact.namePrefix
|
|
72
|
+
self.name["suffix"] = contact.nameSuffix
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
// Organization
|
|
76
|
+
if contact.isKeyAvailable(CNContactJobTitleKey) {
|
|
77
|
+
self.organization["company"] = contact.organizationName
|
|
78
|
+
self.organization["jobTitle"] = contact.jobTitle
|
|
79
|
+
self.organization["department"] = contact.departmentName
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Birthday
|
|
83
|
+
if contact.isKeyAvailable(CNContactBirthdayKey) {
|
|
84
|
+
if let dateComponents = contact.birthday {
|
|
85
|
+
self.birthday["year"] = dateComponents.year
|
|
86
|
+
self.birthday["month"] = dateComponents.month
|
|
87
|
+
self.birthday["day"] = dateComponents.day
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Note
|
|
92
|
+
if contact.isKeyAvailable(CNContactNoteKey) {
|
|
93
|
+
self.note = contact.note
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// Phones
|
|
97
|
+
if contact.isKeyAvailable(CNContactPhoneNumbersKey) {
|
|
98
|
+
self.phones = contact.phoneNumbers.map { phone in
|
|
99
|
+
let type = Contacts.phoneTypeMap.getKey(phone.label)
|
|
100
|
+
|
|
101
|
+
var phoneObject: JSObject = [
|
|
102
|
+
"type": type,
|
|
103
|
+
"number": phone.value.stringValue
|
|
104
|
+
]
|
|
105
|
+
|
|
106
|
+
if let label = ContactPayload.getLabel(type, phone.label) {
|
|
107
|
+
phoneObject["label"] = label
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
return phoneObject
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
// Emails
|
|
115
|
+
if contact.isKeyAvailable(CNContactEmailAddressesKey) {
|
|
116
|
+
self.emails = contact.emailAddresses.map { email in
|
|
117
|
+
let type = Contacts.emailTypeMap.getKey(email.label)
|
|
118
|
+
|
|
119
|
+
var emailObject: JSObject = [
|
|
120
|
+
"type": type,
|
|
121
|
+
"address": email.value as String
|
|
122
|
+
]
|
|
123
|
+
|
|
124
|
+
if let label = ContactPayload.getLabel(type, email.label) {
|
|
125
|
+
emailObject["label"] = label
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
return emailObject
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// URLs
|
|
133
|
+
if contact.isKeyAvailable(CNContactUrlAddressesKey) {
|
|
134
|
+
self.urls = contact.urlAddresses.map { url in
|
|
135
|
+
return url.value as String
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// Postal Addresses
|
|
140
|
+
if contact.isKeyAvailable(CNContactPostalAddressesKey) {
|
|
141
|
+
self.postalAddresses = contact.postalAddresses.map { postalAddress in
|
|
142
|
+
let type = Contacts.postalAddressTypeMap.getKey(postalAddress.label)
|
|
143
|
+
let formatted = CNPostalAddressFormatter.string(from: postalAddress.value, style: .mailingAddress)
|
|
144
|
+
|
|
145
|
+
var postalAddressObject: JSObject = [
|
|
146
|
+
"type": type,
|
|
147
|
+
"formatted": formatted,
|
|
148
|
+
"street": postalAddress.value.street,
|
|
149
|
+
"neighborhood": postalAddress.value.subAdministrativeArea,
|
|
150
|
+
"city": postalAddress.value.city,
|
|
151
|
+
"region": postalAddress.value.state,
|
|
152
|
+
"postcode": postalAddress.value.postalCode,
|
|
153
|
+
"country": postalAddress.value.country
|
|
154
|
+
]
|
|
155
|
+
|
|
156
|
+
if let label = ContactPayload.getLabel(type, postalAddress.label) {
|
|
157
|
+
postalAddressObject["label"] = label
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
return postalAddressObject
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
// Image
|
|
165
|
+
if contact.isKeyAvailable(CNContactImageDataKey) {
|
|
166
|
+
if let image = contact.imageData {
|
|
167
|
+
let mimeType = ContactPayload.getMimetype(image)
|
|
168
|
+
let encodedImage = image.base64EncodedString()
|
|
169
|
+
self.image["base64String"] = "data:\(mimeType);base64,\(encodedImage)"
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
public func getJSObject() -> JSObject {
|
|
175
|
+
var contact = JSObject()
|
|
176
|
+
|
|
177
|
+
// Id
|
|
178
|
+
contact["contactId"] = self.contactId
|
|
179
|
+
|
|
180
|
+
// Name
|
|
181
|
+
if self.name.count > 0 {
|
|
182
|
+
contact["name"] = self.name
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
// Organization
|
|
186
|
+
if self.organization.count > 0 {
|
|
187
|
+
contact["organization"] = self.organization
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// Birthday
|
|
191
|
+
if self.birthday.count > 0 {
|
|
192
|
+
contact["birthday"] = self.birthday
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Note
|
|
196
|
+
if self.note != nil {
|
|
197
|
+
contact["note"] = self.note
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
// Phones
|
|
201
|
+
if self.phones.count > 0 {
|
|
202
|
+
contact["phones"] = self.phones
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Emails
|
|
206
|
+
if self.emails.count > 0 {
|
|
207
|
+
contact["emails"] = self.emails
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// URLs
|
|
211
|
+
if self.urls.count > 0 {
|
|
212
|
+
contact["urls"] = self.urls
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Postal Addresses
|
|
216
|
+
if self.postalAddresses.count > 0 {
|
|
217
|
+
contact["postalAddresses"] = self.postalAddresses
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Image
|
|
221
|
+
if self.image.count > 0 {
|
|
222
|
+
contact["image"] = self.image
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
return contact
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
import Foundation
|
|
2
|
+
import Contacts
|
|
3
|
+
|
|
4
|
+
public class Contacts: NSObject {
|
|
5
|
+
public static let phoneTypeMap = BiMap<String, String>([
|
|
6
|
+
// Home / Work
|
|
7
|
+
"home": CNLabelHome,
|
|
8
|
+
"work": CNLabelWork,
|
|
9
|
+
// Other
|
|
10
|
+
"other": CNLabelOther,
|
|
11
|
+
// Custom
|
|
12
|
+
"custom": "custom",
|
|
13
|
+
// Phone specific
|
|
14
|
+
"main": CNLabelPhoneNumberMain,
|
|
15
|
+
"mobile": CNLabelPhoneNumberMobile,
|
|
16
|
+
"pager": CNLabelPhoneNumberPager,
|
|
17
|
+
"fax_home": CNLabelPhoneNumberHomeFax,
|
|
18
|
+
"fax_work": CNLabelPhoneNumberWorkFax,
|
|
19
|
+
"fax_other": CNLabelPhoneNumberOtherFax,
|
|
20
|
+
//
|
|
21
|
+
//
|
|
22
|
+
// iOS only:
|
|
23
|
+
// School
|
|
24
|
+
// "school": CNLabelSchool, // (iOS ^13.x.x only)
|
|
25
|
+
// Phone specific
|
|
26
|
+
// "apple_watch": CNLabelPhoneNumberAppleWatch, // (iOS ^14.3.x only)
|
|
27
|
+
"iphone": CNLabelPhoneNumberiPhone
|
|
28
|
+
], "custom", "custom")
|
|
29
|
+
|
|
30
|
+
public static let emailTypeMap = BiMap<String, String>([
|
|
31
|
+
// Home / Work
|
|
32
|
+
"home": CNLabelHome,
|
|
33
|
+
"work": CNLabelWork,
|
|
34
|
+
// Other
|
|
35
|
+
"other": CNLabelOther,
|
|
36
|
+
// Custom
|
|
37
|
+
"custom": "custom",
|
|
38
|
+
//
|
|
39
|
+
//
|
|
40
|
+
// iOS only:
|
|
41
|
+
// School
|
|
42
|
+
// "school": CNLabelSchool, // (iOS ^13.x.x only)
|
|
43
|
+
// Email specific
|
|
44
|
+
"icloud": CNLabelEmailiCloud
|
|
45
|
+
], "custom", "custom")
|
|
46
|
+
|
|
47
|
+
public static let postalAddressTypeMap = BiMap<String, String>([
|
|
48
|
+
// Home / Work
|
|
49
|
+
"home": CNLabelHome,
|
|
50
|
+
"work": CNLabelWork,
|
|
51
|
+
// Other
|
|
52
|
+
"other": CNLabelOther,
|
|
53
|
+
// Custom
|
|
54
|
+
"custom": "custom"
|
|
55
|
+
//
|
|
56
|
+
//
|
|
57
|
+
// iOS only:
|
|
58
|
+
// School
|
|
59
|
+
// "school": CNLabelSchool, // (iOS ^13.x.x only)
|
|
60
|
+
], "custom", "custom")
|
|
61
|
+
|
|
62
|
+
public func getContact(_ contactId: String, _ projection: GetContactsProjectionInput) -> ContactPayload? {
|
|
63
|
+
let projection = projection.getProjection()
|
|
64
|
+
|
|
65
|
+
let cs = CNContactStore()
|
|
66
|
+
|
|
67
|
+
do {
|
|
68
|
+
let contactResult = try cs.unifiedContact(withIdentifier: contactId, keysToFetch: projection)
|
|
69
|
+
|
|
70
|
+
let contact = ContactPayload(contactId)
|
|
71
|
+
|
|
72
|
+
contact.fillData(contactResult)
|
|
73
|
+
|
|
74
|
+
return contact
|
|
75
|
+
} catch {
|
|
76
|
+
return nil
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
public func getContacts(_ projection: GetContactsProjectionInput) -> [ContactPayload] {
|
|
81
|
+
let projection = projection.getProjection()
|
|
82
|
+
|
|
83
|
+
var contacts = [ContactPayload]()
|
|
84
|
+
|
|
85
|
+
let cs = CNContactStore()
|
|
86
|
+
|
|
87
|
+
do {
|
|
88
|
+
let request = CNContactFetchRequest(keysToFetch: projection)
|
|
89
|
+
|
|
90
|
+
try cs.enumerateContacts(with: request) { (contactData, _) in
|
|
91
|
+
let contact = ContactPayload(contactData.identifier)
|
|
92
|
+
|
|
93
|
+
contact.fillData(contactData)
|
|
94
|
+
|
|
95
|
+
contacts.append(contact)
|
|
96
|
+
}
|
|
97
|
+
} catch {
|
|
98
|
+
// oops
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
return contacts
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
public func createContact(_ contactInput: CreateContactInput) -> String? {
|
|
105
|
+
let newContact = CNMutableContact()
|
|
106
|
+
|
|
107
|
+
// Name
|
|
108
|
+
if let nameGiven = contactInput.nameGiven {
|
|
109
|
+
newContact.givenName = nameGiven
|
|
110
|
+
}
|
|
111
|
+
if let nameMiddle = contactInput.nameMiddle {
|
|
112
|
+
newContact.middleName = nameMiddle
|
|
113
|
+
}
|
|
114
|
+
if let nameFamily = contactInput.nameFamily {
|
|
115
|
+
newContact.familyName = nameFamily
|
|
116
|
+
}
|
|
117
|
+
if let namePrefix = contactInput.namePrefix {
|
|
118
|
+
newContact.namePrefix = namePrefix
|
|
119
|
+
}
|
|
120
|
+
if let nameSuffix = contactInput.nameSuffix {
|
|
121
|
+
newContact.nameSuffix = nameSuffix
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
// Organization
|
|
125
|
+
if let organizationName = contactInput.organizationName {
|
|
126
|
+
newContact.organizationName = organizationName
|
|
127
|
+
}
|
|
128
|
+
if let organizationJobTitle = contactInput.organizationJobTitle {
|
|
129
|
+
newContact.jobTitle = organizationJobTitle
|
|
130
|
+
}
|
|
131
|
+
if let organizationDepartment = contactInput.organizationDepartment {
|
|
132
|
+
newContact.departmentName = organizationDepartment
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Birthday
|
|
136
|
+
if let birthday = contactInput.birthday {
|
|
137
|
+
newContact.birthday = birthday
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
// Note
|
|
141
|
+
if let note = contactInput.note {
|
|
142
|
+
newContact.note = note
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
// Phones
|
|
146
|
+
newContact.phoneNumbers = contactInput.phones.map { phone in
|
|
147
|
+
return CNLabeledValue(
|
|
148
|
+
label: phone.type,
|
|
149
|
+
value: CNPhoneNumber(stringValue: phone.number ?? "")
|
|
150
|
+
)
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// Email
|
|
154
|
+
newContact.emailAddresses = contactInput.emails.map { email in
|
|
155
|
+
return CNLabeledValue(
|
|
156
|
+
label: email.type,
|
|
157
|
+
value: email.address as? NSString ?? ""
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
// URLs
|
|
162
|
+
newContact.urlAddresses = contactInput.urls.map { url in
|
|
163
|
+
return CNLabeledValue(
|
|
164
|
+
label: nil,
|
|
165
|
+
value: url as NSString
|
|
166
|
+
)
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
// Postal Addresses
|
|
170
|
+
newContact.postalAddresses = contactInput.postalAddresses.map({ postalAddress in
|
|
171
|
+
let address = CNMutablePostalAddress()
|
|
172
|
+
address.street = postalAddress.street ?? ""
|
|
173
|
+
address.subAdministrativeArea = postalAddress.neighborhood ?? ""
|
|
174
|
+
address.city = postalAddress.city ?? ""
|
|
175
|
+
address.state = postalAddress.region ?? ""
|
|
176
|
+
address.postalCode = postalAddress.postcode ?? ""
|
|
177
|
+
address.country = postalAddress.country ?? ""
|
|
178
|
+
|
|
179
|
+
return CNLabeledValue(
|
|
180
|
+
label: postalAddress.type,
|
|
181
|
+
value: address
|
|
182
|
+
)
|
|
183
|
+
})
|
|
184
|
+
|
|
185
|
+
// Image
|
|
186
|
+
if let image = contactInput.image {
|
|
187
|
+
if let base64String = image.base64String {
|
|
188
|
+
if let data = Data(base64Encoded: base64String, options: .ignoreUnknownCharacters) {
|
|
189
|
+
newContact.imageData = data
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
do {
|
|
195
|
+
let cs = CNContactStore()
|
|
196
|
+
let saveRequest = CNSaveRequest()
|
|
197
|
+
saveRequest.add(newContact, toContainerWithIdentifier: nil)
|
|
198
|
+
|
|
199
|
+
try cs.execute(saveRequest)
|
|
200
|
+
|
|
201
|
+
if newContact.isKeyAvailable(CNContactIdentifierKey) {
|
|
202
|
+
return newContact.identifier
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
return nil
|
|
206
|
+
} catch {
|
|
207
|
+
return nil
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
public func deleteContact(_ contactId: String) -> Bool {
|
|
212
|
+
let cs = CNContactStore()
|
|
213
|
+
|
|
214
|
+
do {
|
|
215
|
+
let contactResult = try cs.unifiedContact(withIdentifier: contactId, keysToFetch: [CNContactIdentifierKey] as [CNKeyDescriptor])
|
|
216
|
+
|
|
217
|
+
let saveRequest = CNSaveRequest()
|
|
218
|
+
saveRequest.delete(contactResult.mutableCopy() as! CNMutableContact)
|
|
219
|
+
|
|
220
|
+
try cs.execute(saveRequest)
|
|
221
|
+
|
|
222
|
+
return true
|
|
223
|
+
} catch {
|
|
224
|
+
return false
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
#import <UIKit/UIKit.h>
|
|
2
|
+
|
|
3
|
+
//! Project version number for Plugin.
|
|
4
|
+
FOUNDATION_EXPORT double PluginVersionNumber;
|
|
5
|
+
|
|
6
|
+
//! Project version string for Plugin.
|
|
7
|
+
FOUNDATION_EXPORT const unsigned char PluginVersionString[];
|
|
8
|
+
|
|
9
|
+
// In this header, you should import all the public headers of your framework using statements like #import <Plugin/PublicHeader.h>
|
|
10
|
+
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <Capacitor/Capacitor.h>
|
|
3
|
+
|
|
4
|
+
// Define the plugin using the CAP_PLUGIN Macro, and
|
|
5
|
+
// each method the plugin supports using the CAP_PLUGIN_METHOD macro.
|
|
6
|
+
CAP_PLUGIN(ContactsPlugin, "Contacts",
|
|
7
|
+
CAP_PLUGIN_METHOD(checkPermissions, CAPPluginReturnPromise);
|
|
8
|
+
CAP_PLUGIN_METHOD(requestPermissions, CAPPluginReturnPromise);
|
|
9
|
+
CAP_PLUGIN_METHOD(getContact, CAPPluginReturnPromise);
|
|
10
|
+
CAP_PLUGIN_METHOD(getContacts, CAPPluginReturnPromise);
|
|
11
|
+
CAP_PLUGIN_METHOD(createContact, CAPPluginReturnPromise);
|
|
12
|
+
CAP_PLUGIN_METHOD(deleteContact, CAPPluginReturnPromise);
|
|
13
|
+
CAP_PLUGIN_METHOD(pickContact, CAPPluginReturnPromise);
|
|
14
|
+
)
|