Skip to content

Commit ea771d9

Browse files
robingenztafelnl
andauthored
feat: add ability to save image on createContact (#126)
This PR adds the ability to save an image using the `createContact` method with base64. Close #59 --------- Co-authored-by: tafelnl <[email protected]>
1 parent e1baf75 commit ea771d9

File tree

6 files changed

+74
-4
lines changed

6 files changed

+74
-4
lines changed

android/src/main/java/getcapacitor/community/contacts/Contacts.java

+16
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
1717
import android.provider.ContactsContract.CommonDataKinds.Website;
1818
import android.provider.ContactsContract.RawContacts;
19+
import android.util.Base64;
1920
import androidx.annotation.NonNull;
2021
import androidx.annotation.Nullable;
2122
import java.util.ArrayList;
@@ -313,6 +314,21 @@ public String createContact(CreateContactInput contactInput) {
313314
ops.add(op.build());
314315
}
315316

317+
// Image
318+
if (contactInput.image != null && contactInput.image.base64String != null) {
319+
byte[] photoData = Base64.decode(contactInput.image.base64String, Base64.DEFAULT);
320+
321+
op =
322+
ContentProviderOperation
323+
.newInsert(ContactsContract.Data.CONTENT_URI)
324+
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
325+
// Add to this key
326+
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
327+
// Data
328+
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photoData);
329+
ops.add(op.build());
330+
}
331+
316332
try {
317333
ContentResolver cr = this.mActivity.getContentResolver();
318334
ContentProviderResult[] result = cr.applyBatch(ContactsContract.AUTHORITY, ops);

android/src/main/java/getcapacitor/community/contacts/CreateContactInput.java

+16-1
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ public class CreateContactInput {
4545
// Postal Addresses
4646
public ArrayList<PostalAddressInput> postalAddresses = new ArrayList<>();
4747

48-
// @TODO:
4948
// Image
49+
public ImageInput image;
5050

5151
CreateContactInput(JSONObject fromJSONObject) {
5252
// Name
@@ -153,6 +153,12 @@ public class CreateContactInput {
153153
}
154154
}
155155
}
156+
157+
// Image
158+
JSONObject imageObject = fromJSONObject.optJSONObject("image");
159+
if (imageObject != null) {
160+
this.image = new ImageInput(imageObject);
161+
}
156162
}
157163

158164
public static class PhoneInput {
@@ -215,4 +221,13 @@ public static class PostalAddressInput {
215221
this.country = fromJSONObject.has("country") ? fromJSONObject.optString("country") : null;
216222
}
217223
}
224+
225+
public static class ImageInput {
226+
227+
public final String base64String;
228+
229+
ImageInput(JSONObject fromJSONObject) {
230+
this.base64String = fromJSONObject.has("base64String") ? fromJSONObject.optString("base64String") : null;
231+
}
232+
}
218233
}

docs/api.md

+8
Original file line numberDiff line numberDiff line change
@@ -266,6 +266,7 @@ pickContact(options: PickContactOptions) => Promise<PickContactResult>
266266
| **`emails`** | <code>EmailInput[]</code> | Emails |
267267
| **`urls`** | <code>string[]</code> | URLs |
268268
| **`postalAddresses`** | <code>PostalAddressInput[]</code> | Postal Addresses |
269+
| **`image`** | <code>[ImageInput](#imageinput) \| null</code> | Image |
269270

270271

271272
#### NameInput
@@ -332,6 +333,13 @@ pickContact(options: PickContactOptions) => Promise<PickContactResult>
332333
| **`country`** | <code>string \| null</code> |
333334

334335

336+
#### ImageInput
337+
338+
| Prop | Type | Description |
339+
| ------------------ | --------------------------- | --------------------- |
340+
| **`base64String`** | <code>string \| null</code> | Base64 encoded image. |
341+
342+
335343
#### DeleteContactOptions
336344

337345
| Prop | Type |

ios/Plugin/Contacts.swift

+9
Original file line numberDiff line numberDiff line change
@@ -182,6 +182,15 @@ public class Contacts: NSObject {
182182
)
183183
})
184184

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+
185194
do {
186195
let cs = CNContactStore()
187196
let saveRequest = CNSaveRequest()

ios/Plugin/CreateContactInput.swift

+15-1
Original file line numberDiff line numberDiff line change
@@ -33,8 +33,8 @@ public class CreateContactInput {
3333
// Postal Addresses
3434
public var postalAddresses: [PostalAddressInput] = []
3535

36-
// @TODO:
3736
// Image
37+
public var image: ImageInput?
3838

3939
init(_ fromJSONObject: JSObject) {
4040
// Name
@@ -103,6 +103,11 @@ public class CreateContactInput {
103103
}
104104
}
105105
}
106+
107+
// Image
108+
if let imageObject = fromJSONObject["image"] as? JSObject {
109+
self.image = ImageInput.init(imageObject)
110+
}
106111
}
107112

108113
static func getType(_ type: String?, _ fromJSONObject: JSObject) -> String? {
@@ -170,4 +175,13 @@ public class CreateContactInput {
170175
self.country = fromJSONObject["country"] as? String
171176
}
172177
}
178+
179+
public class ImageInput {
180+
181+
public var base64String: String?
182+
183+
init(_ fromJSONObject: JSObject) {
184+
self.base64String = fromJSONObject["base64String"] as? String
185+
}
186+
}
173187
}

src/definitions.ts

+10-2
Original file line numberDiff line numberDiff line change
@@ -270,6 +270,15 @@ export interface EmailInput {
270270
address: string | null;
271271
}
272272

273+
export interface ImageInput {
274+
/**
275+
* Base64 encoded image.
276+
*
277+
* @example "iVBORw0KGgoAAAANSUhEUgAAABgAAAAYCAYAAADgdz34AAAABHNCSVQICAgIfAhkiAAAAAlwSFlzAAAApgAAAKYB3X3/OAAAABl0RVh0U29mdHdhcmUAd3d3Lmlua3NjYXBlLm9yZ5vuPBoAAANCSURBVEiJtZZPbBtFFMZ/M7ubXdtdb1xSFyeilBapySVU8h8OoFaooFSqiihIVIpQBKci6KEg9Q6H9kovIHoCIVQJJCKE1ENFjnAgcaSGC6rEnxBwA04Tx43t2FnvDAfjkNibxgHxnWb2e/u992bee7tCa00YFsffekFY+nUzFtjW0LrvjRXrCDIAaPLlW0nHL0SsZtVoaF98mLrx3pdhOqLtYPHChahZcYYO7KvPFxvRl5XPp1sN3adWiD1ZAqD6XYK1b/dvE5IWryTt2udLFedwc1+9kLp+vbbpoDh+6TklxBeAi9TL0taeWpdmZzQDry0AcO+jQ12RyohqqoYoo8RDwJrU+qXkjWtfi8Xxt58BdQuwQs9qC/afLwCw8tnQbqYAPsgxE1S6F3EAIXux2oQFKm0ihMsOF71dHYx+f3NND68ghCu1YIoePPQN1pGRABkJ6Bus96CutRZMydTl+TvuiRW1m3n0eDl0vRPcEysqdXn+jsQPsrHMquGeXEaY4Yk4wxWcY5V/9scqOMOVUFthatyTy8QyqwZ+kDURKoMWxNKr2EeqVKcTNOajqKoBgOE28U4tdQl5p5bwCw7BWquaZSzAPlwjlithJtp3pTImSqQRrb2Z8PHGigD4RZuNX6JYj6wj7O4TFLbCO/Mn/m8R+h6rYSUb3ekokRY6f/YukArN979jcW+V/S8g0eT/N3VN3kTqWbQ428m9/8k0P/1aIhF36PccEl6EhOcAUCrXKZXXWS3XKd2vc/TRBG9O5ELC17MmWubD2nKhUKZa26Ba2+D3P+4/MNCFwg59oWVeYhkzgN/JDR8deKBoD7Y+ljEjGZ0sosXVTvbc6RHirr2reNy1OXd6pJsQ+gqjk8VWFYmHrwBzW/n+uMPFiRwHB2I7ih8ciHFxIkd/3Omk5tCDV1t+2nNu5sxxpDFNx+huNhVT3/zMDz8usXC3ddaHBj1GHj/As08fwTS7Kt1HBTmyN29vdwAw+/wbwLVOJ3uAD1wi/dUH7Qei66PfyuRj4Ik9is+hglfbkbfR3cnZm7chlUWLdwmprtCohX4HUtlOcQjLYCu+fzGJH2QRKvP3UNz8bWk1qMxjGTOMThZ3kvgLI5AzFfo379UAAAAASUVORK5CYII="
278+
*/
279+
base64String?: string | null;
280+
}
281+
273282
export interface PostalAddressInput {
274283
type: PostalAddressType;
275284
label?: string | null;
@@ -327,8 +336,7 @@ export interface ContactInput {
327336
/**
328337
* Image
329338
*/
330-
// @TODO:
331-
// image?: ImageInput | null;
339+
image?: ImageInput | null;
332340
}
333341

334342
export interface CreateContactResult {

0 commit comments

Comments
 (0)