Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 12 additions & 6 deletions android/src/main/java/chat/rocket/RealPathUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,17 @@ public static String getPathFromSavingTempFile(Context context, final Uri uri) {

ParcelFileDescriptor pfd = context.getContentResolver().openFileDescriptor(uri, "r");

FileChannel src = new FileInputStream(pfd.getFileDescriptor()).getChannel();
FileChannel dst = new FileOutputStream(tmpFile).getChannel();
dst.transferFrom(src, 0, src.size());
src.close();
dst.close();
InputStream fileStream = new FileInputStream(pfd.getFileDescriptor());
OutputStream newDatabase = new FileOutputStream(tmpFile);
byte[] buffer = new byte[1024];
int length;
while((length = fileStream.read(buffer)) > 0)
{
newDatabase.write(buffer, 0, length);
}
newDatabase.flush();
fileStream.close();
newDatabase.close();
} catch (IOException ex) {
return null;
}
Expand Down Expand Up @@ -199,4 +205,4 @@ public static String getMimeTypeFromUri(final Context context, final Uri uri) {
return "application/octet-stream";
}
}
}
}
7 changes: 5 additions & 2 deletions android/src/main/java/chat/rocket/ShareModule.java
Original file line number Diff line number Diff line change
Expand Up @@ -86,8 +86,11 @@ public WritableMap processIntent() {
} else if (type.equals("video/*")) {
type = "video/mp4";
}

map.putString("type", "media");
if(type.equals("text/x-vcard")) {
map.putString("type", "contact");
} else {
map.putString("type", "media");
}
}
}
}
Expand Down
9 changes: 9 additions & 0 deletions ios/ContactsHelper.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#import <Foundation/Foundation.h>
#import <Contacts/Contacts.h>

@interface ContactsHelper : NSObject
- (NSDictionary *) contactToDictionary:(CNContact *)person withThumbnails:(BOOL)withThumbnails API_AVAILABLE(ios(9.0));
- (NSString *) getPathForDirectory:(int)directory;
- (NSString *) thumbnailFilePath:(NSString *)recordID;
- (NSString *) getFilePathForThumbnailImage:(CNContact *)contact recordID:(NSString *)recordID API_AVAILABLE(ios(9.0));
@end
203 changes: 203 additions & 0 deletions ios/ContactsHelper.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,203 @@
#import <ContactsHelper.h>

@implementation ContactsHelper : NSObject

- (NSDictionary*)contactToDictionary:(CNContact *)person withThumbnails:(BOOL)withThumbnails API_AVAILABLE(ios(9.0)) {
NSMutableDictionary* output = [NSMutableDictionary dictionary];

NSString *recordID = person.identifier;
NSString *givenName = person.givenName;
NSString *familyName = person.familyName;
NSString *middleName = person.middleName;
NSString *company = person.organizationName;
NSString *jobTitle = person.jobTitle;
NSDateComponents *birthday = person.birthday;

[output setObject:recordID forKey: @"recordID"];

if (givenName) {
[output setObject: (givenName) ? givenName : @"" forKey:@"givenName"];
}

if (familyName) {
[output setObject: (familyName) ? familyName : @"" forKey:@"familyName"];
}

if(middleName){
[output setObject: (middleName) ? middleName : @"" forKey:@"middleName"];
}

if(company){
[output setObject: (company) ? company : @"" forKey:@"company"];
}

if(jobTitle){
[output setObject: (jobTitle) ? jobTitle : @"" forKey:@"jobTitle"];
}

if (birthday) {
if (birthday.month != NSDateComponentUndefined && birthday.day != NSDateComponentUndefined) {
//months are indexed to 0 in JavaScript (0 = January) so we subtract 1 from NSDateComponents.month
if (birthday.year != NSDateComponentUndefined) {
[output setObject:@{@"year": @(birthday.year), @"month": @(birthday.month - 1), @"day": @(birthday.day)} forKey:@"birthday"];
} else {
[output setObject:@{@"month": @(birthday.month - 1), @"day":@(birthday.day)} forKey:@"birthday"];
}
}
}

//handle phone numbers
NSMutableArray *phoneNumbers = [[NSMutableArray alloc] init];

for (CNLabeledValue<CNPhoneNumber*>* labeledValue in person.phoneNumbers) {
NSMutableDictionary* phone = [NSMutableDictionary dictionary];
NSString * label = [CNLabeledValue localizedStringForLabel:[labeledValue label]];
NSString* value = [[labeledValue value] stringValue];

if(value) {
if(!label) {
label = [CNLabeledValue localizedStringForLabel:@"other"];
}
[phone setObject: value forKey:@"number"];
[phone setObject: label forKey:@"label"];
[phoneNumbers addObject:phone];
}
}

[output setObject: phoneNumbers forKey:@"phoneNumbers"];
//end phone numbers

//handle urls
NSMutableArray *urlAddresses = [[NSMutableArray alloc] init];

for (CNLabeledValue<NSString*>* labeledValue in person.urlAddresses) {
NSMutableDictionary* url = [NSMutableDictionary dictionary];
NSString* label = [CNLabeledValue localizedStringForLabel:[labeledValue label]];
NSString* value = [labeledValue value];

if(value) {
if(!label) {
label = [CNLabeledValue localizedStringForLabel:@"home"];
}
[url setObject: value forKey:@"url"];
[url setObject: label forKey:@"label"];
[urlAddresses addObject:url];
} else {
NSLog(@"ignoring blank url");
}
}

[output setObject: urlAddresses forKey:@"urlAddresses"];

//end urls

//handle emails
NSMutableArray *emailAddreses = [[NSMutableArray alloc] init];

for (CNLabeledValue<NSString*>* labeledValue in person.emailAddresses) {
NSMutableDictionary* email = [NSMutableDictionary dictionary];
NSString* label = [CNLabeledValue localizedStringForLabel:[labeledValue label]];
NSString* value = [labeledValue value];

if(value) {
if(!label) {
label = [CNLabeledValue localizedStringForLabel:@"other"];
}
[email setObject: value forKey:@"email"];
[email setObject: label forKey:@"label"];
[emailAddreses addObject:email];
}
}

[output setObject: emailAddreses forKey:@"emailAddresses"];
//end emails

//handle postal addresses
NSMutableArray *postalAddresses = [[NSMutableArray alloc] init];

for (CNLabeledValue<CNPostalAddress*>* labeledValue in person.postalAddresses) {
CNPostalAddress* postalAddress = labeledValue.value;
NSMutableDictionary* address = [NSMutableDictionary dictionary];

NSString* street = postalAddress.street;
if(street){
[address setObject:street forKey:@"street"];
}
NSString* city = postalAddress.city;
if(city){
[address setObject:city forKey:@"city"];
}
NSString* state = postalAddress.state;
if(state){
[address setObject:state forKey:@"state"];
}
NSString* region = postalAddress.state;
if(region){
[address setObject:region forKey:@"region"];
}
NSString* postCode = postalAddress.postalCode;
if(postCode){
[address setObject:postCode forKey:@"postCode"];
}
NSString* country = postalAddress.country;
if(country){
[address setObject:country forKey:@"country"];
}

NSString* label = [CNLabeledValue localizedStringForLabel:labeledValue.label];
if(label) {
[address setObject:label forKey:@"label"];

[postalAddresses addObject:address];
}
}

[output setObject:postalAddresses forKey:@"postalAddresses"];
//end postal addresses

[output setValue:[NSNumber numberWithBool:person.imageDataAvailable] forKey:@"hasThumbnail"];
if (withThumbnails) {
[output setObject:[self getFilePathForThumbnailImage:person recordID:recordID] forKey:@"thumbnailPath"];
}

return output;
}

- (NSString *)getPathForDirectory:(int)directory {
NSArray *paths = NSSearchPathForDirectoriesInDomains(directory, NSUserDomainMask, YES);
return [paths firstObject];
}

- (NSString *)thumbnailFilePath:(NSString *)recordID {
NSString *filename = [recordID stringByReplacingOccurrencesOfString:@":ABPerson" withString:@""];
NSString* filepath = [NSString stringWithFormat:@"%@/rnextensionshare_%@.png", [self getPathForDirectory:NSCachesDirectory], filename];
return filepath;
}

- (NSString *)getFilePathForThumbnailImage:(CNContact *)contact recordID:(NSString *)recordID API_AVAILABLE(ios(9.0)) {
if (contact.imageDataAvailable){
NSString *filepath = [self thumbnailFilePath:recordID];
NSData *contactImageData = contact.thumbnailImageData;

if ([[NSFileManager defaultManager] fileExistsAtPath:filepath]) {
NSData *existingImageData = [NSData dataWithContentsOfFile: filepath];

if([contactImageData isEqual: existingImageData]) {
return filepath;
}
}

BOOL success = [[NSFileManager defaultManager] createFileAtPath:filepath contents:contactImageData attributes:nil];

if (!success) {
NSLog(@"Unable to copy image");
return @"";
}

return filepath;
}

return @"";
}

@end
17 changes: 15 additions & 2 deletions ios/ReactNativeShareExtension.m
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
#import <objc/runtime.h>

#import <React/RCTRootView.h>
#import <MobileCoreServices/MobileCoreServices.h>

Expand All @@ -6,6 +8,7 @@
#endif

#import "ReactNativeShareExtension.h"
#import "ContactsHelper.h"

NSExtensionContext* extensionContext;

Expand Down Expand Up @@ -80,12 +83,22 @@ - (void)extractDataFromContext:(NSExtensionContext *)context withCallback:(void(

// is an URL - Can be a path or Web URL
if ([(NSObject *)item isKindOfClass:[NSURL class]]) {
NSURL *url = (NSURL *) item;
NSURL *url = (NSURL *)item;
string = [url absoluteString];
type = ([[string pathExtension] isEqualToString:@""]) || [url.scheme containsString:@"http"] ? @"text" : @"media";

[data addObject:@{ @"value": string, @"type": type }];


// is a Dictionary
} else if ([(NSObject *)item isKindOfClass:[NSData class]]) {
if (@available(iOS 9.0, *)) {
NSArray *contacts = [CNContactVCardSerialization contactsWithData:(NSData *)item error:nil];
for (CNContact *contact in contacts) {
type = @"contact";
[data addObject:@{ @"value": [[ContactsHelper new] contactToDictionary:contact withThumbnails:true], @"type": type }];
}
}

// is a String
} else if ([(NSObject *)item isKindOfClass:[NSString class]]) {
string = (NSString *)item;
Expand Down
8 changes: 8 additions & 0 deletions ios/ReactNativeShareExtension.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
objects = {

/* Begin PBXBuildFile section */
1E908633243572E7005708C0 /* ContactsHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E908632243572E7005708C0 /* ContactsHelper.m */; };
41B5DE3E1D0B50D300949BD5 /* ReactNativeShareExtension.m in Sources */ = {isa = PBXBuildFile; fileRef = 41B5DE3D1D0B50D300949BD5 /* ReactNativeShareExtension.m */; };
/* End PBXBuildFile section */

Expand All @@ -23,6 +24,8 @@
/* End PBXCopyFilesBuildPhase section */

/* Begin PBXFileReference section */
1E908631243572D9005708C0 /* ContactsHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ContactsHelper.h; sourceTree = "<group>"; };
1E908632243572E7005708C0 /* ContactsHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ContactsHelper.m; sourceTree = "<group>"; };
41B5DE301D0B505800949BD5 /* libReactNativeShareExtension.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libReactNativeShareExtension.a; sourceTree = BUILT_PRODUCTS_DIR; };
41B5DE3D1D0B50D300949BD5 /* ReactNativeShareExtension.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReactNativeShareExtension.m; sourceTree = "<group>"; };
41B5DE3F1D0B50FA00949BD5 /* ReactNativeShareExtension.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ReactNativeShareExtension.h; sourceTree = "<group>"; };
Expand Down Expand Up @@ -58,6 +61,8 @@
41B5DE3C1D0B506B00949BD5 /* src */ = {
isa = PBXGroup;
children = (
1E908632243572E7005708C0 /* ContactsHelper.m */,
1E908631243572D9005708C0 /* ContactsHelper.h */,
41B5DE3F1D0B50FA00949BD5 /* ReactNativeShareExtension.h */,
41B5DE3D1D0B50D300949BD5 /* ReactNativeShareExtension.m */,
);
Expand Down Expand Up @@ -103,6 +108,7 @@
developmentRegion = English;
hasScannedForEncodings = 0;
knownRegions = (
English,
en,
);
mainGroup = 41B5DE271D0B505800949BD5;
Expand All @@ -120,6 +126,7 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
1E908633243572E7005708C0 /* ContactsHelper.m in Sources */,
41B5DE3E1D0B50D300949BD5 /* ReactNativeShareExtension.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -262,6 +269,7 @@
41B5DE3B1D0B505800949BD5 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>IDEDidComputeMac32BitWarning</key>
<true/>
</dict>
</plist>
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>SchemeUserState</key>
<dict>
<key>ReactNativeShareExtension.xcscheme_^#shared#^_</key>
<dict>
<key>orderHint</key>
<integer>0</integer>
</dict>
</dict>
</dict>
</plist>
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "rn-extensions-share",
"version": "2.3.10",
"version": "2.4.0-rc.1",
"description": "Share-Extension using react-native for both ios and android",
"main": "lib/index.js",
"scripts": {
Expand Down