When talking about gathering information, context is king. Being able to establish context faster or better can separate you from the pack. Add to this an ability to obtain and display that data without the user having to lift a finger and now you've really got something. This essentially describes the relationship between Popcorn and Spokes. Popcorn is an innovative application that pulls the most pertinent information from Salesforce that a salesperson needs to make the conversation smarter and to keep the ball moving. It also gives the salesperson quick actions to take. So on it's own, it's intuitive, quick and easy to use.
![]() | ![]() |
Figure 1.1 - Searching up a person in Popcorn by name and selecting the result
Now imagine getting this same pop-up of information simply by receiving a phone call. This is where Spokes comes in. While Popcorn also subscribes to various headset state events, at the heart of Popcorn is it's monitoring of Call State events:
_session.CallEvents.CallStateChanged += _ui.EventCatcher; _session.CallEvents.CallRequested += _ui.EventCatcher;
In the snippet above, _ui is our main Windows.Form class and represents the starting point for any UI that is to appear on the screen. Above, we've subscribed to call-related events within Spokes. The _session class was declared prior this, as follows:
_sessionMgr = SessionManager.Instance; _session = _sessionMgr.Register(Name);
Name is the fully qualified name of our plugin dll. So now that we're listening to call events, how can we make the best use of that? Here's an abbreviated version of our EventCatcher method, which was established as the delegate above:
public void EventCatcher(object sender, EventArgs e) { if (e is DeviceListenerEventArgs) { DeviceListenerEventArgs devEvt = (DeviceListenerEventArgs)e; // leaving empty cases in to make it easier to add items later switch (devEvt.ATDStateChange) { case ATDStateChange.MobileCallEnded: this.UIThread(() => UpdateCallControls()); break; case ATDStateChange.MobileCallerID: this.UIThread(() => UpdateCallControls()); if (!_callMadeFromPopcorn) this.UIThread(() => ScreenStartSearch()); break; case ATDStateChange.MobileInComing: this.UIThread(() => UpdateCallControls()); if (!_callMadeFromPopcorn && !_profileSearchStarted) this.UIThread(() => ScreenStart()); break; case ATDStateChange.MobileOnCall: this.UIThread(() => UpdateCallControls()); break; case ATDStateChange.DeskphoneHeadset: case ATDStateChange.MobileOutGoing: case ATDStateChange.PstnInComingCallRingOff: case ATDStateChange.PstnInComingCallRingOn: case ATDStateChange.Unknown: default: break; } } }
You'll see that, based on the type of information we receive, something particular is done on the UI Thread. Sometimes, for us, it's as simple as just updating the call controls - our big call and hangup buttons. But let me point you to one of our most important pieces of code - the case where Spokes has hand-delivered us a MobileCallerID. When this event is received, we're cooking with gas. You'll see that at this point, we spawn a Search. At this point, we have the context that we really need - the phone number of the incoming or outgoing call. At this point, Popcorn is able to take this phone number and perform a query against Salesforce and return anything that matches. This is the ScreenStartSearch method specified above. If we get an exact match - we immediately display the screen (as seen in figure 1) for the profile found. If we get more than one profile match, we display a selection screen. If we can't find anything, we display a name search (also as seen in figure 1).
So you can see how this little bit of context can serve us in a big way - this single event handler above allows the user to get from incoming call to all of their most important Salesforce data and activities in seconds. All thanks to Spokes.
So this is very helpful during a call. Another way that Spokes and Popcorn work together is just before the call. As noted above, within Popcorn, you can search up someone within Salesforce at any given time, whether a call was received or not. So if I am preparing for a call, I would like have an individuals Salesforce information already pulled up in Popcorn. At this point, Popcorn simplifies your life even more, by allowing you to simply call up the individual, on your mobile device, directly from Popcorn. Again, with the help of Spokes:
private void Dial(Modals.DialOptions.DialSelectionOptions selection) { string cid = string.Empty; switch (selection) { case Modals.DialOptions.DialSelectionOptions.PhoneOnMobile: cid = PhoneUtility.ScrubPhoneNumberText(_profile.Phone); _plugin.ATDCommand.MakeMobileCall(cid); break; case Modals.DialOptions.DialSelectionOptions.MobileOnMobile: cid = PhoneUtility.ScrubPhoneNumberText(_profile.MobilePhone); _plugin.ATDCommand.MakeMobileCall(cid); break; default: break; } }
After you click the big green Dial button, this function is executed. Seeing as this is a lead, contact or user within Salesforce, the person could have a number of phone numbers to dial. Popcorn first presents a list of ways to dial the user, after clicking the Dial button: Call Mobile or Call Phone from my Phone. This is represented in the switch statement above. The profile, which was obviously already pulled from Salesforce, then gives us the number in question and finally, the Spokes Plugin class is accessed to make the call.
So now you see the chief ways that Popcorn makes use of Spokes to add value, via improved context and improved functionality. What will your application be able to do with this kind of power?
Mike Homol
Product Manager of Popcorn