Chatter Mobile 4.2 and Visualforce Publisher Actions

It was a quiet update: version 4.2 of Chatter Mobile, now available. No fanfare. Maybe you get a lot of update notifications on your iPhone, so you didn't notice. Maybe you have never downloaded Chatter Mobile. Maybe...you should. Read on to learn how to add a Visualforce Page as a Quick Action in Chatter Mobile.

It was a quiet update: version 4.2 of Chatter Mobile, now available. No fanfare. Maybe you get a lot of update notifications on your iPhone, so you didn’t notice.  Maybe you have never downloaded Chatter Mobile.  Maybe…you should.  This might just be the killer app you need for the $1M hackathon!

Daniel Hoechst did. He broke the news with his post: Chatter Mobile and Visualforce, showing how to add a Hello World page to the Chatter Mobile app’s left-hand navigation.

This is just the beginning.  The Chatter Mobile app makes it dead easy to expose records from the salesforce.com cloud database on a mobile device, without any code.  Now you can extend it with code, which is AWESOME!

The possibilities are endless, but let’s get started with a simple example.

Backstory

The Developer Evangelism team uses a custom app on the Salesforce Platform to manage the Dreamforce ’13 Developer Track sessions.  With Chatter Mobile 4.1, we have been reviewing our session decks and updating session records on our phones or tablets.  Now, we can do more.

Let’s add the ability to Tweet about a session, right from the Session record, so that each Evangelist can easily promote the 20+ sessions they manage.  To do this we need a Visualforce page that backs a publisher Action on the Session object.

If you are not familiar with Salesforce’s markup language, Visualforce, don’t worry. Think of it as a container for your HTML and Javascript. You need to learn a few new tags, and then you’re all set.

The first two things you need to know are:

1. the <apex:page> tag, which needs to wrap all of your other tags
2. the API Name of the Salesforce Object that stores the data you need to access

Simple Visualforce Page

Let’s walk through how to do it.

Before we start coding, we need to Enable Publisher Actions in our Salesforce organization (if you do not have a Salesforce org, get one for free here). In Setup, go to Customize | Chatter | Settings. Make sure that the Enable Publisher Actions checkbox is checked.

Now, we need to create a Visualforce page that posts to Twitter.  This was easier than I expected.  All we need is the the Twitter Web Intent URL and two merge fields, {!session__c.title__c} and {!session__c.Lead_Speaker_Name__c}, from the Session object to populate the tweet with the data from our session records.  This standardizes the message, and saves a ton of time for each Developer Evangelist.

In this example, the API Name of our Salesforce object is Session__c. We use this in the <apex:page> tag to define the controller for our page, in this example it is a standard controller, so no Apex Code is required. You can also create custom controllers and controller extensions, but that is for another day.

To create a new Visualforce page from Setup, go to Develop | Pages and click New.  (There are many other options for code editing in Force.com, but for this example we are going to stay in the Setup web interface.)  Enter a label and make sure to check the Available for Salesforce mobile apps checkbox.

My first simple page looked like this.

<apex:page standardController="Session__c">
 <h1>
 <a href="https://twitter.com/intent/tweet?status=Join+me+at+the+{!session__c.title__c}+session+in+the+%23devzone+%40dreamforce">Join Me!</a>
 <br/>
 <a href="https://twitter.com/intent/tweet?status=Great+dry+run+with+{!session__c.Lead_Speaker_Name__c}+for+{!session__c.title__c}+session+%23devzone+%40dreamforce">Great Dry Run!</a>
 <br/>
 <a href="https://twitter.com/intent/tweet?status=Can%27t+wait+to+see+{!session__c.Lead_Speaker_Name__c}+rock+the+%23devzone in {!session__c.title__c}+%40dreamforce">Can't Wait!</a>
 </h1>
</apex:page>

Let’s test the page in the browser.

It works, but the styling could use some work.  We can fix that later.

Publisher Actions

Next, to expose this Visualforce page to end users in either the Salesforce browser app or the Chatter Mobile app, we need to decide whether to make a Global Action or an Object-level Action. Global Actions are available in the publisher on the main feed and on record feeds for all objects, which is overkill for this scenario – we just need it on the Session feed publisher. Also, we need the Session context to retrieve the merge fields using the standard controller, so we need to create an Object-level Action.

Creating an Action is easy.

In Setup, navigate to Create | Objects and select the Session object.  Actions are managed on the Buttons, Links, and Actions related list.  Click New Action on that related list and set the Action Type to Custom Visualforce and select the Visualforce page (in this example it is named SessionTweet).

Now we have an Action, but there is one more step before the end users will see it.  We need to add it to the Page Layout for the Session object.

Adding an Action to a Page Layout is easy.  We’re still on the Session object detail page, so we go to the Page Layouts related list and click Edit on the default page layout.  The Page Layout Editor is a WYSIWYG tool to define the user interface for the new, edit, and detail pages in the desktop browser app UI, and now that same metadata is driving the Chatter Mobile UI.

Notice the Publisher Actions heading on the layout, and click override the global publisher layout.  At the top of the editor, in the palette, select Actions from the left-hand menu.  Then drag our custom Action, Tweet, into the Publisher Actions area and drop it.  Save.

Now, we’re ready to test the Action.  Let’s do that in the browser first, just to make sure the layout is correct.  Navigate to the Sessions tab in the Salesforce UI, then select a Session, and we see the Tweet action in the Chatter Publisher.  Click Tweet and we should see our three links.  It works!

That’s nothing new, though.  What’s new is that, with no additional configuration, it will now display in Chatter Mobile.  But first, let’s clean up that styling.

Styling

Let’s override some of the standard Salesforce behavior. To do that, we set the showHeader, sidebar, and standardStylesheets attributes to false.

<apex:page docType="html-5.0"
 showHeader="false" 
 sidebar="false"
 standardStylesheets="false"
 standardController="Session__c">
 <h1>
 <a href="https://twitter.com/intent/tweet?status=Join+me+at+the+{!session__c.title__c}+session+in+the+%23devzone+%40dreamforce">Join Me!</a>
 <br/>
 <a href="https://twitter.com/intent/tweet?status=Great+dry+run+with+{!session__c.Lead_Speaker_Name__c}+for+{!session__c.title__c}+session+%23devzone+%40dreamforce">Great Dry Run!</a>
 <br/>
 <a href="https://twitter.com/intent/tweet?status=Can%27t+wait+to+see+{!session__c.Lead_Speaker_Name__c}+rock+the+%23devzone in {!session__c.title__c}+%40dreamforce">Can't Wait!</a>
 </h1>
</apex:page>

Now, we can add our custom HTML and Javascript.

I am using the Salesforce Mobile Templates. I included the templates here as Static Resources, using the Visualforce tags <apex:stylesheet> and <apex:includeScript>.

<apex:page docType="html-5.0"
 showHeader="false" 
 sidebar="false"
 standardStylesheets="false"
 standardController="Session__c">
<head>
 <meta charset="utf-8"/>
 <meta name="viewport" content="width=device-width, initial-scale=1, 
 minimum-scale=1, maximum-scale=1, user-scalable=no"/> 
 <apex:stylesheet value="{!URLFOR($Resource.MobileDesignTemplates, 
 'Mobile-Design-Templates-master/common/css/app.min.css')}"/>
 <apex:includeScript value="{!URLFOR($Resource.MobileDesignTemplates, 
 'Mobile-Design-Templates-master/common/js/jQuery2.0.2.min.js')}"/>
 <apex:includeScript value="{!URLFOR($Resource.MobileDesignTemplates, 
 'Mobile-Design-Templates-master/common/js/jquery.touchwipe.min.js')}"/>
 <apex:includeScript value="{!URLFOR($Resource.MobileDesignTemplates, 
 'Mobile-Design-Templates-master/common/js/main.min.js')}"/>
 </head>
 <h1>
 <a href="https://twitter.com/intent/tweet?status=Join+me+at+the+{!session__c.title__c}+session+in+the+%23devzone+%40dreamforce">Join Me!</a>
 <br/>
 <a href="https://twitter.com/intent/tweet?status=Great+dry+run+with+{!session__c.Lead_Speaker_Name__c}+for+{!session__c.title__c}+session+%23devzone+%40dreamforce">Great Dry Run!</a>
 <br/>
 <a href="https://twitter.com/intent/tweet?status=Can%27t+wait+to+see+{!session__c.Lead_Speaker_Name__c}+rock+the+%23devzone in {!session__c.title__c}+%40dreamforce">Can't Wait!</a>
 </h1>
</apex:page>

Now, instead of the <h1> tags, let’s use the Mobile Template styles.  Personally, I like my buttons to be grey, so I am overriding the color.  This is the full, final, Visualforce page markup.

<apex:page docType="html-5.0"
           showHeader="false" 
           sidebar="false"
           standardStylesheets="false"
           standardController="Session__c">

    <style>
        .data-capture-buttons a {
        background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #597f86), color-stop(100%, #7ba8b0));
        background-image: -webkit-linear-gradient(top, #838383, #a9a9a9);
        background-image: -moz-linear-gradient(top, #838383, #a9a9a9);
        background-image: -o-linear-gradient(top, #838383, #a9a9a9);
        background-image: linear-gradient(top, #838383, #a9a9a9);
        font-size: 200%;
    </style>           

   <head>
      <meta charset="utf-8"/>
      <meta name="viewport" content="width=device-width, initial-scale=1, 
                                  minimum-scale=1, maximum-scale=1, user-scalable=no"/> 
      <apex:stylesheet value="{!URLFOR($Resource.MobileDesignTemplates, 
                'Mobile-Design-Templates-master/common/css/app.min.css')}"/>
      <apex:includeScript value="{!URLFOR($Resource.MobileDesignTemplates, 
                'Mobile-Design-Templates-master/common/js/jQuery2.0.2.min.js')}"/>
      <apex:includeScript value="{!URLFOR($Resource.MobileDesignTemplates, 
                'Mobile-Design-Templates-master/common/js/jquery.touchwipe.min.js')}"/>
      <apex:includeScript value="{!URLFOR($Resource.MobileDesignTemplates, 
                'Mobile-Design-Templates-master/common/js/main.min.js')}"/>
   </head>

   <body>
        <section>
         <div>
             <a href="https://twitter.com/intent/tweet?status=Join+me+at+the+{!Session__c.Title__c}+session+in+the+%23devzone+%40dreamforce">Join Me!</a>
         </div>
       </section>
       <section>
         <div>
             <a href="https://twitter.com/intent/tweet?status=Great+dry+run+with+{!Session__c.Lead_Speaker_Name__c}+for+{!Session__c.Title__c}+session+%23devzone+%40dreamforce">Great Dry Run!</a>
         </div>
       </section>
        <section>
         <div>
             <a href="https://twitter.com/intent/tweet?status=Can%27t+wait+to+see+{!Session__c.Lead_Speaker_Name__c}+rock+the+%23devzone in {!Session__c.Title__c}+%40dreamforce">Rock Star!</a>
         </div>
       </section>
   </body>

</apex:page>

OK.  Let’s give it a try in the Chatter Mobile app.  Note that Sessions are displayed in the RECENT section in the left-hand navigation.  This happens automatically, to display the most relevant standard or custom Objects for each user.

Tap to navigate to a session record.  Here’s a good one about developing offline mobile apps with the Salesforce Mobile SDK (shameless plug!).

Then tap the + to access the list of actions.  Our custom Action, Tweet, is to the right of the Post action because that’s where we placed it on the Session Page Layout.

Then tap Tweet, and we see our custom Visualforce page with the newly styled buttons.

Tom Gersic is a rock star, so let’s tap Rock Star! to tweet about him and his session.  This navigates to the Twitter status interface and includes our text with the speaker name and session title merge fields populated based on the Session record.

Now, we can choose to edit the status, or just Tweet it as is (which is what I did). Done!

Bring it to Dreamforce!

I am excited to see our developer community extend the Chatter Mobile app with code.  Post your examples here, or if you are coming to Dreamforce, bring us your ideas and your examples, we’d love to see them!

Leave your comments...

Chatter Mobile 4.2 and Visualforce Publisher Actions