diff --git a/README.md b/README.md
index 0a6594b7..d8f4e252 100644
--- a/README.md
+++ b/README.md
@@ -226,6 +226,18 @@ iOS Quirks:
```
+##### Experimental feature: sharing directly to someone
+Available in 5.0.8 and up - please let me know if this works for your device! Open an issue if not..
+
+```html
+
+```
+For `receiver` on iOS pass in the Addressbook ID (or 'abid'). You can find those abid's by using the [Cordova Contacts Plugin](https://github.com/apache/cordova-plugin-contacts).
+The result in the success callback of the `find` function is a JSON array of contact objects, use the 'id' you find in those objects.
+Don't pass in an image on iOS because that can't be sent to someone directly unfortunately. Message and URL are fine though.
+
+On Android pass in the phone number of the person you want to send a message to (untested at the moment).
+
####SMS
Note that on Android, SMS via Hangouts may not behave correctly
```html
@@ -381,7 +393,7 @@ Here's the list of available activities you can disable :
## 4b. Usage on Windows Phone
-The available methods on WP8 are: `available`, `canShareViaEmail`, `share` and `shareViaEmail`.
+The available methods on WP8 are: `available`, `canShareViaEmail`, `share`, `shareViaEmail` and `shareViaSMS`.
Currently the first two always return true, but this may change in the future in case I can find a way to truly detect the availability.
The `share` function on WP8 supports two flavours: message only, or a combination of message, title and link.
diff --git a/package.json b/package.json
index 5f21e1d9..b34769e8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "cordova-plugin-x-socialsharing",
- "version": "5.0.6",
+ "version": "5.0.10",
"description": "Share text, images (and other files), or a link via the native sharing widget of your device. Android is fully supported, as well as iOS 6 and up. WP8 has somewhat limited support.",
"cordova": {
"id": "cordova-plugin-x-socialsharing",
@@ -29,7 +29,7 @@
"ecosystem:cordova",
"cordova-ios",
"cordova-android",
- "cordova-wp8"
+ "cordova-windows"
],
"engines": [
{
diff --git a/plugin.xml b/plugin.xml
index 9a66d554..3b9c7289 100755
--- a/plugin.xml
+++ b/plugin.xml
@@ -1,8 +1,8 @@
+ id="cordova-plugin-x-socialsharing"
+ version="5.0.10">
SocialSharing
@@ -71,6 +71,7 @@
+
diff --git a/src/android/nl/xservices/plugins/SocialSharing.java b/src/android/nl/xservices/plugins/SocialSharing.java
index 08e9724b..521c546c 100644
--- a/src/android/nl/xservices/plugins/SocialSharing.java
+++ b/src/android/nl/xservices/plugins/SocialSharing.java
@@ -47,7 +47,9 @@ public class SocialSharing extends CordovaPlugin {
private static final String ACTION_SHARE_VIA_SMS_EVENT = "shareViaSMS";
private static final String ACTION_SHARE_VIA_EMAIL_EVENT = "shareViaEmail";
+ private static final int ACTIVITY_CODE_SEND = 1;
private static final int ACTIVITY_CODE_SENDVIAEMAIL = 2;
+ private static final int ACTIVITY_CODE_SENDVIAWHATSAPP = 3;
private CallbackContext _callbackContext;
@@ -77,7 +79,11 @@ public boolean execute(String action, JSONArray args, CallbackContext callbackCo
this.pasteMessage = args.getString(4);
return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "com.facebook.katana", false);
} else if (ACTION_SHARE_VIA_WHATSAPP_EVENT.equals(action)) {
- return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "whatsapp", false);
+ if (notEmpty(args.getString(4))) {
+ return shareViaWhatsAppDirectly(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), args.getString(4));
+ } else {
+ return doSendIntent(callbackContext, args.getString(0), args.getString(1), args.getJSONArray(2), args.getString(3), "whatsapp", false);
+ }
} else if (ACTION_SHARE_VIA_INSTAGRAM_EVENT.equals(action)) {
if (notEmpty(args.getString(0))) {
copyHintToClipboard(args.getString(0), "Instagram paste message");
@@ -222,6 +228,7 @@ public void run() {
if (notEmpty(subject)) {
sendIntent.putExtra(Intent.EXTRA_SUBJECT, subject);
}
+
// add the URL to the message, as there seems to be no separate field
if (notEmpty(url)) {
if (notEmpty(message)) {
@@ -275,7 +282,7 @@ public void run() {
if (peek) {
callbackContext.sendPluginResult(new PluginResult(PluginResult.Status.OK));
} else {
- mycordova.startActivityForResult(plugin, Intent.createChooser(sendIntent, null), 1);
+ mycordova.startActivityForResult(plugin, Intent.createChooser(sendIntent, null), ACTIVITY_CODE_SEND);
}
}
}
@@ -319,6 +326,10 @@ private Uri getFileUriAndSetType(Intent sendIntent, String dir, String image, St
Matcher matcher = dispositionPattern.matcher(disposition);
if (matcher.find()) {
filename = matcher.group(1).replaceAll("[^a-zA-Z0-9._-]", "");
+ if (filename.length() == 0) {
+ // in this case we can't determine a filetype so some targets (gmail) may not render it correctly
+ filename = "file";
+ }
localImage = "file://" + dir + "/" + filename;
}
}
@@ -350,12 +361,80 @@ private Uri getFileUriAndSetType(Intent sendIntent, String dir, String image, St
}
saveFile(Base64.decode(encodedImg, Base64.DEFAULT), dir, fileName);
localImage = "file://" + dir + "/" + fileName;
+ } else if (image.startsWith("df:")) {
+ // safeguard for https://code.google.com/p/android/issues/detail?id=7901#c43
+ if (!image.contains(";base64,")) {
+ sendIntent.setType("text/plain");
+ return null;
+ }
+ // format looks like this : df:filename.txt;data:image/png;base64,R0lGODlhDAA...
+ final String fileName = image.substring(image.indexOf("df:") + 3, image.indexOf(";data:"));
+ final String fileType = image.substring(image.indexOf(";data:") + 6, image.indexOf(";base64,"));
+ final String encodedImg = image.substring(image.indexOf(";base64,") + 8);
+ sendIntent.setType(fileType);
+ saveFile(Base64.decode(encodedImg, Base64.DEFAULT), dir, sanitizeFilename(fileName));
+ localImage = "file://" + dir + "/" + fileName;
} else if (!image.startsWith("file://")) {
throw new IllegalArgumentException("URL_NOT_SUPPORTED");
}
return Uri.parse(localImage);
}
+ private boolean shareViaWhatsAppDirectly(final CallbackContext callbackContext, String message, final String subject, final JSONArray files, final String url, final String number) {
+ // add the URL to the message, as there seems to be no separate field
+ if (notEmpty(url)) {
+ if (notEmpty(message)) {
+ message += " " + url;
+ } else {
+ message = url;
+ }
+ }
+ final String shareMessage = message;
+ final SocialSharing plugin = this;
+ cordova.getThreadPool().execute(new SocialSharingRunnable(callbackContext) {
+ public void run() {
+ Intent intent = new Intent(Intent.ACTION_SENDTO);
+ intent.setData(Uri.parse("smsto:" + number));
+
+ intent.putExtra("sms_body", shareMessage);
+ intent.putExtra("sms_subject", subject);
+ intent.setPackage("com.whatsapp");
+
+ try {
+ if (files.length() > 0 && !"".equals(files.getString(0))) {
+ final boolean hasMultipleAttachments = files.length() > 1;
+ final String dir = getDownloadDir();
+ if (dir != null) {
+ ArrayList fileUris = new ArrayList();
+ Uri fileUri = null;
+ for (int i = 0; i < files.length(); i++) {
+ fileUri = getFileUriAndSetType(intent, dir, files.getString(i), subject, i);
+ if (fileUri != null) {
+ fileUris.add(fileUri);
+ }
+ }
+ if (!fileUris.isEmpty()) {
+ if (hasMultipleAttachments) {
+ intent.putExtra(Intent.EXTRA_STREAM, fileUris);
+ } else {
+ intent.putExtra(Intent.EXTRA_STREAM, fileUri);
+ }
+ }
+ }
+ }
+ } catch (Exception e) {
+ callbackContext.error(e.getMessage());
+ }
+ try {
+ cordova.startActivityForResult(plugin, intent, ACTIVITY_CODE_SENDVIAWHATSAPP);
+ } catch (Exception e) {
+ callbackContext.error(e.getMessage());
+ }
+ }
+ });
+ return true;
+ }
+
private boolean invokeSMSIntent(final CallbackContext callbackContext, JSONObject options, String p_phonenumbers) {
final String message = options.optString("message");
// TODO test this on a real SMS enabled device before releasing it
@@ -458,13 +537,16 @@ private void createOrCleanDir(final String downloadDir) throws IOException {
}
private static String getFileName(String url) {
+ if (url.endsWith("/")) {
+ url = url.substring(0, url.length()-1);
+ }
final String pattern = ".*/([^?#]+)?";
Pattern r = Pattern.compile(pattern);
Matcher m = r.matcher(url);
if (m.find()) {
return m.group(1);
} else {
- return null;
+ return "file";
}
}
diff --git a/src/ios/SocialSharing.h b/src/ios/SocialSharing.h
index b51474d3..399cd239 100755
--- a/src/ios/SocialSharing.h
+++ b/src/ios/SocialSharing.h
@@ -4,7 +4,7 @@
@interface SocialSharing : CDVPlugin
@property (nonatomic, strong) MFMailComposeViewController *globalMailComposer;
-@property (retain) UIDocumentInteractionController * documentInteractionController;
+@property (nonatomic, strong) UIDocumentInteractionController * documentInteractionController;
@property (retain) NSString * tempStoredFile;
@property (retain) CDVInvokedUrlCommand * command;
diff --git a/src/ios/SocialSharing.m b/src/ios/SocialSharing.m
index cd0913a4..6e6fe49e 100755
--- a/src/ios/SocialSharing.m
+++ b/src/ios/SocialSharing.m
@@ -57,15 +57,15 @@ - (void)share:(CDVInvokedUrlCommand*)command {
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
return;
}
-
+
NSString *message = [command.arguments objectAtIndex:0];
NSString *subject = [command.arguments objectAtIndex:1];
NSArray *filenames = [command.arguments objectAtIndex:2];
NSString *urlString = [command.arguments objectAtIndex:3];
-
+
NSMutableArray *activityItems = [[NSMutableArray alloc] init];
[activityItems addObject:message];
-
+
NSMutableArray *files = [[NSMutableArray alloc] init];
if (filenames != (id)[NSNull null] && filenames.count > 0) {
for (NSString* filename in filenames) {
@@ -79,18 +79,18 @@ - (void)share:(CDVInvokedUrlCommand*)command {
}
[activityItems addObjectsFromArray:files];
}
-
+
if (urlString != (id)[NSNull null]) {
- [activityItems addObject:[NSURL URLWithString:urlString]];
+ [activityItems addObject:[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]];
}
-
+
UIActivity *activity = [[UIActivity alloc] init];
NSArray *applicationActivities = [[NSArray alloc] initWithObjects:activity, nil];
UIActivityViewController *activityVC = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:applicationActivities];
if (subject != (id)[NSNull null]) {
[activityVC setValue:subject forKey:@"subject"];
}
-
+
// TODO deprecated in iOS 8.0, change this some day
[activityVC setCompletionHandler:^(NSString *activityType, BOOL completed) {
[self cleanupStoredFiles];
@@ -98,12 +98,12 @@ - (void)share:(CDVInvokedUrlCommand*)command {
CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_OK messageAsBool:completed];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
}];
-
+
NSArray * socialSharingExcludeActivities = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"SocialSharingExcludeActivities"];
if (socialSharingExcludeActivities!=nil && [socialSharingExcludeActivities count] > 0) {
activityVC.excludedActivityTypes = socialSharingExcludeActivities;
}
-
+
dispatch_async(dispatch_get_main_queue(), ^(void){
// iPad on iOS >= 8 needs a different approach
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
@@ -230,27 +230,27 @@ - (bool)isAvailableForSharing:(CDVInvokedUrlCommand*)command
- (void)shareViaInternal:(CDVInvokedUrlCommand*)command
type:(NSString *) type {
-
+
NSString *message = [command.arguments objectAtIndex:0];
// subject is not supported by the SLComposeViewController
NSArray *filenames = [command.arguments objectAtIndex:2];
NSString *urlString = [command.arguments objectAtIndex:3];
-
+
// boldly invoke the target app, because the phone will display a nice message asking to configure the app
SLComposeViewController *composeViewController = [SLComposeViewController composeViewControllerForServiceType:type];
if (message != (id)[NSNull null]) {
[composeViewController setInitialText:message];
}
-
+
for (NSString* filename in filenames) {
UIImage* image = [self getImage:filename];
if (image != nil) {
[composeViewController addImage:image];
}
}
-
+
if (urlString != (id)[NSNull null]) {
- [composeViewController addURL:[NSURL URLWithString:urlString]];
+ [composeViewController addURL:[NSURL URLWithString:[urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]]];
}
[composeViewController setCompletionHandler:^(SLComposeViewControllerResult result) {
@@ -272,7 +272,7 @@ - (void)shareViaInternal:(CDVInvokedUrlCommand*)command
- (void)shareViaEmail:(CDVInvokedUrlCommand*)command {
if ([self isEmailAvailable]) {
-
+
if (TARGET_IPHONE_SIMULATOR && IsAtLeastiOSVersion(@"8.0")) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"SocialSharing plugin"
message:@"Sharing via email is not supported on the iOS 8 simulator."
@@ -282,38 +282,38 @@ - (void)shareViaEmail:(CDVInvokedUrlCommand*)command {
[alert show];
return;
}
-
+
self.globalMailComposer.mailComposeDelegate = self;
-
+
if ([command.arguments objectAtIndex:0] != (id)[NSNull null]) {
NSString *message = [command.arguments objectAtIndex:0];
BOOL isHTML = [message rangeOfString:@"<[^>]+>" options:NSRegularExpressionSearch].location != NSNotFound;
[self.globalMailComposer setMessageBody:message isHTML:isHTML];
}
-
+
if ([command.arguments objectAtIndex:1] != (id)[NSNull null]) {
[self.globalMailComposer setSubject: [command.arguments objectAtIndex:1]];
}
-
+
if ([command.arguments objectAtIndex:2] != (id)[NSNull null]) {
[self.globalMailComposer setToRecipients:[command.arguments objectAtIndex:2]];
}
-
+
if ([command.arguments objectAtIndex:3] != (id)[NSNull null]) {
[self.globalMailComposer setCcRecipients:[command.arguments objectAtIndex:3]];
}
-
+
if ([command.arguments objectAtIndex:4] != (id)[NSNull null]) {
[self.globalMailComposer setBccRecipients:[command.arguments objectAtIndex:4]];
}
-
+
if ([command.arguments objectAtIndex:5] != (id)[NSNull null]) {
NSArray* attachments = [command.arguments objectAtIndex:5];
NSFileManager* fileManager = [NSFileManager defaultManager];
for (NSString* path in attachments) {
NSURL *file = [self getFile:path];
NSData* data = [fileManager contentsAtPath:file.path];
-
+
NSString* fileName;
NSString* mimeType;
NSString* basename = [self getBasenameFromAttachmentPath:path];
@@ -331,14 +331,14 @@ - (void)shareViaEmail:(CDVInvokedUrlCommand*)command {
[self.globalMailComposer addAttachmentData:data mimeType:mimeType fileName:fileName];
}
}
-
+
// remember the command, because we need it in the didFinishWithResult method
_command = command;
[self.commandDelegate runInBackground:^{
[[self getTopMostViewController] presentViewController:self.globalMailComposer animated:YES completion:nil];
}];
-
+
} else {
CDVPluginResult * pluginResult = [CDVPluginResult resultWithStatus:CDVCommandStatus_ERROR messageAsString:@"not available"];
[self.commandDelegate sendPluginResult:pluginResult callbackId:command.callbackId];
@@ -406,7 +406,7 @@ - (void)shareViaSMS:(CDVInvokedUrlCommand*)command {
NSString *message = [options objectForKey:@"message"];
NSString *subject = [options objectForKey:@"subject"];
NSString *image = [options objectForKey:@"image"];
-
+
MFMessageComposeViewController *picker = [[MFMessageComposeViewController alloc] init];
picker.messageComposeDelegate = (id) self;
if (message != (id)[NSNull null]) {
@@ -424,7 +424,7 @@ - (void)shareViaSMS:(CDVInvokedUrlCommand*)command {
}
}
}
-
+
if (phonenumbers != (id)[NSNull null]) {
[picker setRecipients:[phonenumbers componentsSeparatedByString:@","]];
}
@@ -469,7 +469,7 @@ - (void)openImage:(NSString *)imageName {
}
- (void)shareViaInstagram:(CDVInvokedUrlCommand*)command {
-
+
// on iOS9 canShareVia('instagram'..) will only work if instagram:// is whitelisted.
// If it's not, this method will ask permission to the user on iOS9 for opening the app,
// which is of course better than Instagram sharing not working at all because you forgot to whitelist it.
@@ -492,7 +492,7 @@ - (void)shareViaInstagram:(CDVInvokedUrlCommand*)command {
image = [self getImage:filename];
break;
}
-
+
// NSData *imageObj = [NSData dataFromBase64String:objectAtIndex0];
NSString *tmpDir = NSTemporaryDirectory();
NSString *path = [tmpDir stringByAppendingPathComponent:@"instagram.igo"];
@@ -517,7 +517,7 @@ - (void)shareViaInstagram:(CDVInvokedUrlCommand*)command {
}
- (void)shareViaWhatsApp:(CDVInvokedUrlCommand*)command {
-
+
// on iOS9 canShareVia('whatsapp'..) will only work if whatsapp:// is whitelisted.
// If it's not, this method will ask permission to the user on iOS9 for opening the app,
// which is of course better than WhatsApp sharing not working at all because you forgot to whitelist it.
@@ -534,6 +534,7 @@ - (void)shareViaWhatsApp:(CDVInvokedUrlCommand*)command {
// subject is not supported by the SLComposeViewController
NSArray *filenames = [command.arguments objectAtIndex:2];
NSString *urlString = [command.arguments objectAtIndex:3];
+ NSString *abid = [command.arguments objectAtIndex:4];
// only use the first image (for now.. maybe we can share in a loop?)
UIImage* image = nil;
@@ -561,14 +562,18 @@ - (void)shareViaWhatsApp:(CDVInvokedUrlCommand*)command {
if ([shareString isEqual: @""]) {
shareString = urlString;
} else {
- shareString = [NSString stringWithFormat:@"%@ %@", shareString, urlString];
+ shareString = [NSString stringWithFormat:@"%@ %@", shareString, [urlString stringByAddingPercentEscapesUsingEncoding: NSUTF8StringEncoding]];
}
}
NSString * encodedShareString = [shareString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
// also encode the '=' character
encodedShareString = [encodedShareString stringByReplacingOccurrencesOfString:@"=" withString:@"%3D"];
encodedShareString = [encodedShareString stringByReplacingOccurrencesOfString:@"&" withString:@"%26"];
- NSString * encodedShareStringForWhatsApp = [NSString stringWithFormat:@"whatsapp://send?text=%@", encodedShareString];
+ NSString * abidString = @"";
+ if (abid != (id)[NSNull null]) {
+ abidString = [NSString stringWithFormat:@"abid=%@&", abid];
+ }
+ NSString * encodedShareStringForWhatsApp = [NSString stringWithFormat:@"whatsapp://send?%@text=%@", abidString, encodedShareString];
NSURL *whatsappURL = [NSURL URLWithString:encodedShareStringForWhatsApp];
[[UIApplication sharedApplication] openURL: whatsappURL];
diff --git a/src/windows/SocialSharingProxy.js b/src/windows/SocialSharingProxy.js
index 99e0af15..ff257d52 100644
--- a/src/windows/SocialSharingProxy.js
+++ b/src/windows/SocialSharingProxy.js
@@ -10,6 +10,36 @@ module.exports = {
var fileOrFileArray = args[2];
//Web link
var url = args[3];
+
+ var folder = Windows.Storage.ApplicationData.current.temporaryFolder;
+
+ var getExtension = function (strBase64) {
+ return strBase64.substring(strBase64.indexOf("/") + 1, strBase64.indexOf(";base64"));
+ };
+
+ var replaceAll = function (str, find, replace) {
+ return str.replace(new RegExp(find, 'g'), replace);
+ };
+
+ var sanitizeFilename = function (name) {
+ return replaceAll(name, "[:\\\\/*?|<> ]", "_");
+ };
+
+ var getFileName = function (position, fileExtension) {
+ var fileName = (subject ? sanitizeFilename(subject) : "file") + (position == 0 ? "" : "_" + position) + "." + fileExtension;
+ return fileName;
+ };
+
+ var createTemporalFile = function (fileName, buffer) {
+
+ var filePath = "";
+ return folder.createFileAsync(fileName, Windows.Storage.CreationCollisionOption.replaceExisting).then(function (file) {
+ filePath = file.path;
+ return Windows.Storage.FileIO.writeBufferAsync(file, buffer);
+ }).then(function(){
+ return Windows.Storage.StorageFile.getFileFromPathAsync(filePath);
+ });
+ };
var doShare = function (e) {
e.request.data.properties.title = subject?subject: "Sharing";
@@ -19,25 +49,49 @@ module.exports = {
var deferral = e.request.getDeferral();
var storageItems = [];
var filesCount = fileOrFileArray.length;
+
+ var completeFile = function () {
+ if (!--filesCount) {
+ storageItems.length && e.request.data.setStorageItems(storageItems);
+ deferral.complete();
+ }
+ };
+
for (var i = 0; i < fileOrFileArray.length; i++) {
- Windows.Storage.StorageFile.getFileFromPathAsync(fileOrFileArray[i]).done(
- function (file) {
- storageItems.push(file);
- if (!--filesCount) {
- e.request.data.setStorageItems(storageItems);
- deferral.complete();
- }
- },
- function() {
- if (!--filesCount) {
- e.request.data.setStorageItems(storageItems);
- deferral.complete();
+
+ var file = fileOrFileArray[i];
+ if (file.indexOf("data:") >= 0) {
+ var fileName = getFileName(i, getExtension(file));
+ var buffer = Windows.Security.Cryptography.CryptographicBuffer.decodeFromBase64String(file.split(',')[1]);
+ if (buffer) {
+ createTemporalFile(fileName, buffer).done(
+ function (file) {
+ storageItems.push(file);
+ completeFile();
+ },
+ function () {
+ completeFile();
+ }
+ );
+ }
+ else {
+ completeFile();
+ }
+ }
+ else {
+ Windows.Storage.StorageFile.getFileFromPathAsync(file).done(
+ function (file) {
+ storageItems.push(file);
+ completeFile();
+ },
+ function () {
+ completeFile();
}
- }
- );
+ );
+ }
}
}
- }
+ };
var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
@@ -96,7 +150,7 @@ module.exports = {
);
}
}
- }
+ };
var dataTransferManager = Windows.ApplicationModel.DataTransfer.DataTransferManager.getForCurrentView();
diff --git a/src/wp8/Newtonsoft.Json.dll b/src/wp8/Newtonsoft.Json.dll
new file mode 100755
index 00000000..b8194284
Binary files /dev/null and b/src/wp8/Newtonsoft.Json.dll differ
diff --git a/src/wp8/SocialSharing.cs b/src/wp8/SocialSharing.cs
index 351bac93..1a165127 100644
--- a/src/wp8/SocialSharing.cs
+++ b/src/wp8/SocialSharing.cs
@@ -4,6 +4,8 @@
using WPCordovaClassLib.Cordova.Commands;
using WPCordovaClassLib.Cordova.JSON;
+using Newtonsoft.Json;
+
namespace Cordova.Extension.Commands
{
public class SocialSharing : BaseCommand
@@ -76,5 +78,26 @@ public void shareViaEmail(string jsonArgs)
draft.Show();
DispatchCommandResult(new PluginResult(PluginResult.Status.OK, true));
}
+
+ public void shareViaSMS(string jsonArgs)
+ {
+ var options = JsonHelper.Deserialize(jsonArgs);
+
+ SmsComposeTask smsComposeTask = new SmsComposeTask();
+
+ smsComposeTask.To = options[1];
+ SMSMessageClass m = JsonConvert.DeserializeObject(options[0]);
+ smsComposeTask.Body = m.message;
+
+ smsComposeTask.Show();
+
+ DispatchCommandResult(new PluginResult(PluginResult.Status.OK, true));
+ }
+ }
+
+ public class SMSMessageClass
+ {
+ public string message { get; set; }
}
+
}
\ No newline at end of file
diff --git a/tests/plugin.xml b/tests/plugin.xml
index 44bad99a..1ccb2217 100644
--- a/tests/plugin.xml
+++ b/tests/plugin.xml
@@ -9,5 +9,5 @@
Nicolas Oliver
MIT
-
+
\ No newline at end of file
diff --git a/tests/test.js b/tests/test.js
new file mode 100644
index 00000000..ad1a8229
--- /dev/null
+++ b/tests/test.js
@@ -0,0 +1,363 @@
+/**
+ * Jasmine Based test suites
+ *
+ * Several of SocialSharing APIs cannot be automatically tested, because
+ * they depend on user interaction in order to call success or fail
+ * handlers. For most of them, there is a basic test that assert the presence of
+ * the API.
+ *
+ * There are some cases that test automation can be applied, i.e in "canShareVia",
+ * "canShareViaEmail" and "available" methods. For those cases, there is some level
+ * of automatic test coverage.
+ */
+exports.defineAutoTests = function () {
+ 'use strict';
+
+ describe('socialsharing', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing).toBeDefined();
+ });
+
+ describe('share', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.share).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.share).toEqual('function');
+ });
+ });
+
+ describe('shareVia', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.shareVia).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.shareVia).toEqual('function');
+ });
+ });
+
+ describe('shareViaTwitter', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.shareViaTwitter).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.shareViaTwitter).toEqual('function');
+ });
+ });
+
+ describe('shareViaFacebook', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.shareViaFacebook).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.shareViaFacebook).toEqual('function');
+ });
+ });
+
+ describe('shareViaFacebookWithPasteMessageHint', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.shareViaFacebookWithPasteMessageHint).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.shareViaFacebookWithPasteMessageHint).toEqual('function');
+ });
+ });
+
+ describe('shareViaWhatsApp', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.shareViaWhatsApp).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.shareViaWhatsApp).toEqual('function');
+ });
+ });
+
+ describe('shareViaSMS', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.shareViaSMS).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.shareViaSMS).toEqual('function');
+ });
+ });
+
+ describe('shareViaEmail', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.shareViaEmail).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.shareViaEmail).toEqual('function');
+ });
+ });
+
+ describe('canShareVia', function () {
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.canShareVia).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.canShareVia).toEqual('function');
+ });
+
+ it('should always call callback or error function', function (done) {
+ function onSuccess(data){
+ expect(data).not.toEqual(null);
+ done();
+ }
+
+ function onError(error){
+ expect(error).not.toEqual(null);
+ done();
+ }
+
+ window.plugins.socialsharing.canShareVia('dummytarget','dummymessage', null, null, null, onSuccess, onError);
+ });
+ });
+
+ describe('canshareViaEmail', function(){
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.canShareViaEmail).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.canShareViaEmail).toEqual('function');
+ });
+
+ it('should always call callback or error function', function (done) {
+ function onSuccess(data){
+ expect(data).not.toEqual(null);
+ done();
+ }
+
+ function onError(error){
+ expect(error).not.toEqual(null);
+ done();
+ }
+
+ window.plugins.socialsharing.canShareViaEmail(onSuccess, onError);
+ });
+ });
+
+ describe('availabe', function(){
+ it('should be defined', function () {
+ expect(window.plugins.socialsharing.available).toBeDefined();
+ });
+
+ it('should be a function', function () {
+ expect(typeof window.plugins.socialsharing.available).toEqual('function');
+ });
+
+ it('should return a boolean when called', function(done){
+ window.plugins.socialsharing.available(function(isAvailable) {
+ expect(typeof isAvailable).toEqual('boolean');
+ done();
+ });
+ });
+ });
+ });
+};
+
+/**
+ * Manual tests suites
+ *
+ * Some actions buttons to execute SocialSharing plugin methods
+ */
+exports.defineManualTests = function (contentEl, createActionButton) {
+ 'use strict';
+
+ /** helper function to log messages in the log div element */
+ function logMessage(message, color) {
+ var log = document.getElementById('info'),
+ logLine = document.createElement('div');
+
+ if (color) {
+ logLine.style.color = color;
+ }
+
+ logLine.innerHTML = message;
+ log.appendChild(logLine);
+ }
+
+ /** helper function to clear the log div element */
+ function clearLog() {
+ var log = document.getElementById('info');
+ log.innerHTML = '';
+ }
+
+ /** helper function to declare a not implemented test */
+ function testNotImplemented(testName) {
+ return function () {
+ console.error(testName, 'test not implemented');
+ };
+ }
+
+ /** init method called on deviceready event */
+ function init() {}
+
+ /** object to hold properties and configs */
+ var TestSuite = {};
+
+ TestSuite.getCanShareViaTarget = function(){
+ return document.getElementById('inputCanShareVia').value;
+ };
+
+ TestSuite.$markup = '' +
+ '
' +
+
+ '' +
+
+ '' +
+ '';
+
+ contentEl.innerHTML = '' + TestSuite.$markup;
+
+ createActionButton('availabe', function () {
+ clearLog();
+ window.plugins.socialsharing.available(function(isAvailable) {
+ var message = 'is this plugin available? ';
+ message += isAvailable? 'Yes' : 'No';
+
+ logMessage(message, isAvailable? 'green' : 'red');
+ });
+ }, 'buttonIsAvailable');
+
+ createActionButton('share message', function () {
+ window.plugins.socialsharing.share('Message body');
+ }, 'buttonShareMessage');
+
+ createActionButton('share message and subject', function () {
+ window.plugins.socialsharing.share('Message body', 'Message subject');
+ }, 'buttonShareMessageWithSubject');
+
+ createActionButton('share link', function () {
+ window.plugins.socialsharing.share(null, null, null, 'http://www.x-services.nl');
+ }, 'buttonShareLink');
+
+ createActionButton('share message and link', function () {
+ window.plugins.socialsharing.share('Message body', null, null, 'http://www.x-services.nl');
+ }, 'buttonShareMessageAndLink');
+
+ createActionButton('share image', function () {
+ window.plugins.socialsharing.share(null, null, 'https://www.google.nl/images/srpr/logo4w.png', null);
+ }, 'buttonShareImage');
+
+ createActionButton('share image base 64', function () {
+ window.plugins.socialsharing.share(null, 'Android filename', 'data:image/png;base64,R0lGODlhDAAMALMBAP8AAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAUKAAEALAAAAAAMAAwAQAQZMMhJK7iY4p3nlZ8XgmNlnibXdVqolmhcRQA7', null);
+ }, 'buttonShareImageBase64');
+
+ createActionButton('share message with image', function () {
+ window.plugins.socialsharing.share('Message body', null, 'https://www.google.nl/images/srpr/logo4w.png', null);
+ }, 'buttonShareMessageImage');
+
+ createActionButton('share message, image, and link', function () {
+ window.plugins.socialsharing.share('Message body', null, 'https://www.google.nl/images/srpr/logo4w.png', 'http://www.x-services.nl');
+ }, 'buttonShareMessageImageLink');
+
+ createActionButton('share message, subject, image, and link', function () {
+ window.plugins.socialsharing.share('Message body', 'Message subject', 'https://www.google.nl/images/srpr/logo4w.png', 'http://www.x-services.nl');
+ }, 'buttonShareMessageSubjectImageLink');
+
+ createActionButton('can share via', function () {
+ var target = TestSuite.getCanShareViaTarget();
+
+ if(!target){
+ console.error('must have a canShareVia target');
+ }
+ else {
+ clearLog();
+ window.plugins.socialsharing.canShareVia(target, 'msg', null, null, null, function(e){
+ console.log('canShareVia success, see log for more information');
+ logMessage('canShareVia: ' + e,'green');
+ }, function(e){
+ console.error('canShareVia fail, see log for more information');
+ var message = "Share targets
";
+
+ message += "";
+
+ e.forEach(function(target){
+ message += "- " + target + "
";
+ });
+
+ message += "
";
+ logMessage(message,'red');
+ });
+ }
+ }, 'buttonCanShareVia');
+
+ createActionButton('can share via email', function () {
+ clearLog();
+ window.plugins.socialsharing.canShareViaEmail(function(e){
+ console.log('canShareViaEmail success, see log for more information');
+ logMessage('canShareViaEmail: ' + e,'green');
+ }, function(e){
+ console.error('canShareViaEmail fail, see log for more information');
+ logMessage('canShareViaEmail: ' + e,'red');
+ });
+ }, 'buttonCanShareViaEmail');
+
+ document.addEventListener('deviceready', init, false);
+};
diff --git a/tests/tests.js b/tests/tests.js
deleted file mode 100644
index bcf78b5f..00000000
--- a/tests/tests.js
+++ /dev/null
@@ -1,363 +0,0 @@
-/**
- * Jasmine Based test suites
- *
- * Several of SocialSharing APIs cannot be automatically tested, because
- * they depend on user interaction in order to call success or fail
- * handlers. For most of them, there is a basic test that assert the presence of
- * the API.
- *
- * There are some cases that test automation can be applied, i.e in "canShareVia",
- * "canShareViaEmail" and "available" methods. For those cases, there is some level
- * of automatic test coverage.
- */
-exports.defineAutoTests = function () {
- 'use strict';
-
- describe('socialsharing', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing).toBeDefined();
- });
-
- describe('share', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing.share).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.share).toEqual('function');
- });
- });
-
- describe('shareVia', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing.shareVia).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.shareVia).toEqual('function');
- });
- });
-
- describe('shareViaTwitter', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing.shareViaTwitter).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.shareViaTwitter).toEqual('function');
- });
- });
-
- describe('shareViaFacebook', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing.shareViaFacebook).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.shareViaFacebook).toEqual('function');
- });
- });
-
- describe('shareViaFacebookWithPasteMessageHint', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing.shareViaFacebookWithPasteMessageHint).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.shareViaFacebookWithPasteMessageHint).toEqual('function');
- });
- });
-
- describe('shareViaWhatsApp', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing.shareViaWhatsApp).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.shareViaWhatsApp).toEqual('function');
- });
- });
-
- describe('shareViaSMS', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing.shareViaSMS).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.shareViaSMS).toEqual('function');
- });
- });
-
- describe('shareViaEmail', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing.shareViaEmail).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.shareViaEmail).toEqual('function');
- });
- });
-
- describe('canShareVia', function () {
- it('should be defined', function () {
- expect(window.plugins.socialsharing.canShareVia).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.canShareVia).toEqual('function');
- });
-
- it('should always call callback or error function', function (done) {
- function onSuccess(data){
- expect(data).not.toEqual(null);
- done();
- }
-
- function onError(error){
- expect(error).not.toEqual(null);
- done();
- }
-
- window.plugins.socialsharing.canShareVia('dummytarget','dummymessage', null, null, null, onSuccess, onError);
- });
- });
-
- describe('canshareViaEmail', function(){
- it('should be defined', function () {
- expect(window.plugins.socialsharing.canShareViaEmail).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.canShareViaEmail).toEqual('function');
- });
-
- it('should always call callback or error function', function (done) {
- function onSuccess(data){
- expect(data).not.toEqual(null);
- done();
- }
-
- function onError(error){
- expect(error).not.toEqual(null);
- done();
- }
-
- window.plugins.socialsharing.canShareViaEmail(onSuccess, onError);
- });
- });
-
- describe('availabe', function(){
- it('should be defined', function () {
- expect(window.plugins.socialsharing.available).toBeDefined();
- });
-
- it('should be a function', function () {
- expect(typeof window.plugins.socialsharing.available).toEqual('function');
- });
-
- it('should return a boolean when called', function(done){
- window.plugins.socialsharing.available(function(isAvailable) {
- expect(typeof isAvailable).toEqual('boolean');
- done();
- });
- });
- });
- });
-};
-
-/**
- * Manual tests suites
- *
- * Some actions buttons to execute SocialSharing plugin methods
- */
-exports.defineManualTests = function (contentEl, createActionButton) {
- 'use strict';
-
- /** helper function to log messages in the log div element */
- function logMessage(message, color) {
- var log = document.getElementById('info'),
- logLine = document.createElement('div');
-
- if (color) {
- logLine.style.color = color;
- }
-
- logLine.innerHTML = message;
- log.appendChild(logLine);
- }
-
- /** helper function to clear the log div element */
- function clearLog() {
- var log = document.getElementById('info');
- log.innerHTML = '';
- }
-
- /** helper function to declare a not implemented test */
- function testNotImplemented(testName) {
- return function () {
- console.error(testName, 'test not implemented');
- };
- }
-
- /** init method called on deviceready event */
- function init() {}
-
- /** object to hold properties and configs */
- var TestSuite = {};
-
- TestSuite.getCanShareViaTarget = function(){
- return document.getElementById('inputCanShareVia').value;
- };
-
- TestSuite.$markup = '' +
- '' +
-
- '' +
-
- '' +
- '';
-
- contentEl.innerHTML = '' + TestSuite.$markup;
-
- createActionButton('availabe', function () {
- clearLog();
- window.plugins.socialsharing.available(function(isAvailable) {
- var message = 'is this plugin available? ';
- message += isAvailable? 'Yes' : 'No';
-
- logMessage(message, isAvailable? 'green' : 'red');
- });
- }, 'buttonIsAvailable');
-
- createActionButton('share message', function () {
- window.plugins.socialsharing.share('Message body');
- }, 'buttonShareMessage');
-
- createActionButton('share message and subject', function () {
- window.plugins.socialsharing.share('Message body', 'Message subject');
- }, 'buttonShareMessageWithSubject');
-
- createActionButton('share link', function () {
- window.plugins.socialsharing.share(null, null, null, 'http://www.x-services.nl');
- }, 'buttonShareLink');
-
- createActionButton('share message and link', function () {
- window.plugins.socialsharing.share('Message body', null, null, 'http://www.x-services.nl');
- }, 'buttonShareMessageAndLink');
-
- createActionButton('share image', function () {
- window.plugins.socialsharing.share(null, null, 'https://www.google.nl/images/srpr/logo4w.png', null);
- }, 'buttonShareImage');
-
- createActionButton('share image base 64', function () {
- window.plugins.socialsharing.share(null, 'Android filename', 'data:image/png;base64,R0lGODlhDAAMALMBAP8AAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAUKAAEALAAAAAAMAAwAQAQZMMhJK7iY4p3nlZ8XgmNlnibXdVqolmhcRQA7', null);
- }, 'buttonShareImageBase64');
-
- createActionButton('share message with image', function () {
- window.plugins.socialsharing.share('Message body', null, 'https://www.google.nl/images/srpr/logo4w.png', null);
- }, 'buttonShareMessageImage');
-
- createActionButton('share message, image, and link', function () {
- window.plugins.socialsharing.share('Message body', null, 'https://www.google.nl/images/srpr/logo4w.png', 'http://www.x-services.nl');
- }, 'buttonShareMessageImageLink');
-
- createActionButton('share message, subject, image, and link', function () {
- window.plugins.socialsharing.share('Message body', 'Message subject', 'https://www.google.nl/images/srpr/logo4w.png', 'http://www.x-services.nl');
- }, 'buttonShareMessageSubjectImageLink');
-
- createActionButton('can share via', function () {
- var target = TestSuite.getCanShareViaTarget();
-
- if(!target){
- console.error('must have a canShareVia target');
- }
- else {
- clearLog();
- window.plugins.socialsharing.canShareVia(target, 'msg', null, null, null, function(e){
- console.log('canShareVia success, see log for more information');
- logMessage('canShareVia: ' + e,'green');
- }, function(e){
- console.error('canShareVia fail, see log for more information');
- var message = "Share targets
";
-
- message += "";
-
- e.forEach(function(target){
- message += "- " + target + "
";
- });
-
- message += "
";
- logMessage(message,'red');
- });
- }
- }, 'buttonCanShareVia');
-
- createActionButton('can share via email', function () {
- clearLog();
- window.plugins.socialsharing.canShareViaEmail(function(e){
- console.log('canShareViaEmail success, see log for more information');
- logMessage('canShareViaEmail: ' + e,'green');
- }, function(e){
- console.error('canShareViaEmail fail, see log for more information');
- logMessage('canShareViaEmail: ' + e,'red');
- });
- }, 'buttonCanShareViaEmail');
-
- document.addEventListener('deviceready', init, false);
-};
\ No newline at end of file
diff --git a/www/SocialSharing.js b/www/SocialSharing.js
index 6ccd567b..f056c9fd 100644
--- a/www/SocialSharing.js
+++ b/www/SocialSharing.js
@@ -1,4 +1,4 @@
-var cordova = require('cordova');
+var cordova = require('cordova');
function SocialSharing() {
}
@@ -49,7 +49,11 @@ SocialSharing.prototype.shareViaFacebookWithPasteMessageHint = function (message
};
SocialSharing.prototype.shareViaWhatsApp = function (message, fileOrFileArray, url, successCallback, errorCallback) {
- cordova.exec(successCallback, this._getErrorCallback(errorCallback, "shareViaWhatsApp"), "SocialSharing", "shareViaWhatsApp", [message, null, this._asArray(fileOrFileArray), url]);
+ cordova.exec(successCallback, this._getErrorCallback(errorCallback, "shareViaWhatsApp"), "SocialSharing", "shareViaWhatsApp", [message, null, this._asArray(fileOrFileArray), url, null]);
+};
+
+SocialSharing.prototype.shareViaWhatsAppToReceiver = function (receiver, message, fileOrFileArray, url, successCallback, errorCallback) {
+ cordova.exec(successCallback, this._getErrorCallback(errorCallback, "shareViaWhatsAppToReceiver"), "SocialSharing", "shareViaWhatsApp", [message, null, this._asArray(fileOrFileArray), url, receiver]);
};
SocialSharing.prototype.shareViaSMS = function (options, phonenumbers, successCallback, errorCallback) {