New Years Resolutions 2016

It’s that time of year again!

Resolution 1: Post on the blog more regularly. A minimum of once a week.

I know that I say this every time that I come back from a break. It is just a matter of having the self-discipline to find the time to sit down and write something, even it it’s short. It’s not like I have nothing to write – I have a list of topics in the backlog. The problem is that if I miss one week, it becomes a lot easier to miss the next too, so I’m going to practice self-discipline.

Resolution 2: More Apple II Projects

I lost the space I had available to work on stuff as of the summer, so I had to put all of my Apple II gear away. But in about a month, I’m going be getting some office space at home again, so I can set it all up again! I want to continue with the disk imaging, and find some sort of interesting hardware project to do, as well as retrobrite a bunch of stuff. Maybe I can even find something that I can write up for Juiced.GS!

Resolution 3: Work on LuneOS

I did a bit of work with the LuneOS folks last year, but mostly had to leave it alone due to being busy at work. Now that I’m going to have office space at home again, I want to find some time to contribute to the project – maybe get the Photos and Videos app complete and functional.

Resolution 4: FeedSpider rewrite into pure Enyo 2

I know, another FeedSpider rewrite!? The last re-write still relies heavily on prototype.js. With model and collection support, and taking advantage of bindings, I should be able to eliminate that entirely. I’ll be able to complete my goal of releasing FeedSpider for more platforms, especially iOS.

Resolution 5: Grow the business

If I want to be able to fund all of this, I need to keep growing my business, Othello Ventures Ltd. The goal is to take on more development contracts, so that I can bring on more people and turn that into a positive feedback loop. I also have a few other projects in mind that will hopefully help, and I look forward to executing on them. 2015 was a good year for the business. I want 2016 to be a great year!

That all should be enough to keep me busy for an entire year now, shouldn’t it!

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!

Building FeedSpider from Source

Now that FeedSpider 2.x is open source, I’ve had a couple of questions about how to “build” it from source. Of course, since it’s Javascript, it’s really more of a compress and package process than a build process.

It’s fairly straightforward with just a couple of quirks depending on what platform you’re planning to build for. That being said, this guide assumes that you have at least some experience using the various developer tools. Instructions on how to setup the webOS SDK, Cordova, etc, are outside of the scope of this document.

What you need

  • The FeedSpider source. Get it from GitHub.
  • Apache Cordova. Use the latest version for FirefoxOS, or 2.5.0 for webOS.
  • Node.js. Get it from their website.
  • If packaging for webOS or LuneOS, the webOS SDK. (Note that while the files are still available from HP/Palm, the download page is no longer active).

How to Build

  1. If building for webOS, set up the SDK using the instructions here.
  2. Install Node.js. Instructions here.
  3. Install Cordova. Instructions for FirefoxOS here, webOS here. (Note that when setting up the Cordova app for FirefoxOS, you will call it FeedSpider instead of test-app.)
  4. Unzip the FeedSpider source to a directory of your choice.
  5. Open up a command line and navigate to the FeedSpider source directory.
  6. Run the command “tools\deploy.bat” (Windows) or “tools/deploy.sh” (Mac/Linux) without the quotes to build the package.
  7. After the script run completes, you will be able to find the packaged code in the “deploy” directory under the main directory. Navigate there.
  8. Remove all of the files in the Cordova application directory and copy all of the files in this directory to that directory. (Refer to the Cordova instructions for your platform for which directory the application directory is.)
  9. Copy the appinfo.json (webOS), appinfo-luneos.json (LuneOS) or the manifest.webapp (FirefoxOS) file to the Cordova application directory.
  10. If you copied the appinfo-luneos.json file, rename it to appinfo.json.
  11. Package the application using Cordova (refer to Cordova instructions for your platform) and deploy the package using your preferred method.

That should get you going! If you run into trouble, drop an email to feedspider@feedspider.net.

FeedSpider Dev Blog: …and We’re Back!

August was a busy month for me, but not so much for FeedSpider. These little side projects have a way of getting put on hold when real life takes over, but now I’m back and I’ve got some exciting development news.

When we last left FeedSpider, version 1.0.1 was in the Firefox Marketplace queue. It fixed a few bugs and notably changed URL handling so that clicked links would open properly in a new browser window instead of the same window. Since then, 1.0.1 was approved, and I’ve been (slowly) working on a few new things.

Firefox 2.x and Prototype.js

One recurring issue that I kept getting reports about was that web service calls would silently fail and the loading spinner would just keep infinitely spinning. This was only happening on FirefoxOS 2.x (I developed on 1.3, and everything worked properly there.) After some investigation (and updating my Flame to 2.2 ’cause the 2.x simulators are very crashy on my dev machine), I discovered that the new version of the Javascript engine used in FirefoxOS 2.x and Prototype.js don’t play nicely for some reason.

The problem lay in the call to initialize Prototype.js’s Ajax.Request object. When creating a new Ajax.Request object, you will pass it the URL that you want to send the request to, and a JavaScript object with the options.

Internally to Prototype.js, Ajax.Request is derived from Ajax.Base. So, when you create a new Ajax.Request object, it passes its Initialize method the $super parameter, which contains a reference to Ajax.Base’s Initialize method, which can then be called to initialize the object.

The problem is that on FirefoxOS 2.x the $super parameter is not passed. The method just receives the two parameters, url and options, instead of the 3 that it is expecting. Since it doesn’t have the correct information, and doesn’t know what else to do, it tries to call the URL parameter as the $super method, blows up and never returns, leaving the UI hanging, waiting for some sort of response.

Since the only other class that extends Ajax.Base is Ajax.PeriodicalUpdater, which I don’t use, and Ajax.Base only defines an initialize method, the simplest solution was to remove the inheritance, incorporate Ajax.Base’s initialize method into Ajax.Request’s, and ship a custom version of the library. It winds up looking like this:

initialize: function(url, options) {
  this.options = {
    method: 'post',
    asynchronous: true,
    contentType: 'application/x-www-form-urlencoded',
    encoding: 'UTF-8',
    parameters: '',
    evalJSON: true,
    evalJS: true
  };
  Object.extend(this.options, options || { });

  this.options.method = this.options.method.toLowerCase();

  if (Object.isHash(this.options.parameters))
    this.options.parameters = this.options.parameters.toObject(); 
  this.transport = Ajax.getTransport();
  this.request(url);
},

Instead of this:

initialize: function($super, url, options) {
  $super(options);
  this.transport = Ajax.getTransport();
  this.request(url);
},

It’s not the cleanest solution, but I am considering moving away from Prototype.js anyways. Enyo kinds can take the place of Prototype.js classes, and I can roll my own Ajax class if I need to.

But, that’s a project for another day. This works for the moment.

Version 2.0.0

With the Prototype.js issue fixed, I was able to build and submit version 2.0.0 to the Firefox Marketplace last Wednesday and see it approved last Friday. It includes the Prototype.js fix, as well as the integration of the Macaw SimpleLang Localization Library, a couple of typo fixes, and a behaviour change that will cause it to fall back to the system JSON parser if there isn’t a better one available. Initially, it supports English, but it’s easy to add new languages as we go.

This is a version that I’m happy to call “done” and use as a base for my cross-platform work.

The big version number bump is something that I should have done in the first place to reduce confusion. From here on in, FeedSpider 1.x will refer to the old Mojo-based webOS version, and FeedSpider 2.x will refer to the new Enyo 2-based cross-platform version.

Initial Support for webOS and LuneOS

After getting 2.0.0 to the Marketplace, I started on webOS. Just as a simple test, I set up an appinfo.json, plugged the code into palm-package, and pushed it up to the TouchPad emulator. I’m happy to report that Enyo has performed exactly as advertised. Aside from the things that I knew weren’t going to work because they were programmed specifically for FirefoxOS, everything worked properly, even a few things that I suspected would not.

Just for fun, I also pushed it up to the Pre3 emulator just to see what would happen. The text is a little small, but it works there too, so I might consider a release for webOS 2.x as well.

This means that the webOS port is already 90% to 95% done, and I just have a few OS-specific areas left that I have to port.

As far as LuneOS goes, I still need to update my TouchPad and get the latest build on there, but I’ve sent a couple of packages out into the field for others to try. I’ve had reports that things work really well, including this write-up from PivotCE as part of their article about which webOS apps work on LuneOS:

FeedSpider works amazingly well. I was able to get an early copy and I was impressed. The interface is clean and familiar from his previous work and I could log in and pull down new stories with ease. It’s on the partial list though because the back swipe didn’t take me back and some things just haven’t been coded yet. VERY promising indeed. Perhaps this will find its way into a release of LuneOS in the future. Yup, it’s that good and it’s not even done.

So, it sounds like most of the webOS work will be portable to LuneOS as well. Needless to say, I am very pleased and will certainly use Enyo for cross-platform projects in the future.

Open Source

The final bit of news that I wanted to mention is that FeedSpider 2.x is going open source. I’m releasing the code under an MIT-style license, with the only restrictions being that I reserve the rights to the name and logo. I do plan to keep developing FeedSpider though, and adding more platforms, so don’t worry! This is mostly because I’ve had a few requests to take a look at the code, and I’m hoping that the LuneOS project might be able to make use of it.

If you want to check out the source, its available on GitHub.

What’s Next?

So, what’s next from here? We’re finally moving on to webOS and LuneOS! There are a handful of things from the build last week that had FirefoxOS-specific implementations, so need to be implemented for webOS:

  1. OAuth Authentication (Feedly, AOL Reader). In FirefoxOS, these used iFrames in a way that no other browser seems to support in the same way. So, for webOS, I’m expecting to use WebViews, but we’ll see how that turns out.
  2. Notifications. While the “toast” notifications are functional right now, I should be able to get proper webOS-style notifications working as well. Additionally, for the recurring unread count check, I need to get dashboard notifications working.
  3. Sharing. It just isn’t implemented for webOS yet. But, I know how to do it.

I’ve got most of the code to handle all of this, and the app is already wired for these functionalities, so it shouldn’t be *knock on wood* too difficult to do, just a matter of porting from Mojo to Enyo 2. I’ve even got the handling working for the Back gesture already.

Also, as additional translations come online, thanks to the Mozilla Localization Project, I’ll be able to support additional languages in both webOS and FirefoxOS.

After that, I’ll take a look at porting this as a Firefox Browser app, and as a Google Chrome App, and decide where to go from there. Probably Android or Blackberry. As always, I’ll keep you updated.

In closing, here are the new screenshots:

FeedSpiderWebOS1

Packaged the app, dropped it into the emulator, and things just work!

FeedSpiderWebOS2

We can even get all the way to an article, and stuff like mark read/unread, starred/unstarred, etc work.

FeedSpiderWebOS3

Just for fun, I plugged it into the Pre3 emulator, and things look and work pretty decently there as well.

FeedSpider Dev Blog: After Action Report

FeedSpider 1.0.0 was approved and published to the Firefox Marketplace last Sunday, and I’m happy to say that I had a great experience with the process! It was simple and straightforward, and there few really nice features that the webOS App Catalog was missing.

Notably, when you upload your app package to the Firefox Marketplace, it is scanned by the automated system to let you know if there are any conditions that would cause the app to be instantly rejected. In my case, I had one critical failure on the first upload. One of the rules for privileged apps (at least) is no inline script tags. All scripts must be loaded from .js files. The Enyo bootplate uses an inline script tag in its index.html to load the debug page if the minified version of the app is not present, so I had to pull that out.

The other neat feature is that it will tell you what position your app is in the review queue and the estimated time before it is reviewed. That’s something that I would have loved to have in the webOS App Catalog.

I also had the chance to go through the Marketplace’s update process yesterday. I’ve had a few bugs reported to me and found a couple others on my own. Any application (even one as relatively simple as FeedSpider) is a complex beast; there are behaviours that you wouldn’t even think to test for until it gets into the hands of others and they find out that things don’t exactly work as expected. The core logic still seems pretty solid, as it has undergone few changes from the webOS version. But I completely rewrote the UI layer, so I’ve been expecting to find little glitches along the way. There are a couple of notable ones that I fixed in 1.0.1, mostly relating to how individual articles are handled. I also fixed the one where the main list doesn’t refresh properly after you finish reading all of the articles in a feed or category. Instead, it redraws the dynamic part of the list over the static part of the list. That just required setting the list count to 0 before refreshing it.

The big lesson in this version was on how Enyo Scrollers behave. FeedSpider 1.0.0 just resets the content of the article scroller when you switch between articles. That, however, doesn’t reset the scroll position. So, if you open an article, scroll to the bottom, and then open another article, you’ll find the scroller in the same position as the previous article. The solution to this problem seemed obvious – reset the scroller position to the top before displaying the article panel.

Not exactly.

This works when using the forward and back buttons at the bottom of the article page to switch between articles, since the article panel remains visible. However, when moving from the list of articles to an individual article, it doesn’t. I had to do a bit of digging using console.log and the scroller’s getScrollBounds call, and I learned that if the scroller is not visible on screen, getScrollBounds will return 0,0 regardless of the actual scroll position. So, the solution wound up being making sure to make the article panel visible before resetting it’s content and calling scrollToTop.

The other issue that I ran into was with link handling in the individual articles, or rather that there wasn’t any. Clicking on the article title would properly load the article in the browser, but clicking on a link in the article body would cause problems. The root cause of that is that in webOS, clicking on an external link in an application in webOS will open it in the default browser. In Firefox OS, due to the slightly different nature of how applications work, an application can load web content right in it’s window, but it has to provide the browser chrome. I missed that while planning out the app.

For FeedSpider 1.0.0, this means that clicking on a link in the article body will cause the link to load in FeedSpider’s window, with no way to get back short of closing the app entirely and re-loading it. The solution at least, is simple. If you add the target=”_blank” attribute to the link, it will properly open in a new window. The implementation, however, is a little more difficult when all you have to work with is a blob of html content.

If I were using jQuery, the solution would be simple – add a global click handler to ‘a’ tags, as demonstrated here. Then I could stop the link click and redirect it to a web activity or something else. Since Enyo doesn’t implement event handlers like that, it becomes a little more complicated. I thought about using regex to parse the blob and automatically insert the target attribute to any links, but you know what they say about regular expressions. And, apparently attempting to do that specific operation is bad practice and something that I was warned against.

The far simpler (and hopefully better) solution was to do it the Enyo way. I set up a tap event handler on the component that holds the content. If the target of the tap event has an “href” attribute, then I add the “target” attribute and let the click bubble its way up the chain, causing it to open in the default browser. What throws a wrench in the works are elements that are wrapped in <a> tags, such as images. There, the tap registers on the image, rather than the link. So, I have to check the parent element as well, and do the same procedure if the parent has an “href” attribute. My method winds up looking like this:

 catchLinkTap: function(inSender, inEvent)
 {
     if (inEvent.target.href != undefined) {
         inEvent.target.target = "_blank"
     }
 
     //Catch images. These will be wrapped in an <a> tag.
     if (inEvent.target.parentElement.href != undefined)
     {
         inEvent.target.parentElement.target = "_blank"
     }
 },

It feels a little bit clunky, because I’m using a “global” tap handler rather than an element-specific one. But, still, it works pretty well.

So, what happens next? There’s one thing that is still missing from the Enyo port, simply because I was not sure how to do it – localization. Fortunately, @_minego as been working on the same thing for Macaw and has graciously offered me the use of his library. So, that is the next major milestone for FeedSpider. Once I get localization implemented, (and maybe another round of bugfixes as the UI matures), I’ll start looking at the cross-platfom port. I still intend for webOS to be the next target – I did promise after all.

To close, congrats to @_minego for getting Macaw done and into the Marketplace! FeedSpider 1.0.1 is currently 9 of 24 in queue, and should hopefully be published within the next few days. I hope to see it out there soon!

FeedSpider Dev Blog: Finished!

Well, finished in as much as a software product can ever be finished. On Thursday morning, I delivered a 1.0 version to the Firefox Marketplace for review – a week in advance my deadline, so I’m pretty happy about that.

This last week was mostly under the hood stuff, and dealing with little things that were not huge components, but just needed to get implemented, like mark all read, logout, tap the title to scroll to the top, etc., as well as a few little bugfixes and the like that cropped up during the process.

My big projects for the week were finishing up with the list rewrite, getting event handling working, and getting recurring notifications working.

Even after last week, I wasn’t quite happy with how swiping in the article list was working. The original FeedSpider implemented a method where you could pull over on an article to mark it starred or read without needing to complete the swipe. However, this doesn’t quite work with Enyo lists. There is an event raised when a swipe is completed, but no event raised on an incomplete swipe.

Fortunately, due to the nature of Enyo inheritance, it is very easy to build a custom Kind to fix this. The first method that I tried was to raise an event when the list finishes the process of backing out of a swipe. The problem with this is that the last part of backing out of a swipe is to start an animation using Enyo.job, to hide the container. Since Enyo.job is deferred, the event fires before the animation is complete, leading to some very ugly UI issues. So, that was out.

The second method was to copy the method that handles the animation into my Kind wholesale, overriding the parent Kind, and have it raise an event when the animation is complete. This has the side effect of firing the event any time the animation completes – both on a completed swipe and an incomplete swipe. This meant that when the swipe completed successfully and swipe container stayed on screen for a couple of seconds, the event fired, causing the list to change behind the swipe container. Better, but still ugly. This was half the solution.

Based on the original behaviour, I never actually need the swipe to complete, the user just pulls to one side or the other, the icon underneath changes, and then the list item “springs” back. The List Kind defines a variable: percentageDraggedThreshold, that defines how far (in percent) the user has to drag the list before it will trigger the swipe being completed. By default, this is set to 20%. By setting it to 150%, the swipe will never complete unless the user pulls it a significant distance beyond the end of the window (impossible on a phone/tablet, and will only happen in a desktop browser if the user is really trying), solving the UI problem.

The other bit of work that I did on the article List was to get it to load more articles. A suggestion from Garfonso pointed me in the right direction. An Enyo List is based on a Enyo Scroller, so I was able to tie into the scroller’s underlying scrollEvent to detect if the scroller was in its final “screen” based on the test (inEvent.scrollBounds.top >= inEvent.scrollBounds.maxTop – inEvent.scrollBounds.clientHeight). If so, and if it there were more articles to load (and it wasn’t already loading them) it could then load more articles and refresh the list.

Event handling (for article state change and folder deleted events) was interesting. The way that the app is structured and the objects are created, the objects that trigger these events don’t always exist in the same tree as the panels that are supposed to be receiving them, so standard Enyo event handling doesn’t work. The solution that I came up with was to take advantage of the “feedspider” object – define a method in the app.js that is called and passed the event information, which then waterfalls down the appropriate event to the panels, which handle them. Not super elegant, but it works.

Alarms and Notifications were surprisingly straightforward. (Notwithstanding some sort of state condition in the simulator that had me stymied for a couple of hours. Re-installing the simulator fixed the problem) Following the direction in the Alarm API, and with a little help from Stack Overflow, I pulled together a simple wakeup alarm that would pop up a notification on a timer telling the user how many unread items they had in the feeds that they specified, just like the original FeedSpider.

With that complete, all of the major features of the app were done. It was just a matter of zipping it all up and submitting it to the Marketplace.

Reflecting back on the porting process, it was interesting. Whats nice is that I was just moving from one javascript framework to another, so there were very few changes to the core logic (the fact that I was able to continue using prototype.js helps too). Much of it was a UI re-write, as well as making some components work in a more Enyo-y manner. The biggest change was moving from the Mojo style of defining the different components as html pages and then tying Javascript into them (as in more traditional web design) to the Enyo style of *everything* being defined in Javascript and CSS (well, technically using LESS.js).

I mean that quite literally. I moved from having 29 html pages defining my scenes and html components such as dividers to having 1. And the entire content of the that page (aside from loading Javascript, css, and a little metadata in the header is:

 <body class="enyo-unselectable">
 </body>

It’s a very different style of thinking. But, at the end of the day, it’s all Javascript, its all portable, and once you get it, it all makes a lot of sense.

So what happens next? It’s been a busy couple of months, so I’m going to take a few days off while waiting for the Marketplace review to finish, then it’s time to start looking at the next platform. I promised a webOS port, so that will be next, and should be *relatively* straightforward. Then, after that, probably Blackberry, or Chrome Web Store. (I might throw in a Firefox desktop browser build while I’m at it – I’ve had requests).

In any case, watch this space and my twitter for updates.

As always, lets close out with the screenshots (well screenshot).

FFOS12 The final piece – notifications working with the app closed.

Feedspider Dev Blog: More on Enyo lists and cross-platform support

I’m working on a new progress update for the weekend, but I wanted to get this out first. After last week’s post, I got a few followup questions from Preemptive over on the webOS Nation forums. He’s part of the group that writes PivotCE, the webOS community’s foremost source of news. In the interest of spreading the info to a more diverse audience (and keeping it all organized) he gave me the okay to post it here.

The question:

Interesting read. It seems you’re having to recreate Mojo features in Enyo. I’m not sure how far Enyo is an app framework or whether it’s the whole UI on webOS 3.0.5 / Open / LuneOS. With ‘swipe to delete’, are you having to implement this just for FirefoxOS or across all platforms?

When coding an Enyo app, when you write, ‘perform action’ (e.g. Delete item), does it:
a. Do it in the UI style of the OS? (‘delete’)
b. Do it in a way you select? (‘use slide to delete’)
c. You have to code the interaction in the app? (‘here’s how slide to delete should look’)
d. O.S. specific code so the app is consistent across platforms? (a or b for webOS, c for FFOS)
e. A mix of the above?

I’m curious as to how ‘cross-platform’ Enyo is. As you are tweaking for FFOS, do you include all the code in one app or are you versioning for the platform? It’s clearly not ‘write once’, though obviously, the same framework. From tweaks, through versioning to total rewrite, How far are you having to go to make Feedspider cross-platform?

My Answer:

Glad that you liked it I’ll do my best to answer, but please forgive me if I get too technical

Enyo is one of a couple of app frameworks natively supported by webOS. To the best of my knowledge, many of the core apps are written using Enyo, but the Luna UI is not. Mojo is also supported in 3.0.5, but not in Open or LuneOS. Other frameworks are also supported (jQuery, Enyo2, etc.), but you have to package them along with your app.

Enyo lists do not support the Swipe to delete functionality in the same way as Mojo, so I have to implement this from scratch in my own way across all platforms, using the Enyo list’s swipe functionality. But, the way that I am doing it, it is a cross platform solution. The workflow goes kind of like this when a user swipes:

  1. Enable sticky swipe on list.
  2. Set up the swipe container, which consists of two buttons on a dark grey background.
  3. Display the container to the user over top of the list item that they are swiping.
  4. If the user hits the “Cancel” button, hide the swipe container.
  5. If the user hits the “Delete” button, hide the swipe container, remove the item from the array that defines the data for the list, update the number of items in the list, and refresh the list.
  6. The list is redrawn sans the deleted item.

All of the visual stuff is handled by the list. I just have to define what the swipe container looks like and exactly what the buttons do. (As well as making sure that the container stays visible when you swipe it across).

To answer your other question, Enyo has excellent cross-platform support so it’s mostly just tweaks. 98%+ of the code that I write is the same across all platforms. I develop against Safari on the Mac and test against Firefox OS on the simulator and phone. So, that covers both WebKit and Gecko based browsers, which should be most of what I’m running into on the platforms that I plan to support. To help with this, Enyo exposes the enyo.platforms api, so that you know exactly what you’re running on and can deal with platform and version specific tweaks.

So far, the only Firefox OS-specific UI tweak that I’ve had to do has been the one to deal with lists and floating that I mentioned. The other times that I’m writing OS-specific code have to do with OS-specific ways of doing things. So far, I’ve only run into that in 4 other places:

  1. OAuth. Since I have to handle the authentication in a separate browser window (of one form or another), this varies a bit across platforms. For Firefox OS, I was able to write a custom Enyo Kind. For webOS, I expect to be able to use the WebView kind from webOS-Ports’ webos-lib in much the same way. For the rest of the platforms, I should be able to use a Cordova in-app browser.
  2. Cross-app launching. To handle the launching of URLs and sharing to other applications, the mechanisms are different across platforms. For example, webOS uses the com.palm.applicationManager service, and Firefox OS uses web activities. It just means that I have a kind that handles the launches based on platform, with the majority of the code being the same, except for the actual launch.
  3. Device orientation. Slightly different calls are used here. (PalmSystem.setWindowOrientation vs screen.mozLockOrientation(“portrait”) and screen.mozUnlockOrientation())
  4. Scheduled app relaunches. In order to re-launch the app to check for updated feeds, I can use the com.palm.power/timeout service on webOS to set a recurring timer for the app to launch. On Firefox OS, I can use the Alarm API to re-launch the app. Unfortunately, I need to reset the alarm each time. You can’t set a recurring one yet. I haven’t looked into it on other platforms yet though. (Note: After writing this, I dug deeper into the details since I actually had to implement the feature, and it turns out that com.palm.power/timeout doesn’t support recurring alarms either.)

That wound up being longer than I expected! Hope that clarifies a few things

Preemptive’s response:

So Luna handles cards, just type, launcher, etc. What’s in the card is via a framework (or native). You need to recreate some familiar webOS stuff in Enyo 2, but only a few tweaks are needed for particular platforms.

Thanks. Very informative & some of your work may be useful to others wanting to make webOS style apps.

My close:

In a nutshell, yes. Also, AFAIK Luna uses HTML + Javascript in some capacity to do the UI, but I have not been involved on that side at all, so I can’t give you an authoritative answer. You’d have to ask someone much more qualified than me

Fortunately, someone more qualified did chime inHerrie, one of the top webOS homebrew developers, and one of the people working on the Open webOS port.

We actually use QML but it’s syntax is mainly consisting of Javascript. Coding style wise it looks VERY similar to Enyo!

If you have any questions about working with Enyo, Firefox or webOS, please let me know, and I’ll answer them to the best of my ability. Hope someone finds this useful!

FeedSpider Dev Blog: Almost there! Working with Enyo Lists

So close, I can almost taste it! I can count the list of things left to do on one hand 😀

This week has been all about lists and getting them to display data in the way that I want. I spent the week rewriting the main, folder, and feed screens to use lists instead of popping controls into an Enyo scroller. As with any sort of UI design, it was fiddly, but I came away with something that I’m pretty happy with.

So, how’s last week’s todo list looking?

  • A proper list for feeds and folders with refreshing and delete buttons (Done!)
  • A proper list for articles with swipe to star and mark read/unread (Done!)
  • Recurring notifications (Still on the list)
  • Various bug-fixes and cleanups (off the top of my head: mark all articles in a feed as read (the button is there, just need to wire in the event), proper handling of orientation lock, mark read as you scroll (not doing in this version. I can’t implement it with an existing enyo list, but I might be able to with a custom class.), auto close feeds/folders when all items are read. – all minor things).

Enyo’s lists are pretty good, but, as with anything, there are a few quirks to work around. Honestly, for my purposes, I think that Mojo handled lists better. Enyo’s lists are missing an easy implementation of dividers. (You have to manually show or hide the header for each item, rather than simply being able to provide a function), as well as missing swipe to delete. Additionally, Enyo lists are missing an item rendered event, as well as a swipe canceled one.

Swipe to delete, at least, was something that I could cobble together on my own. There were a few quirks that I had to work around here. First, a normal swipe will cause the swiped item to display for a second, and then disappear. I needed buttons that would stick around so that the user could press them. Fortunately, Enyo lists support a sticky item property. Unfortunately, it isn’t honoured properly, being reset each time, so it has to be set each time the swipe container is activated.

This leads to another quirk – no event is triggered when a sticky swipe item is activated. In fact, an ontap event is triggered, sending the user to the article. So, I had to set up my own “swiping” property to catch the event and cancel it if the sticky swipe item was open. I also had to manually call the list’s internal completeSwipe method as there is no documented way in the API to force a swipe to complete. But, after all that was done, I had a working swipe to delete method.

It’s also frustrating that there is no swipe canceled event. This means that in order to toggle an item’s read or starred property, you have to do a complete swipe, instead of just being able to expose the icon and then cancel the swipe. I played around with a custom class for this, extending the list kind, with a custom event, but the swipeCanceled event would always fire too early, not waiting for the animation to complete. This would have the effect of triggering a tap on the item and causing the article to load. Although, I do have an idea that I will look at implementing next week if time allows.

The last quirk that I had to deal with was the lack of an “item rendered” event. This means that I can’t look for a particular list item to trigger loading more articles. I’ll have to manually do it with a button. But, that’s a problem for next week.

There were two other bits of weirdness regarding sizing that I ran into that were notable enough to remember. The first has to do with how the width of a list item is calculated (at least in FirefoxOS). Since lists use a Flyweight Repeater pattern, you can’t use fittables (rows or columns) in list items. This makes it a little challenging to have a list item that stretches across the window. In other browsers, you can just set float:right on the column that you want on the far side of the list. But, in FirefoxOS, this causes the element to move down to the next line, as well as to float on the right side of the page. Needless to say, that doesn’t work very well. Since my sticky items at the top of my list have statically set widths, ultimately, I had to use this ugly hack:

if (enyo.platform.firefoxOS)
{
  var width = this.$.stickySources.controls[0].controls[0].controls[1].domStyles.width;
  var remainder = window.innerWidth - parseInt(width) - 70; //This is calculated by taking window width less width of the all items title column, less 30px for the icon and 40px for the margins.
  this.$.sourceName.setStyle("width:" + width + "; font-weight: bold");
  this.$.sourceUnreadCount.setStyle("width:" + remainder + "px; text-align: right; font-weight: bold");
}

But, everything now lines up nicely.

The second bit of weirdness involves the list length. When the main window is initially rendered, if the list extends off the end because some titles are more than one line, you can’t get to the last few items. The list will just bounce back. However, if you navigate to another screen and back, the window will re-render properly. The ugly hack that I did to make things work properly was to raise a window resized event to force a redraw. Now, from the user’s perspective, everything renders right the first time.

On the flip side, once it’s working it works great. Also, the re-orderable implementation is very simple, and I got that working without too many problems, and no notable quirks to speak of. All in all, I would definitely use lists again rather than trying to construct my own.

So, what’s still left to do?

  • Recurring notifications
  • Loading more items in a feed (I have some sample code for list paging, just need to implement it.)
  • Event handling. (There are still a few Mojo events left over that need to be converted to Enyo events. ie. mark all articles in a feed as read).
  • Minor bug fixes and cleanups. (off the top of my head: auto close feeds/folders when all items are read and logout. – all minor things)

Beta and a submission to the app store are just around the corner. But, I’ve only got about 2 weeks left, so I need to hurry. Fortunately, I think that I just need a couple more days… (knock on wood).

As always, lets close with the week’s screenshots:

FFOS9

The main view list of feeds with working delete and cancel buttons.

FFOS10

Articles properly split with date headers. Webkit outputs a date in the form of July 18, 2014. Gecko outputs 07/18/2014.

FFOS11

If you swipe right to left, it will toggle the article’s starred state. If you swipe left to right it will toggle the article’s read state.

FeedSpider Dev Blog: Approaching the Finish Line

We’re closing in on the home stretch! The past week has seen me with a bit more time for development, and I’ve made a good dent in the tasks list. Let’s take a look at the one from last week and see how we’re doing:

  • The add subscriptions page (Done!)
  • A proper list for feeds and folders with refreshing and delete buttons (In progress)
  • A proper list for articles with swipe to star and mark read/unread (Next on deck)
  • OAuth (although it looks like Firefox OS will support this nicely – it’s just not a cross-platform solution) (Done, and source code posted)
  • Notifications (toast-style) (Done, source code also posted)
  • Various bug-fixes and cleanups (such as figuring out why the sharing menu won’t refresh properly) (Always in progress)

And there’s one to add that I forgot about last week: The recurring notification system that will alert you of unread feeds when the app is closed. The plumbing is there for this within the app, but I need to wire it into the OS. It looks like I’ll be able to use the Alarm API and the Notification API to make this work.

So, here’s the recap:

OAuth (my old nemesis). Fortunately, this was easier on Firefox OS than I expected. I was originally expecting to use a Cordova InAppBrowser, but, in Firefox OS, those don’t offer all of the features that I need. Namely, one can’t hook any of the event handlers. Fortunately, Firefox OS offers a better native solution using iframes and the Browser API, which I was clued into thanks to Peter Rukavina’s article. And, since I’m using Enyo, I can wrap the iframe in a Kind to set up the specific parameters that it needs to function properly on Firefox OS, and catch the nonstandard mozbrowserlocationchange event that it throws.

The only real weirdness that I ran into is that due to the way that Firefox OS browser sessions handle credentials, simply calling purgeHistory() on the iframe will not clear logged on sessions to Google, Twitter, Facebook, etc. I was unable to find a way to do this inside the Browser API (bug?).
So I needed to clear the logged on session manually. I handle this by navigating to the supported provider’s logout page after the OAuth session is complete and the iframe has (hopefully) been made invisible. We don’t need the logged in session after we’ve received the OAuth code anyways. And, if we don’t log out, there is no way to log in using a different account of the same type.
I thought that this would be a useful kind for the Enyo and Firefox OS developer communities, so I open-sourced it here.
Toast Notifications. The one type of notification missing from the Notification API is a toast notification. You know, the type that pops up from the bottom and stays there a few seconds to let you know that something has happened. It’s odd, because I know that this is in the OS. When an app is installed, this is exactly what happens. It must just not be publicly accessible.
Fortunately, there is an Enyo implementation of notifications by MacFJA. He doesn’t include toast notifications either, but he does provide a flexible, extendable framework, so I rolled my own, mimicking the Firefox OS style. I got a couple of requests for the theme, so I have made it available here.
The only weirdness that I ran into with this one is that it does not like being having the notification object inside a panel. So I had to add another layer and wrap my panels and the notification object inside a new Kind. Fortunately, with Enyo, this works very nicely. It’s turtles all the way down.
The add subscriptions page. Not much to tell here. It’s a bit different than the old FeedSpider, but its simpler. I think that it will actually work a bit better. Pictures will be below.
Converting things to use lists. When I first started this project, I was afraid that I would have to roll my own list type to handle the headers and dividers that I needed. This, I knew would be quite complex, so I’ve been putting it off. The “lists” that I’ve been showing in the screenshots are very fragile and don’t properly survive a refresh.
Now, I’ve gotten to the point in the project where I can’t put it off any longer, and have to actually deal with it. Fortunately, I’ve had a pleasant surprise. New to Enyo 2.4 (I’m pretty sure) is the AroundList, which will let you do headers and dividers like I need, as well as supporting swiping and re-ordering. This means that all the functionality that I need is available natively and I don’t have to stress about doing a custom kind anymore. I’ve done some initial work on implementing these lists, and this looks to be my project for the beginning of next week.
I’m hoping to have the app in a beta-able form by next Friday, and have it submitted to the Marketplace by the end of the following week (well inside my deadline). Then, I can start work on the versions for other platforms, including making sure that the app runs nicely on a Firefox OS tablet.
So, what’s left to do?
  • A proper list for feeds and folders with refreshing and delete buttons
  • A proper list for articles with swipe to star and mark read/unread
  • Recurring notifications
  • Various bug-fixes and cleanups (off the top of my head: mark all articles in a feed as read, proper handling of orientation lock, mark read as you scroll, auto close feeds/folders when all items are read. – all minor things).

And now, to close the post, the screenshots:

FFOS5

The completed OAuth screen, with border and back button. The OAuth Kind doesn’t provide any browser chrome, just the iframe. You can plug it in anywhere you want.

FFOS6

Functioning toaster notifications!

FFOS7

The completed add subscription screen.

FFOS8

The main page re-implemented using an Enyo.AroundList. (This works in Firefox OS too, but I use Safari for my UI testing because it is much quicker to iterate).

Feedspider Dev Blog: Firefox OS Ho!

Last week, I was fairly busy due to other commitments and did not have much time to work on FeedSpider, but last Wednesday, I got a bit of exciting news – I had been accepted to the Firefox OS Apps on a Flame program!

In exchange for me committing to have an app ported and in the Firefox Marketplace within 30 days of receiving the device, they sent me a Flame developer phone to do hardware testing on. So, with that time limit in place, that moves Firefox OS up to be the priority development target! Fortunately, Enyo (with a little bit of Cordova to fill in the gaps) and Firefox OS play very nicely together, so I have had a productive week.

Since the Firefox OS UI is HTML5 based, I have only had to make minor tweaks to FeedSpider’s core (so far) to make it work. The big thing is that it doesn’t like cross-domain Ajax calls using JSON (instead of JSONP). Unfortunately, that is 99% of what FeedSpider does.

That being said, it’s not impossible. You just need to know the magic words, and ask for the right permissions for your app. In my case, the app needs to be privileged, and ask for the systemXHR permission, as described here.

The tricky part is that you also need to pass the parameter {mozSystem: true} to the XMLHTTPRequest when you create it. In Enyo, that is a little challenging, as you would typically call enyo,Ajax, which doesn’t appear to pass the parameters all the way down to XMLHTTPRequest. For another app that I was working on, I wound up having to call XMLHTTPRequest directly, rather than using enyo.Ajax. For FeedSpider, however, since I am using the prototype.js library to handle my AJAX calls, I just had to change prototype.js’s call to include the {mozSystem: true} parameter, and then everything worked. Now, I just have a couple of places to update where I have implemented my own XMLHTTPRequest handlers to work around webOS not handling puts and deletes properly.

The other bit is that it doesn’t allow you to use exec statements, so I had to toss out the JSON parser that I added in to parse articles after some characters were causing the default webOS parser to choke. On Firefox OS, this is an even simpler fix. The XMLHTTPRequest response object returns a pre-parsed responseJSON object, so I don’t even need to add the overhead of parsing the JSON. (Gecko FTW!)

As of right now, I only have a handful of things to still get working properly before the app is ready:

  • The add subscriptions page
  • A proper list for feeds and folders with refreshing and delete buttons
  • A proper list for articles with swipe to star and mark read/unread
  • OAuth (although it looks like Firefox OS will support this nicely – it’s just not a cross-platform solution)
  • Notifications (toast-style)
  • Various bug-fixes and cleanups (such as figuring out why the sharing menu won’t refresh properly)

Parts of this are a bit of a tall order, but I think that I can do it. And the Flame arrived yesterday, so the clock is ticking.

FFOS1

First boot on the emulator. At this point, the list of feeds and folders are loading correctly, but the articles aren’t due to the problematic JSON parser being blocked by the system.

FFOS2

A few small tweaks later, and we can load articles.

FFOS3

A bit of work on the sharing menu, and we can now share links via Email and Twitter using the Mozilla Web Activities API.

FFOS4

I got a box yesterday! The Flame looks and feels very nice, and I look forward to working with it. (I might even write a review later).

FFOS5

And this morning when I got back into the office, I tried it out. FeedSpider running on Firefox OS on real hardware. It looks great!