Mon 12 May 2008
I realized a few months ago that, unlike pretty much everyone else I know, I don’t regularly use an RSS reader. Not that I haven’t tried—I used FeedDemon early on, and more recently tried out Google Reader—but never managed to form the habit of checking them regularly. Both of them are fine apps; the problem was with me. Every time I sat down and saw that I had a gazillion unread items in my hundreds of feeds, I didn’t know where to start. Eventually I just gave up trying to keep up.
Around the same time I came to this realization, Adobe AIR 1.0 was publicly released. I wanted to try to write an AIR app just for fun, and it occurred to me that I might be able to make something that would solve my RSS problem.
The result is Snackr, a ticker-like widget that lives on the bottom (or side) of your screen and scrolls random items from your RSS feeds. (It’s called “Snackr” because it lets you nibble on your feeds. Guffaw.) Here’s what it looks like on my desktop:
I’m actually finding Snackr really useful—it helps me keep up with blogs I want to keep up with, and also gives me a great smattering of items from sources I wouldn’t normally read regularly. Please try it out and let me know if you like it! (Of course, it’s still an alpha, so please expect bugs; there’s a list of known issues on the Snackr website.)
Snackr has also been really fun to write, and along the way I figured out some tips and tricks for doing various things with Flex and AIR. Some notes on that after the jump.
Snackr is written in Flex 3 (and, of course, AIR). I hadn’t done any AIR development when I started writing it, and it’s a testament to how well AIR is designed that I got the basic thing up and running in a weekend. Of course, most of that was due to my familiarity with Flex, but the fact that AIR makes it trivially easy to package up a normal Flex app as a desktop app is easy to take for granted. With almost no work, I went from being a Flex developer to a cross-platform desktop app developer.
Once I got the basic ticker UI up and running, I started exercising more AIR-specific functionality. Initially, I kept all the feed items in memory, but decided to try out AIR’s local database capability to improve Snackr’s memory footprint. Like a lot of other things in AIR, it was dead easy to set this up; I’m not a database/SQL guru, but it was very straightforward to build out the database code. (I used synchronous mode for simplicity; it would have been much more complex had I tried to do it in asynchronous mode—as with all other Flash/Flex/AJAX programming, asynchronicity is one of the toughest things to manage cleanly, especially if you have a chain of things you want to happen in sequence.)
The next thing I did was build the animation for the popup windows. I ran into a couple of little snags here. I started by trying to just animate the Flex Window component using standard Flex effects, but that didn’t seem to work, probably because setting (say) the x and y of the window component doesn’t actually set the position of the underlying AIR NativeWindow. So, to get it to work correctly, I directly animated the “bounds” property of the underlying AIR NativeWindow class. In order to keep both the position and size of the bounds in sync as I animated, I wrote my own AnimateBounds effect—this was easy to achieve by subclassing TweenEffect and just converting the bounds property of NativeWindow to an array of numbers as TweenEffect expects.
I also had to be careful when drawing the “bubble” background in my popup window’s updateDisplayList() function. Before I added the animation, the background drew fine, but I found that during the animation it didn’t seem to redraw at the right size at each step. I discovered that I had to ignore the standard unscaledWidth/unscaledHeight being passed into updateDisplayList(), and (once again) just look directly at the AIR NativeWindow bounds to get the width and height to use. I’m guessing that during fast animations, the bounds of the Flex Window component don’t update synchronously with the NativeWindow bounds.
Around the time I was finishing up the animation stuff, we released the alpha version of AIR for Linux. Just for grins, I installed Ubuntu in VMWare on my Mac and tried it out—and amazingly enough, it worked! Well, with one snag. As Linux folks know, window transparency is something that’s only recently been supported in Linux, and not all window managers have it. I couldn’t figure out how to get a transparency-supporting window manager set up, so I just punted; the popups look okay without it (though they look like rectangles rather than bubbles).
There was a bigger issue, though. I noticed that unlike on Mac OS X and Windows XP, the popup animation was really jittery on Linux. Later on, when I tried Snackr out on Windows Vista, I noticed some jitter there too (although it’s not nearly as bad as on Linux). I haven’t yet figured out exactly what causes this—I filed a bug with the AIR team—but I’m guessing that on Vista and Linux, even when I set both the position and size of the popup at the same time, the OS either (1) processes them separately, so they get out of sync, or (2) processes the move immediately by directly blitting the window at its current size before I get a chance to redraw it on the resize event. (This mostly comes into play because I’m actually animating the popups upwards, so both the position and size have to change at the same time. It wouldn’t be an issue if you’re just growing a window larger or smaller but keeping it at the same position.)
The final issue, and probably the biggest one, is that there’s no way currently to have Snackr act like a true docking window—it can’t tell the OS to reduce the available space of the desktop, so if you maximize a window, the window will overlap Snackr. There isn’t currently an API for this in AIR, so there’s no real way to work around this for now. To compensate, I’ve added a bunch of convenient ways to get Snackr out of your way; you can toss it around the screen to different sides, put it on a second monitor, or collapse it temporarily.
Other than that, all the functionality I’ve put in Snackr has been really easy to implement. AIR makes it really simple to support multiple monitors, for example. And it’s also pretty easy to implement auto-update—you have to set up whatever logic you want to figure out when a new version is available (e.g. by downloading an XML file from a website), but once you retrieve a newer installer it’s a single function call to run the updater to install it.
I’m planning to put up the source somewhere eventually, but I want to clean it up a bit first (yes, my coding habits are sloppier at home than at work). I definitely plan to continue to add features to it—since I’m using it myself, I have a lot of incentive to keep it up. Also, my colleague Rob Adams (who was the first person to use Snackr besides myself, and has given me lots of great feedback) is planning to add some features to it as well—notably, making it synchronize the feed list and read items with Google Reader, so you can use it as an adjunct to your normal blog reading habits instead of a replacement. (Please feel free to bug him if you want this feature.)
Enjoy Snackr—I’d love to get your feedback!