Pages

Try the processWave.org Diagram Editor now!

Use the processWave.org Editor in Google Wave (discontinued).

Watch the screencasts showing the editor in Google Wave or Google+ Hangouts.

Check out our MIT-licensed source code on GitHub.

December 2, 2009

Invity - Behind the Scenes

We hope you enjoyed Invity, our group management robot for Google Wave. Now we want to reveal the code behind our robot and share our thoughts and problems with you.

At first, we developed Invity as a pure robot without any sophisticated user interface. One had to type something like "#groups.save myFriends" in a Blip to save a group. However, we quickly realized it would be cool to have a gadget that allows more comfortable user interaction. But as gadgets are not able to invite people, it was obvious to us that the robot has in some way to interact with the gadget. The reason is that the gadget has to delegate the user input to the robot and the robot has to push the info about a user's groups to the gadget.

We use the state of the gadget to save the input of a user.
When someone clicks on "Invite!", we do the following:
var state = wave.getState();
var viewer = wave.getViewer().getId();
var value = gadgets.json.stringify({ 'action' : action, 'groupName' : groupName, 'viewer' : viewer });
state.submitValue('command', value); 
On the robot side, we parse and execute the action the user specified like this:
JSONObject json = new JSONObject(command);
String action = json.getString("action");
String groupName = json.getString("groupName");
String viewer = json.getString("viewer");
if (action.equals("save")) {
    saveGroup(event, groupName, viewer);
} 
The saveGroup method look like this:
private void saveGroup(RobotMessageBundle bundle, String groupName, String viewer) {
    PersistenceManager db = PMF.get().getPersistenceManager();
    List<String> participants = bundle.getWavelet().getParticipants();
    List<Group> groups = fetchGroupByName(groupName, viewer, db);
    if (groups.isEmpty()) {
          participants.remove("pw-invity@appspot.com");
          Group group = new Group(groupName, participants, viewer);
          db.makePersistent(group);
    }
    db.close();
}
We were quite impressed how easy and reliable this saving of groups in the Data Viewer works. However, from the robot to the gadget, the communication does not work quite that well. When we tried to display the current groups of a user in the gadget, we encountered a strange behaviour:

We use the setProperty method in the following way to save the groups of all participants of a wave in the gadget state:
String allGroups = createJSONFromGroups(participants);
gadget.setProperty("allGroups", allGroups); 
We expected that this call would trigger the updateState callback as specified on the gadget side:
wave.setStateCallback(displayState);
Unfortunately, the displayState method is not called when the robot changes the gadget state. So we had to build an ugly workaround which deletes the gadget and reinserts it after the robot commits a change:
private void reinsertGadget(RobotMessageBundle bundle) {
    List<Blip> allBlips = bundle.getWavelet().getRootBlip().getChildren();
    Blip gadgetBlip = deleteGadgetFromBlips(allBlips);
    Gadget newGadget = new Gadget(gadgetURL);
    updateGadgetState(bundle, newGadget);
    gadgetBlip.getDocument().getGadgetView().append(newGadget);
} 
We're not really happy with this solution, but as Google knows about this issue, we hope we can delete it soon.

Sources

You can get the full source code for the Robot and for the Gadget at http://wave-samples-gallery.appspot.com/about_app?app_id=77015. Feel free to modify and reuse under the terms of the MIT License (http://www.opensource.org/licenses/mit-license.php).

If you have not tried out Invity yet, just add pw-invity@appspot.com to one of your waves.

5 comments:

  1. Hi,
    Thanks for sharing. Really interesting and useful robot.
    It does not seem to difficult to implement.

    Daniel Graversen
    MasteringWave.com

    ReplyDelete
  2. How can i make a google wave gadget using C#.NET?

    ReplyDelete
  3. From a technical point of view, Gadgets are (X)HTML documents embedded into a Wave. As the browser does all the interpretation of the content, you can either use JavaScript or Plugins for interactivity.

    I'm not sure if there are browser plugins that execute C#/.NET code - however I saw some gadgets written with Adobe Flash.

    However, I would not suggest using anything else than JavaScript.... too many issues like cross platform compatibility, speed, ....

    ReplyDelete
  4. The link in the profile contact card of the bot download a file using Google Chrome instead to open a web brower page. From an end-user point of view thats weird :-)

    ReplyDelete
  5. Hi Rubén,
    Thanks for your hint, that was not intended.
    We will fix this as soon as robot profiles are enabled again.

    ReplyDelete

 
Web Statistics
Embed Wave to Blogger