The current abstractions are kinda messaged up in the Messaging (and Contacts) API. For one, you need to deal with objects directly sometimes, other times you need to deal with them through events, or through a manager etc. This makes the whole API very difficult and confusing to use - it's also not very "JavaScripty".
I propose that the API be changed so it works like this:
//Sending SMS - returns a Future.
var msg = {to: "+12312", body: "Hello There!"};
Messaging.send("sms", msg).done(updateUI);
//allow arrays of numbers
var msg = {to: ["+123324", "+455612312"], body: "Hello There!"};
Messaging.send("sms", msg).done(updateUI);
//allow contacts
var msg = {to: contacts, body: "Hello There!"};
var contacts = Contacts.find("").then( function(){
Messaging.send("sms", msg).done(updateUI);
}
//Sending mms - returns ProgressFuture
Messaging.send("mms","foo@bar.com", "Hello There!")
.progress(updateProgress)
.done(updateUI);
Messaging.send("mms", {... details ...}).done(updateUI);
...
//capture progress and delivery
Messaging.send("sms","+12312", "Hello There!")
.then(handleDelivery, showErrorUI)
.done(updateUI);
function handleDelivery(sms){
//Mixing events and futures is kinda messy... not sure how best to deal with it.
sms.ondeliverysuccess = (e) => deliverSuccess(this);
sms.ondeliveryfail= (e) => deliverFail(this);
}
MessagingManager just becomes Messaging:
interface Messaging{
static Future send(DOMString type, (SMSContent or MMSContent) content);
... other attributes/methods...
};
#Using contacts and Messaging together It should be possible to use a list of contacts together with messaging API.
var msg = "Dudes! My house. Now!";
//`friends` being a result set of Contacts
Messaging.send("sms", friends, msg).done(updateUI);
The new interface would be:
interface SmsMessage : EventTarget {
readonly attribute DOMString messageID;
readonly attribute MessageType type;
readonly attribute DOMString serviceID;
readonly attribute DOMString from;
readonly attribute Date timestamp;
readonly attribute boolean read;
readonly attribute DOMString[] to;
readonly attribute DOMString body;
readonly attribute SmsState state;
readonly attribute DeliveryStatus? deliveryStatus;
readonly attribute DOMString messageClass;
//event handlers
attribute EventHandler ondeliverysuccess;
attribute EventHandler ondeliveryfail;
//Methods
Future markAsRead(optional boolean read = true);
};
#Working with results Whem retriving results, a MessageList should be returned that provides the capabilities of MessageManager. In addition it would be nide to be able to "filter" results that were returned. Filtering only filters on the already retrieved result set, potentially making it more efficient to work with the results. So:
//Serach for a particular subject, and mark all those results as read.
var query = {subject: "foo"};
Messaging.find("messages", {subject: "foo"}).done( (results) => results.markAsRead() );
Messaging.find("messages", {subject: "foo"}).done( filterBySomething );
function filterBySomething(results){
var query = {... ...},
filteredResults = results.filter(query);
updateUI(results);
}
Even more awesome, filter searches:
Messaging.find("messages", {subject: "foo"}).then( showResults );
showResults(results){
//update ui... refine query
if(userWantsToRefineQuery){
refineResults(type, results, criteria);
}
}
function refineResults(type, results, criteria){
results.find(type, criteria).then(showResults);
}
The MessagingCursor is way too limited and not very JavaScripty. Firstly, it should provide a getter that allows it to behave like an array. Secondly, it should be built for purpose: working with messages in bulk.
I want to be able to do this:
//find all foo and mark them as read.
Messaging.find("messages", {subject: "foo"}).done( (results) => results.markAsRead());
//Incrementally filter out stuff.
var filter1 = {subject: "foo"};
var filter2 = {from: "bar"};
var filter3 = {read: false};
var promise = Messaging.find("messages", filter1)
.then((results) => results.filter(filter1))
.then((results) => results.filter(filter2));
//iterate properly
function iterate(results){
for(var i = 0, id; i < results.length; i++){
id = results[i];
results.fetch(id).getMessage((result) => showIt(result));
}
}
Something like:
interface MessageResultList {
readonly attribute unsigned long length;
getter DOMString? item(unsigned long index);
boolean contains(DOMString id);
Future filter(MessagingFilter filter); //filter the current result set.
Future markAsRead(optional boolean or (MessagingFilter) or (DOMString or DOMString[]) messages = true, optional boolean value = true);
Future getMessage((DOMString or sequence<DOMString>) id); //Fetch the message object
};