Skip to content

Instantly share code, notes, and snippets.

@marcoscaceres
Last active December 16, 2015 15:49
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save marcoscaceres/5459002 to your computer and use it in GitHub Desktop.
Save marcoscaceres/5459002 to your computer and use it in GitHub Desktop.

Rethinking the Messaging API

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 messages and dealing with events

//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);
}

Improved MessagingCursor

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
};
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment