diff --git a/android/app/build.gradle b/android/app/build.gradle index e112598..d258bfd 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -137,6 +137,7 @@ android { } dependencies { + compile project(':react-native-app-settings') compile project(':react-native-contacts') compile project(':react-native-webview') compile project(':react-native-vector-icons') diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 9fb7a3f..33833ec 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -3,6 +3,7 @@ + getPackages() { return Arrays.asList( new MainReactPackage(), + new OpenAppSettingsPackage(), new ReactNativeContacts(), new RNCWebViewPackage(), new VectorIconsPackage(), diff --git a/android/settings.gradle b/android/settings.gradle index 9e1189e..be5e104 100644 --- a/android/settings.gradle +++ b/android/settings.gradle @@ -1,4 +1,6 @@ rootProject.name = 'Tagfer' +include ':react-native-app-settings' +project(':react-native-app-settings').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-app-settings/android') include ':react-native-contacts' project(':react-native-contacts').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-contacts/android') include ':react-native-webview' diff --git a/ios/Tagfer.xcodeproj/project.pbxproj b/ios/Tagfer.xcodeproj/project.pbxproj index 85010ea..55f1323 100644 --- a/ios/Tagfer.xcodeproj/project.pbxproj +++ b/ios/Tagfer.xcodeproj/project.pbxproj @@ -5,7 +5,6 @@ }; objectVersion = 46; objects = { - /* Begin PBXBuildFile section */ 00703E436FE7412D82B8B2ED /* libRealmReact.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 35A364E2A9804D0FA6E9C2BD /* libRealmReact.a */; }; 00C302E51ABCBA2D00DB3ED1 /* libRCTActionSheet.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 00C302AC1ABCB8CE00DB3ED1 /* libRCTActionSheet.a */; }; @@ -56,6 +55,8 @@ CCFF320D8D3B429E98A05055 /* MaterialCommunityIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = AC4E3A77FB9C4C96AC304034 /* MaterialCommunityIcons.ttf */; }; D9DE5DDB1B7D4D3A97259D9B /* Octicons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = F025858B6C364BB985AFD241 /* Octicons.ttf */; }; E42DCC4F98F24BC99A74B29B /* SimpleLineIcons.ttf in Resources */ = {isa = PBXBuildFile; fileRef = 05246261280A4D30B02BFE85 /* SimpleLineIcons.ttf */; }; + 5732A1A6497B4CAD966524D3 /* libReactNativePermissions.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 75B79A57F6EF4FE2A21CEE97 /* libReactNativePermissions.a */; }; + 864F29A547984CC590F11FA6 /* libRNOpenAppSettings.a in Frameworks */ = {isa = PBXBuildFile; fileRef = E5E2957596074A7C85333B68 /* libRNOpenAppSettings.a */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -419,6 +420,10 @@ DB6CE8411CF34300A2ED791F /* Foundation.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Foundation.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Foundation.ttf"; sourceTree = ""; }; E76DD57CF0E846F0B388335E /* libz.tbd */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = "sourcecode.text-based-dylib-definition"; name = libz.tbd; path = usr/lib/libz.tbd; sourceTree = SDKROOT; }; F025858B6C364BB985AFD241 /* Octicons.ttf */ = {isa = PBXFileReference; explicitFileType = undefined; fileEncoding = 9; includeInIndex = 0; lastKnownFileType = unknown; name = Octicons.ttf; path = "../node_modules/react-native-vector-icons/Fonts/Octicons.ttf"; sourceTree = ""; }; + E335F09B945C4E2391D1FCD3 /* ReactNativePermissions.xcodeproj */ = {isa = PBXFileReference; name = "ReactNativePermissions.xcodeproj"; path = "../node_modules/react-native-permissions/ios/ReactNativePermissions.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; + 75B79A57F6EF4FE2A21CEE97 /* libReactNativePermissions.a */ = {isa = PBXFileReference; name = "libReactNativePermissions.a"; path = "libReactNativePermissions.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; + 92557FC291AB42ADB5028635 /* RNOpenAppSettings.xcodeproj */ = {isa = PBXFileReference; name = "RNOpenAppSettings.xcodeproj"; path = "../node_modules/react-native-app-settings/ios/RNOpenAppSettings.xcodeproj"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = wrapper.pb-project; explicitFileType = undefined; includeInIndex = 0; }; + E5E2957596074A7C85333B68 /* libRNOpenAppSettings.a */ = {isa = PBXFileReference; name = "libRNOpenAppSettings.a"; path = "libRNOpenAppSettings.a"; sourceTree = ""; fileEncoding = undefined; lastKnownFileType = archive.ar; explicitFileType = undefined; includeInIndex = 0; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -453,6 +458,8 @@ 054B5176D9D541119DF55198 /* libRNVectorIcons.a in Frameworks */, AD3198E72354473C9CFBB5F9 /* libRNCWebView.a in Frameworks */, 1BF10613A6304DD5B4189358 /* libRCTContacts.a in Frameworks */, + 5732A1A6497B4CAD966524D3 /* libReactNativePermissions.a in Frameworks */, + 864F29A547984CC590F11FA6 /* libRNOpenAppSettings.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -698,6 +705,8 @@ 2DACAA5CB9F345B5888D681E /* RNVectorIcons.xcodeproj */, A6904FF8C83444048D6F2AF5 /* RNCWebView.xcodeproj */, 90515674F3834203B1DE6531 /* RCTContacts.xcodeproj */, + E335F09B945C4E2391D1FCD3 /* ReactNativePermissions.xcodeproj */, + 92557FC291AB42ADB5028635 /* RNOpenAppSettings.xcodeproj */, ); name = Libraries; sourceTree = ""; @@ -1406,6 +1415,8 @@ "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-webview/ios", "$(SRCROOT)/../node_modules/react-native-contacts/ios/RCTContacts", + "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", + "$(SRCROOT)/../node_modules/react-native-app-settings/ios", ); INFOPLIST_FILE = TagferTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1417,6 +1428,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1440,6 +1453,8 @@ "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-webview/ios", "$(SRCROOT)/../node_modules/react-native-contacts/ios/RCTContacts", + "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", + "$(SRCROOT)/../node_modules/react-native-app-settings/ios", ); INFOPLIST_FILE = TagferTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 9.0; @@ -1451,6 +1466,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1475,6 +1492,8 @@ "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-webview/ios", "$(SRCROOT)/../node_modules/react-native-contacts/ios/RCTContacts", + "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", + "$(SRCROOT)/../node_modules/react-native-app-settings/ios", ); INFOPLIST_FILE = Tagfer/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1501,6 +1520,8 @@ "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-webview/ios", "$(SRCROOT)/../node_modules/react-native-contacts/ios/RCTContacts", + "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", + "$(SRCROOT)/../node_modules/react-native-app-settings/ios", ); INFOPLIST_FILE = Tagfer/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1534,6 +1555,8 @@ "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-webview/ios", "$(SRCROOT)/../node_modules/react-native-contacts/ios/RCTContacts", + "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", + "$(SRCROOT)/../node_modules/react-native-app-settings/ios", ); INFOPLIST_FILE = "Tagfer-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1544,6 +1567,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1576,6 +1601,8 @@ "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-webview/ios", "$(SRCROOT)/../node_modules/react-native-contacts/ios/RCTContacts", + "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", + "$(SRCROOT)/../node_modules/react-native-app-settings/ios", ); INFOPLIST_FILE = "Tagfer-tvOS/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; @@ -1586,6 +1613,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1617,6 +1646,8 @@ "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-webview/ios", "$(SRCROOT)/../node_modules/react-native-contacts/ios/RCTContacts", + "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", + "$(SRCROOT)/../node_modules/react-native-app-settings/ios", ); INFOPLIST_FILE = "Tagfer-tvOSTests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -1627,6 +1658,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", @@ -1658,6 +1691,8 @@ "$(SRCROOT)/../node_modules/react-native-vector-icons/RNVectorIconsManager", "$(SRCROOT)/../node_modules/react-native-webview/ios", "$(SRCROOT)/../node_modules/react-native-contacts/ios/RCTContacts", + "$(SRCROOT)/../node_modules/react-native-permissions/ios/**", + "$(SRCROOT)/../node_modules/react-native-app-settings/ios", ); INFOPLIST_FILE = "Tagfer-tvOSTests/Info.plist"; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -1668,6 +1703,8 @@ "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", + "\"$(SRCROOT)/$(TARGET_NAME)\"", ); OTHER_LDFLAGS = ( "-ObjC", diff --git a/ios/Tagfer/Info.plist b/ios/Tagfer/Info.plist index ff58dca..dc3e423 100644 --- a/ios/Tagfer/Info.plist +++ b/ios/Tagfer/Info.plist @@ -27,7 +27,7 @@ LSRequiresIPhoneOS NSLocationWhenInUseUsageDescription - + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities diff --git a/package-lock.json b/package-lock.json index 967f41e..df29d40 100644 --- a/package-lock.json +++ b/package-lock.json @@ -8523,6 +8523,11 @@ "yargs": "^9.0.0" } }, + "react-native-app-settings": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/react-native-app-settings/-/react-native-app-settings-2.0.1.tgz", + "integrity": "sha512-MmYtXQbPBJ0tlAmn4MeeOOjrSR9Cup4PI4HFSsETDGUMrOGmb7WETrQ/9bZ06BeisNnqf8/Qj+efgH+OmFYDjQ==" + }, "react-native-contacts": { "version": "2.2.5", "resolved": "https://registry.npmjs.org/react-native-contacts/-/react-native-contacts-2.2.5.tgz", @@ -8630,6 +8635,11 @@ "tinymask": "^1.0.2" } }, + "react-native-permissions": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/react-native-permissions/-/react-native-permissions-1.1.1.tgz", + "integrity": "sha512-t0Ujm177bagjUOSzhpmkSz+LqFW04HnY9TeZFavDCmV521fQvFz82aD+POXqWsAdsJVOK3umJYBNNqCjC3g0hQ==" + }, "react-native-safe-area-view": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-native-safe-area-view/-/react-native-safe-area-view-0.11.0.tgz", diff --git a/package.json b/package.json index 463dd18..57b3cc9 100644 --- a/package.json +++ b/package.json @@ -11,12 +11,14 @@ "i18n-js": "^3.1.0", "react": "16.6.3", "react-native": "0.57.8", + "react-native-app-settings": "^2.0.1", "react-native-contacts": "^2.2.5", "react-native-country-picker-modal": "^0.6.2", "react-native-elements": "^0.19.1", "react-native-flash-message": "^0.1.10", "react-native-gesture-handler": "^1.0.12", "react-native-masked-text": "^1.9.2", + "react-native-permissions": "^1.1.1", "react-native-vector-icons": "^4.6.0", "react-native-webview": "^2.14.3", "react-navigation": "^3.0.9", diff --git a/src/components/lists/ContactListItem.js b/src/components/lists/ContactListItem.js index 63681b2..f266bdf 100644 --- a/src/components/lists/ContactListItem.js +++ b/src/components/lists/ContactListItem.js @@ -6,7 +6,10 @@ import { isEmpty } from '../../utils/aux'; const ContactListItem = ({ contact, selected, onPress }) => { const { givenName, familyName, phoneNumbers } = contact; - const fullName = `${contact.givenName} ${contact.familyName}`; + let fullName = ''; + + if (!isEmpty(givenName)) fullName += givenName; + if (!isEmpty(familyName)) fullName += familyName; return ( { if (error) { @@ -90,29 +92,39 @@ export default class SignupScreenFive extends React.Component { }); } + requestPermissions() { + Permissions.request('contacts').then(permission => { + if (permission === 'authorized') return this.getContacts(); + this.props.navigation.navigate('signup6'); + }); + } + createSettingsAlert() { Alert.alert( - 'Tagfer does not have access to your contacts', + 'Contacts Access Denied', 'To enable access, tap Settings and turn on Contacts', [ { text: 'Cancel', onPress: () => this.props.navigation.navigate('signup6') }, - { text: 'Settings', onPress: () => Linking.openURL('app-settings:') } + { text: 'Settings', onPress: () => OpenAppSettings.open() } ] ); } - fetchContactsIOS() { - Contacts.checkPermission((error, permission) => { - if (error) this.props.navigation.navigate('signup6'); + fetchContacts() { + Permissions.check('contacts').then(permission => { + if (Platform.OS === 'ios') { + if (permission === 'restricted') return this.props.navigation.navigate('signup6'); + if (permission === 'denied') return this.createSettingsAlert(); + + return this.getContacts(); + } - if (permission === 'denied') { - this.createSettingsAlert(); - } else { - this.getContacts(); + if (Platform.OS === 'android') { + return permission === 'restricted' ? this.createSettingsAlert() : this.requestPermissions(); } }); } - // END: iOS Handlers + // END: Fetch Contacts renderItem(contact, index) { const selected = this.state.selectedContacts.has(index);