Skip to content

Commit

Permalink
added attachments support
Browse files Browse the repository at this point in the history
  • Loading branch information
omorandi committed Aug 13, 2014
1 parent 5c663e0 commit 8276be1
Show file tree
Hide file tree
Showing 7 changed files with 358 additions and 61 deletions.
106 changes: 93 additions & 13 deletions Classes/ComOmorandiSMSDialogProxy.m
Original file line number Diff line number Diff line change
Expand Up @@ -3,24 +3,24 @@
#import "TiColor.h"
#import "TiApp.h"

@interface ComOmorandiSMSDialogProxy()

@property (nonatomic, assign) BOOL attachmentsDisabled;
@property (nonatomic, retain) NSMutableArray *attachments;

@end


@implementation ComOmorandiSMSDialogProxy

/*
Proxy memory management
*/


- (void) dealloc
{
RELEASE_TO_NIL(recipients);
[super dealloc];
}

-(void)_destroy
{
RELEASE_TO_NIL(recipients);
[super _destroy];
}


// Get the recipients array

Expand All @@ -45,6 +45,65 @@ -(void)addRecipient:(id)aRecipient
}


-(BOOL)attachmentsSupported
{
Class messageComposerClass = [self messageComposerClass];
if (messageComposerClass == nil) {
return NO;
}
if (![messageComposerClass respondsToSelector:@selector(canSendAttachments)]) {
return NO;
}
return [NSNumber numberWithBool:[messageComposerClass canSendAttachments]];
}


-(Class)messageComposerClass
{
return NSClassFromString(@"MFMessageComposeViewController");
}

-(id)canSendAttachments:(id)args
{
return [NSNumber numberWithBool:[self attachmentsSupported]];
}

-(void)disableUserAttachments:(id)args
{
self.attachmentsDisabled = YES;
}

-(void)addAttachment:(id)args
{
if (![self attachmentsSupported]) {
[self throwException:@"sending attachments is not supported on the current device" subreason:nil location:CODELOCATION];
}
if ([args count] < 1) {
[self throwException:@"expected string or TiBlob argument" subreason:nil location:CODELOCATION];
}

id attachment = [args objectAtIndex:0];

if (!([attachment isKindOfClass:[NSString class]] || [attachment isKindOfClass:[TiBlob class]])) {
[self throwException:@"expected string or TiBlob argument" subreason:nil location:CODELOCATION];
}

NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:attachment forKey:@"attachment"];

if ([args count] > 1) {
NSString *alternateFileName = [args objectAtIndex:1];
ENSURE_TYPE(alternateFileName, NSString);

[dict setObject:alternateFileName forKey:@"alternateFileName"];
}
if (self.attachments == nil) {
self.attachments = [NSMutableArray array];
}

[self.attachments addObject:dict];
}

// Check if the device provides sms sending capabilities
- (id)isSupported:(id)args
{
Expand All @@ -57,7 +116,7 @@ - (id)isSupported:(id)args
BOOL smsSupported = NO;

//First we check the existence of the MFMessageComposeViewController class
Class messageClass = (NSClassFromString(@"MFMessageComposeViewController"));
Class messageClass = [self messageComposerClass];

if (messageClass != nil)
{
Expand All @@ -74,8 +133,10 @@ - (id)isSupported:(id)args
// create and open the SMS dialog window
- (void)open:(id)args
{
ENSURE_SINGLE_ARG_OR_NIL(args, NSDictionary);

[self rememberSelf];
ENSURE_SINGLE_ARG_OR_NIL(args, NSDictionary);


// ensure that the functionality is supported
if (![self isSupported:nil])
Expand Down Expand Up @@ -123,7 +184,25 @@ - (void)open:(id)args

//set our proxy as delegate (for responding to messageComposeViewController:didFinishWithResult)
composer.messageComposeDelegate = self;


if (self.attachmentsDisabled) {
[composer disableUserAttachments];
}

if ([self.attachments count] > 0) {
for (NSDictionary *dict in self.attachments) {
id attachment = dict[@"attachment"];
NSString *alternateFileName = dict[@"alternateFileName"];
if ([attachment isKindOfClass:[NSString class]]) {
[composer addAttachmentURL:[TiUtils toURL:attachment proxy:self] withAlternateFilename:alternateFileName];
}
else if ([attachment isKindOfClass:[TiBlob class]]){
[composer addAttachmentData:[attachment data] typeIdentifier:[attachment mimeType] filename:alternateFileName];
}
}
}


//set the navbar color
if (barColor != nil)
{
Expand Down Expand Up @@ -203,7 +282,8 @@ - (void)messageComposeViewController:(MFMessageComposeViewController *)composer
[composer dismissViewControllerAnimated:YES completion:nil];

[self forgetSelf];
[self autorelease];}
[self autorelease];
}



Expand Down
124 changes: 77 additions & 47 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,27 +4,41 @@

The SMSDialog Module extends the Appcelerator Titanium Mobile framework implementing an iPhone dialog window that enables you to send in application text messages on behalf of the app user, exposing an API very similar to the one of the Ti.UI.EmailDialog object. Both recipients and body fields can be pre-populated from your application.


# New in Version 1.1.0: attachments support

![](./screenshots/mms.png)

Since iOS version 7.0, the `MFMessageComposeViewController` class allows adding attachments to SMS or iMessage messages, thus enabling the ability to send MMSs.
The SMSDialog module has been extended in order to support this feature through new API methods and properties:

* `canSendAttachments()`: return true if the current device/os combination allows sending attachments
* `disableUserAttachments()`: Disables the camera/attachment button in the message composition view
* `addAttachment(attachment, alternateFileName)`: add a new attachment as a string file path, or TiBlob, optionally setting an alternate file name for it



## Building and installing the SMSDialog Module ##

### BUILD ###
First, you must have your XCode and Titanium Mobile SDKs in place, and have at least read the first few pages of the [iOS Module Development Guide](http://docs.appcelerator.com/titanium/latest/#!/guide/iOS_Module_Development_Guide).

The build process can be launched using the build.py script that you find in the module's code root directory.

As a result, the `com.omorandi-iphone-1.0.2.zip` file will be generated.
As a result, the `com.omorandi-iphone-1.1.0.zip` file will be generated.

### INSTALL ###
You can either copy the module package (`com.omorandi-iphone-1.0.2.zip`) to `~/Library/Application\ Support/Titanium` and reference the module in your application (the Titanium SDK will automatically unzip the file in the right place), or manually launch the command:
You can either copy the module package (`com.omorandi-iphone-1.1.0.zip`) to `~/Library/Application\ Support/Titanium` and reference the module in your application (the Titanium SDK will automatically unzip the file in the right place), or manually launch the command:

unzip -u -o com.omorandi-iphone-1.0.2.zip -d ~/Library/Application\ Support/Titanium/
unzip -u -o com.omorandi-iphone-1.1.0.zip -d ~/Library/Application\ Support/Titanium/


## Referencing the module in your Titanium Mobile application ##

Simply add the following lines to your `tiapp.xml` file:

<modules>
<module version="1.0.2" platform="iphone">com.omorandi</module>
<module version="1.1.0" platform="iphone">com.omorandi</module>
</modules>


Expand Down Expand Up @@ -108,52 +122,68 @@ a string containing a textual description of the result

## Usage

//instantiate the module
var module = require('com.omorandi');
Ti.API.info("module is => " + module);

//create the smsDialog object
var smsDialog = module.createSMSDialog();

//check if the feature is available on the device at hand
if (!smsDialog.isSupported())
{
//falls here when executed on iOS versions < 4.0 and in the emulator
var a = Ti.UI.createAlertDialog({title: 'warning', message: 'the required feature is not available on your device'});
a.show();
```JavaScript
//instantiate the module
var module = require('com.omorandi');
Ti.API.info("module is => " + module);

//create the smsDialog object
var smsDialog = module.createSMSDialog();

//check if the feature is available on the device at hand
if (!smsDialog.isSupported())
{
//falls here when executed on iOS versions < 4.0 and in the emulator
var a = Ti.UI.createAlertDialog({title: 'warning', message: 'the required feature is not available on your device'});
a.show();
}
else
{
//pre-populate the dialog with the info provided in the following properties
smsDialog.recipients = ['+14151234567'];
smsDialog.messageBody = 'Test message from me';

//set the color of the title-bar
smsDialog.barColor = 'red';

//add attachments if supported
if (smsDialog.canSendAttachments()) {
Ti.API.info('We can send attachments');
//add an attachment as a file path
smsDialog.addAttachment('images/01.jpg', 'image1.jpg');

var file = Ti.Filesystem.getFile('images/02.jpg');
//add an attachment as a TiBlob
smsDialog.addAttachment(file.read(), 'image2.jpg');
}
else
{
//pre-populate the dialog with the info provided in the following properties
smsDialog.recipients = ['+14151234567'];
smsDialog.messageBody = 'Test message from me';

//set the color of the title-bar
smsDialog.barColor = 'red';

//add an event listener for the 'complete' event, in order to be notified about the result of the operation
smsDialog.addEventListener('complete', function(e){
Ti.API.info("Result: " + e.resultMessage);
var a = Ti.UI.createAlertDialog({title: 'complete', message: 'Result: ' + e.resultMessage});
a.show();
if (e.result == smsDialog.SENT)
{
//do something
}
else if (e.result == smsDialog.FAILED)
{
//do something else
}
else if (e.result == smsDialog.CANCELLED)
{
//don't bother
}
});

//open the SMS dialog window with slide-up animation
smsDialog.open({animated: true});
else {
Ti.API.info('We cannot send attachments');
}

//add an event listener for the 'complete' event, in order to be notified about the result of the operation
smsDialog.addEventListener('complete', function(e){
Ti.API.info("Result: " + e.resultMessage);
var a = Ti.UI.createAlertDialog({title: 'complete', message: 'Result: ' + e.resultMessage});
a.show();
if (e.result == smsDialog.SENT)
{
//do something
}
else if (e.result == smsDialog.FAILED)
{
//do something else
}
else if (e.result == smsDialog.CANCELLED)
{
//don't bother
}
});

//open the SMS dialog window with slide-up animation
smsDialog.open({animated: true});
}

```

## Author

Expand Down
Loading

0 comments on commit 8276be1

Please sign in to comment.