Skip to content

Commit

Permalink
feat: add ability to save image on createContact (#126)
Browse files Browse the repository at this point in the history
This PR adds the ability to save an image using the `createContact`
method with base64.

Close #59

---------

Co-authored-by: tafelnl <35837839+tafelnl@users.noreply.github.com>
  • Loading branch information
robingenz and tafelnl authored Sep 18, 2024
1 parent e1baf75 commit ea771d9
Show file tree
Hide file tree
Showing 6 changed files with 74 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
import android.provider.ContactsContract.CommonDataKinds.StructuredPostal;
import android.provider.ContactsContract.CommonDataKinds.Website;
import android.provider.ContactsContract.RawContacts;
import android.util.Base64;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import java.util.ArrayList;
Expand Down Expand Up @@ -313,6 +314,21 @@ public String createContact(CreateContactInput contactInput) {
ops.add(op.build());
}

// Image
if (contactInput.image != null && contactInput.image.base64String != null) {
byte[] photoData = Base64.decode(contactInput.image.base64String, Base64.DEFAULT);

op =
ContentProviderOperation
.newInsert(ContactsContract.Data.CONTENT_URI)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
// Add to this key
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Photo.CONTENT_ITEM_TYPE)
// Data
.withValue(ContactsContract.CommonDataKinds.Photo.PHOTO, photoData);
ops.add(op.build());
}

try {
ContentResolver cr = this.mActivity.getContentResolver();
ContentProviderResult[] result = cr.applyBatch(ContactsContract.AUTHORITY, ops);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,8 @@ public class CreateContactInput {
// Postal Addresses
public ArrayList<PostalAddressInput> postalAddresses = new ArrayList<>();

// @TODO:
// Image
public ImageInput image;

CreateContactInput(JSONObject fromJSONObject) {
// Name
Expand Down Expand Up @@ -153,6 +153,12 @@ public class CreateContactInput {
}
}
}

// Image
JSONObject imageObject = fromJSONObject.optJSONObject("image");
if (imageObject != null) {
this.image = new ImageInput(imageObject);
}
}

public static class PhoneInput {
Expand Down Expand Up @@ -215,4 +221,13 @@ public static class PostalAddressInput {
this.country = fromJSONObject.has("country") ? fromJSONObject.optString("country") : null;
}
}

public static class ImageInput {

public final String base64String;

ImageInput(JSONObject fromJSONObject) {
this.base64String = fromJSONObject.has("base64String") ? fromJSONObject.optString("base64String") : null;
}
}
}
8 changes: 8 additions & 0 deletions docs/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -266,6 +266,7 @@ pickContact(options: PickContactOptions) => Promise<PickContactResult>
| **`emails`** | <code>EmailInput[]</code> | Emails |
| **`urls`** | <code>string[]</code> | URLs |
| **`postalAddresses`** | <code>PostalAddressInput[]</code> | Postal Addresses |
| **`image`** | <code>[ImageInput](#imageinput) \| null</code> | Image |


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


#### ImageInput

| Prop | Type | Description |
| ------------------ | --------------------------- | --------------------- |
| **`base64String`** | <code>string \| null</code> | Base64 encoded image. |


#### DeleteContactOptions

| Prop | Type |
Expand Down
9 changes: 9 additions & 0 deletions ios/Plugin/Contacts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,15 @@ public class Contacts: NSObject {
)
})

// Image
if let image = contactInput.image {
if let base64String = image.base64String {
if let data = Data(base64Encoded: base64String, options: .ignoreUnknownCharacters) {
newContact.imageData = data
}
}
}

do {
let cs = CNContactStore()
let saveRequest = CNSaveRequest()
Expand Down
16 changes: 15 additions & 1 deletion ios/Plugin/CreateContactInput.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ public class CreateContactInput {
// Postal Addresses
public var postalAddresses: [PostalAddressInput] = []

// @TODO:
// Image
public var image: ImageInput?

init(_ fromJSONObject: JSObject) {
// Name
Expand Down Expand Up @@ -103,6 +103,11 @@ public class CreateContactInput {
}
}
}

// Image
if let imageObject = fromJSONObject["image"] as? JSObject {
self.image = ImageInput.init(imageObject)
}
}

static func getType(_ type: String?, _ fromJSONObject: JSObject) -> String? {
Expand Down Expand Up @@ -170,4 +175,13 @@ public class CreateContactInput {
self.country = fromJSONObject["country"] as? String
}
}

public class ImageInput {

public var base64String: String?

init(_ fromJSONObject: JSObject) {
self.base64String = fromJSONObject["base64String"] as? String
}
}
}
12 changes: 10 additions & 2 deletions src/definitions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,15 @@ export interface EmailInput {
address: string | null;
}

export interface ImageInput {
/**
* Base64 encoded image.
*
* @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="
*/
base64String?: string | null;
}

export interface PostalAddressInput {
type: PostalAddressType;
label?: string | null;
Expand Down Expand Up @@ -327,8 +336,7 @@ export interface ContactInput {
/**
* Image
*/
// @TODO:
// image?: ImageInput | null;
image?: ImageInput | null;
}

export interface CreateContactResult {
Expand Down

0 comments on commit ea771d9

Please sign in to comment.