diff --git a/README.md b/README.md index c6d7231..ee51410 100644 --- a/README.md +++ b/README.md @@ -19,6 +19,24 @@ For React Native => 0.59 only: react-native link react-native-select-contact ``` +### Expo Usage +since this package use NativeModules you need to +migrate to development build. more info [here](https://docs.expo.dev/develop/development-builds/create-a-build/) + +add `react-native-select-contact` to the plugin array in your `app.json` + +```json +{ + "expo": { + ... + "plugins": [ + ... + "react-native-select-contact" + ] + } +} +``` + #### Android For Android support, make sure your manifest file includes permission to read contacts along with a query intent for Android 11+: ```xml diff --git a/android/build.gradle b/android/build.gradle index 1a1583f..b2eabaf 100644 --- a/android/build.gradle +++ b/android/build.gradle @@ -9,7 +9,7 @@ buildscript { if (project == rootProject) { repositories { google() - mavencentral() + mavenCentral() } dependencies { classpath 'com.android.tools.build:gradle:3.5.2' @@ -43,7 +43,6 @@ repositories { url "$rootDir/../node_modules/jsc-android/dist" } google() - mavencentral() } dependencies { diff --git a/app.plugin.js b/app.plugin.js new file mode 100644 index 0000000..c59f388 --- /dev/null +++ b/app.plugin.js @@ -0,0 +1,63 @@ +const { + withAndroidManifest, + withInfoPlist, + withPlugins, +} = require("@expo/config-plugins"); + +const CONTACT_USAGE = "Allow $(PRODUCT_NAME) to access your contacts"; + +const withIosConfig = (config, props) => { + let permissionString = undefined; + if (props) { + const { contactPermission } = props; + permissionString = contactPermission; + } + + return withInfoPlist(config, (config) => { + config.modResults.NSContactsUsageDescription = + permissionString ?? CONTACT_USAGE; + + return config; + }); +}; + +const withAndroidConfig = (config) => { + return withAndroidManifest(config, async (config) => { + const androidManifest = config.modResults.manifest; + + if ( + !config.android.permissions.find( + (permission) => + permission === "android.permission.READ_CONTACTS" + ) + ) { + config.android.permissions.push("android.permission.READ_CONTACTS"); + } + + androidManifest.application[0]?.activity?.[0]?.["intent-filter"].push({ + action: { + $: { + "android:name": "android.intent.action.PICK", + }, + }, + data: { + $: { + "android:mimeType": "vnd.android.cursor.dir/contact", + }, + }, + category: { + $: { + "android:name": "android.intent.category.DEFAULT", + }, + }, + }); + + return config; + }); +}; + +const withSelectContact = (config) => { + return withPlugins(config, [withAndroidConfig, withIosConfig]); +}; + +module.exports = withSelectContact; diff --git a/index.js b/index.js index b740605..0a1ce03 100644 --- a/index.js +++ b/index.js @@ -88,7 +88,9 @@ const SelectContactApi = { return null; } - return selectPhone(phones, textOptions) + const uniquePhones = [...new Map(phones.map(phone => [phone.number.replace(/ /g,''), phone])).values()] + + return selectPhone(uniquePhones, textOptions) .then(selectedPhone => { return selectedPhone ? { contact, selectedPhone } : null; });