FeedSpider Dev Blog: Beware of things that look “easy”

As of Wednesday, I pulled together a fully functioning version of FeedSpider for webOS, which has been submitted to the HP App Catalog and is currently in queue. As of Friday, I built a new version for LuneOS. Getting there was… interesting.

As of my last post, there were 3 (well, really 4) things that needed to be ported over to webOS: OAuth, Sharing, Banner Notifications and Unread (Dashboard) Notifications. Thanks to WebOS Ports’ excellent webos-lib for Enyo 2, much of the access to the system functionality that I needed was made available to me, making the porting job a whole lot easier

OAuth

OAuth wound up being really straightforward. I was able to leverage my previous experience implementing this in Mojo and on Firefox OS to get it working fairly quickly. Thanks to webos-lib’s WebView kind, which implements Enyo 1 WebViews in Enyo 2, I was able to do something very similar to the FirefoxOS iFrame approach.

Of course, there was a webOS twist. As in FeedSpider 1.x, I have the browser redirect to a “local” url (urn:ietf:wg:oauth:2.0:oob) when it gets the authorization code from the service. This causes the Browser to throw an Invalid MIME type error instead of the typical TitleChanged event. I catch the error, and if it the URL contains a code, grab it and go on to get the OAuth token and finish the authentication.

To make this work like it did in the Mojo app, however, I had to make one tweak to the library. On an error, the library returns an object with a message property that is made up of like so: “message: localizedMessage + “: ” + failingURL”. The URL is not sent separately. So, I just added a URL property and returned the failingURL on it’s own, so that I could work with it. That is the beauty of working with open source libraries, you can tweak them to work however you need!

There were two problems that I ran into on this one. First, there is no real way to control the height of the WebView, so I had to hard-code a height into the library. That is something that I may re-visit later if there is good reason to. Secondly, due to a change in webOS 3.0.4, an application can no longer clear it’s own browser cookies. Only the browser application itself can do that. That means that I had to take the same approach as I did on Firefox OS and log the user out of their OAuth Provider’s account in the background after I got the authorization code. A bit of a clunky solution, but otherwise the user would not be able to log in using a different account for any of the OAuth providers.

Sharing

This was actually something that I had partially implemented before getting accepted to the Apps on a Flame program, so it was just a matter of finishing it up. I just had to build a customization dialog using an Enyo list (now that I’ve learned how they work, I love them!), so that the user could choose which services they wanted visible, and implement cross-app launching webos-lib’s enyo.ServiceRequest (which allows me to call into Palm services) – all pretty straightforward.

One of the interesting bits here was getting Instapaper working. Since it uses a direct web service call, rather than just a cross-app launch, I had to work up a dialog to collect its credentials and put in a preferences item to clear the credentials if they were present. However, the way that this is implemented, I should be able to port it over to Firefox OS and other platforms without too much trouble.

I also had to figure out how to handle non-installed apps. The call to open the non-installed application will return a failure message that has a well-defined structure, making it easy to parse out the package ID. With that in hand, I can launch the app catalog. However, since the error message just returns the package ID, I had to build a lookup table for the friendly name, so that I can present it to the user.

Fortunately, launching the app catalog via ServiceRequest is pretty easy. You just have to make a call to open “palm://com.palm.applicationManager” with a target of “http://developer.palm.com/appredirect/?packageid=” + packageID. (ie. com.otheloventures.feedspider2). Also, since Enyo 2 does not offer a yes/no choice dialog, I had to build one, but I think that it turned out pretty nicely.

The problem that I ran into here had to do with the way that things are rendered on screen. When the virtual keyboard comes up for the Instapaper login dialog, the Onyx Toolbar at the bottom of the screen disappears, so I have to call this.resized() on the article panel when the dialog is closed to force the screen to redraw and the toolbar to re-appear.

Banner Notifications

One part of the notification system, the easy part. webos-lib implements an “addBannerMessage” call, which allows you to pop up a banner notification. Adding this was as simple as extending my notification method to support this call.

Unread (Dashboard) Notifications

The other part of the notification system, and something that I expected to be one of the easier parts of the port. This, however, was not the case – I had to do some refactoring.

To trigger the app relaunch, it was just a matter of using ServiceRequest to call the palm://com.palm.power/timeout service and schedule an app relaunch using the palm://com.palm.applicationManager service with the “update” parameter.

In order to support application relaunching and dashboard notifications for unread articles, I needed to change the app to launch headless, using a noWindow: true directive in the appinfo.json file. There is very little documentation on how to handle noWindow and dashboard notifications using Enyo 2. But, fortunately, there was enough material for me to crib something together from the available information. [1] [2] [3]

In order to support this without breaking the other platforms, I wound up splitting my application into two different index pages, one for webOS, and one for everything else, building my own dashboard notification class, and an associated webos-dashboard.html file for it.

When launched on webOS, the application will launch our window manager. Then, based based on whether the app is in update mode or not, it will either try to get an unread count and pop up a dashboard notification, or open the main window by launching a new card with the main index.html page.

 

Fortunately, thanks to the way that Enyo works, it was relatively easy to shim this functionality in with only minor changes to the rest of the application, since the webOS-specific stuff launches the cross-platform stuff. And since it is packaged separately for each platform, I can have different entry points for each platform, maintaining cross-platform compatibility.

Speaking of cross-platform compatibility, if you take a look at the file structure, you will notice that the launching code for each page is split off into it’s own javascript file, rather than just being put in a <script> block in the html file. Even if it is something as simple as:

enyo.ready(function () {
 var launcher = new FeedSpider2.webOSWindowManager();
 launcher.launch();
});

The reason for this is that Firefox OS does not allow inline scripts in it’s html files. Everything has to be in separate .js files. It’s a simple thing to do, but one of those gotchas that you have to watch out for.

LuneOS

LuneOS is not quite webOS. At least not yet. But, as a work in progress, it’s pretty close, and FeedSpider runs on it.

Fortunately, Enyo does not detect LuneOS as webOS, so it is easy to make a check for “!enyo.platform.webos && window.PalmSystem” and implement LuneOS-specific features that will not affect webOS.Almost everything works the same way that it does in webOS, with a few exceptions:

  1. WebViews are not currently supported, so OAuth doesn’t work. I understand that the plan is to implement a solution using iFrames, similar to to the way that Firefox OS works. So, once that functionality is available, I can implement it for LuneOS. In the meantime, Feedly and AOL Reader support have been disabled.
  2. The dashboard is not implemented in LuneOS yet, so webOS-style banner notifications don’t work. Instead, the application falls back to Firefox OS-style toast notifications.
  3. The apps available for sharing have been tweaked slightly. Significantly, the webOS browser has been replaced with the LuneOS browser. Additionally, if an app is not installed, there is no app catalog, so FeedSpider cannot offer to install it for you.
  4. In addition to no dashboard support, LuneOS does not support the noWindow: true directive, (except for the email application), so at this point, I have disabled the unread count notifications.

As a result of issue #4, I’ve had to separate off the LuneOS build from the webOS build. It removes the noWindow: true directive and uses index.html as an entry point instead of index-webos.html, so you need to make sure to use the LuneOS-specific package, otherwise it will not run at all.

Get it

One last note. I’ve decided to cut official webOS 2.x support from this version of FeedSpider, as WebViews do not currently work on webOS 2.x. Also, scaling is not implemented, so all of the text and UI elements are very small. So, I recommend that people use FeedSpider 1.x for webOS 2.x devices. That being said, if you really want to sideload it, you can do so at your own risk – almost all of the features should work.

Hopefully, FeedSpider is accepted to the App Catalog soon, and I would love if you were to purchase it from there and support a small app developer. But in the mean time, you can always get the webOS, LuneOS and FirefoxOS packages for free from feedspider.net. Or, if you’re feeling brave, you can always build it from source.

What’s next

From here, I plan to start bringing in the localized strings that have been generated by the translation project, and add support for Instapaper to the Firefox OS build. Then to start on the Firefox Desktop and Chrome Desktop versions. As always, features will be added to the webOS, LuneOS and Firefox OS builds as I complete them.

In the near future, I also plan to put this project on the back burner a little, and work with the WebOS Ports team on LuneOS, specifically on Preware – Enyo 2 has become my area of expertise after all. I’m also planing to work with the PivotCE folks on a series of articles about setting up a webOS device in 2014. I’ve got some busy times ahead of me, but it should be fun!

As always, lets close with the screenshots:

FeedSpiderWebOS4

OAuth working on the webOS 3.0.4 emulator

FeedSpiderWebOS6

The sharing dialog in testing. Enyo lists will overflow their containers if they are not given an explicit height.

FeedSpiderWebOS5

Here’s what the sharing dialog is supposed to look like.

FeedSpiderWebOS7

Working dashboard notifications on webOS!