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!