So, I have a new release of Shelf, having finally been inspired to put a bit of effort into the scary refactorings I was putting off. It's internally much better than the last one, though I still have places I can take it. Feature-wise, it's only a little better, though. Feeds look nicer. It should be fast, and caches the contents of remote feeds better, so it'll thrash the network less.
The big thing is the Google Social Graph integration. Disabled by default, because it's a privacy nightmare, I can ask Google who the current page in our web browser belongs to, to found out a person to display in Shelf. Once I've got a person, I can also ask Google what other URLs they advertise about themselves, so you no longer have to stuff dozens of URLs into your Address Book cards just to see interesting things about people. Looking at Brad's homepage is a good torture test..
I'm alwo working towards making Simon happier, with a couple of preferences determining how the window should be displayed. It's not all the way there yet, but I'm moving..
Get the full release notes here.
A side-effect of all this Google Social lunacy is that I'm seeing a lot of URLs for people that I wouldn't normally have put in their Address Book entries. For instance, Simon Wistow's Vox page links to his gestalt page which in turn links to his use.perl page, so I see all of these URLs in Shelf. It fetches the pages, and discovers that there's a single RSS feed advertised on the use.perl page - http://use.perl.org/index.rss. But this RSS feed is nothing to do with Simon's page - it's the main use.perl article feed. Shelf doesn't know this, of course, so Simon's display in my Shelf window contains all recent use.perl articles.
The HTML spec seems to imply to me that rel="alternate" links are for linking to the same content, but represented in a different way, not some completely unrelated content that happens to be hosted on the same domain. This is very annoying.
I'm picking on use.perl unreasonably here, of course. Lots of people do it. use.perl is just the first one I noticed. Followed by search.cpan.org (author modules pages have an RSS feed of the master module upload list). But there are others.
The current trunk version of Shelf uses the Google Social Graph API to figure out who owns the web page you’re looking at. If it can’t find a person in the local address book who owns the URL, Shelf can now ask Google if there are any other pages on the internet that link to that page with a rel=”me” relation, and look for those pages in the local address book. So for instance, if I visit my linkedin profile page, Shelf will display context about me, as linkedin links to http://jerakeen.org/. Likewise, any page that I link to from jerakeen.org will be considered mine as well. This elevates Shelf's context-finding ability to practically magical levels in some cases.
Alas, there are disadvantages. Most superficially, the context-deriving part of Shelf was never designed to make long-running network queries, and so lives in the GUI code. Calling the Google API blocks the GUI thread. This sucks. Fixable, of course, but it makes the current development version somewhat choppy.
More serious is that Shelf now sends the URL of every web page I visit, and the homepages of everyone who’s twitters I read, and the base URLs of every RSS feed I read, to Google. I want to look for context in the email signatures of people that send me mail too, so soon it’ll be sending the homepages of everyone who mails me as well. Some people would consider this creepy. Actually most people would consider it creepy. And I don’t blame them. I don’t really have a solution for this one either, other than a big clearly-labeled option to turn it on.
On the API
For this sort of use the Social Graph API is great. Although all this information is available through just fetching the source of the current page and looking for links myself, there’s no way I’d want Shelf as a local GUI app to be doing that sort of thing. Google aren’t exposing anything I couldn’t have found out myself, but they’re doing it in a simple and fast manner, and using the API is trivially easy. No API keys, dealing with XML, registering my app or anything. I love that they just went with JSON as the format, and hang everything else.
Where's the next release?
On a related note, Shelf development has been a little slow recently. Partially I've been distracted by shipping important features for Dopplr, but mostly it's because I've hit a sort of psychic barrier of progression. Shelf needs a decent caching layer. And a threaded context discovery layer. And a much better event-driven model for display stuff, so it makes a more controlled number of network requests to fetch RSS feeds. Basically, now I've explored the problem, I want to rewrite the whole thing to take advantage of my understanding. And that's boring. So I'm not doing anything. I'll get over it.
So, here's a trivial implementation. It's hard-coded to look at my links and friends, but that's not hard to fix, I just don't care. The thing I'm happiest with is the way it's entirely client-side, and pulls in things from the delicious JSON api as it needs them. And it's pretty small, too..
Files associated with this page:
This really doesn't deserve a blog entry. I try to keep them 'serious'. But what the hell.
I see many complaints by Macbook Pro owners about the Macbook Air, and how it's not right for them. But when I was choosing a laptop, I was choosing between a Macbook Pro and something that was smaller, lighter, and not as powerful, but that was still a full-featured computer - the Macbook. And I chose the Pro.
The choice between the Pro and the Air is the same choice, except that it's slightly harder, becuase the Air is even lighter. But I'd still choose the Pro. It's not aimed at people who have already chosen the big heavy laptop over the lighter one.
To preserve state, normal usage is to use the URL fragment to add bookmarkability and history. And sometimes, this actually works. But given that the point is to pretend to be a native iPhone application, it's wrong. You should be storing state in cookies.
Justification: Native iPhone apps act like you never quit them. Even if they get closed by the system at some point, they'll come back to the state you left them in. Bookmarking a rich web application should act the same - I want to bookmark the application, and have it open in the state that I left it, not the state that I bookmarked it in. So you should update the 'current state' in a local cookie every time to navigate somewhere, and respect that state when you next visit the application. Combine this with the 1.1.3 firmware's webclips thing and you can almost pretend to be native.
Which is why I expect the much-anticipated iPhone SDK to be nothing more than 'local web applications'. Give developers a little bit of local storage (you know, like webkit just got), a way of promoting a bookmark to the home screen (we have that one now) and a way of storing some HTML and JS on the phone, and Jobs can claim he's given us an SDK. And he'll be right.
Me? I'd be happy with that. It solves all the sandboxing, security, 'bring down the network', etc problems. And it will keep people from jailbreaking the phone trivially. The only alternative I can see is installation of signed apps only, with the iTunes Media Store as the single point of installation. Which would suck more. But there will be howls of outrage.
Well, as of next month, Facebook developers can no longer put things in a feed unless it's going in as a direct result of an action that the owner of that feed performed on a facebook page.
Now, this is clearly spun as trying to prevent 'you've been given a beer' / 'you've been bitten by a zombie', etc messages. Not letting apps belonging to another person put entries into my feed is a good thing. But the documentation page says
Note that you should not be using a session_key for a user who is not actively using your application when calling this method.
Now, I read this as, you now can't use a background process to put entries into a user's feed using a session_id. You can only put things into their feed if they're looking at your app while you're doing it. And this is irritating. It completely breaks all the apps I use that syndicate the outside world into my Facebook profile - Twitter, delicious, CPAN, Dopplr, etc.
It seems that this is an effort to stop users like me, who just want to use existing services, but centralize update notification for the friends I have that don't want to obsessively subscribe to 20 RSS feeds. Naturally, facebook don't like me, because I don't see, and therefore click, their ads. Forcing me to visit the site to tell my friends anything 'fixes' this.
Maybe I'm paranoid. Maybe I'm mis-reading 'actively', and they're ok with installed apps using session_ids of users who aren't logged in and using that app at this precise moment. I hope so.
Timezones are hard. I've personally spent way too much time dealing with date and time formatting issues and stupidity. But in this case I want to mount a defence of XML-RPC, because I really quite like it. I feel the kung-foo blog gets its complaint wrong:
The Atom publishing protocol gets this right. It requires that dates sent and received specify the timezone. There's no need to configure ecto as it knows Atom is a good boy. The problem is with XML-RPC. It does not have that requirement, and each blog system interprets dates differently.
The XML-RPC spec is really small. It's very easy to implement from scratch if you need it, but you don't normally need to do so, because sensible languages already have clients. And you don't need to know about the XML side of things - it's just RPC, you're calling a named method on a specific endpoint with ordered parameters. Not very RESTful, I'll grant you. But I like things that map well to the underlying realities.
One of the data types it knows how to encapsulate is a 'date', and it does this sensibly, serializing the date using ISO8601. If 'not specifying timezones' is an error, then it's an error in the ISO8601 spec, because the spec allows a time without a timezone. XML-RPC isn't judgemental. But 'floating' times do exist. And I can send them with XML-RPC.
Granted, they make little sense in the context of a blog entry. So the error is with the metaweblog (and associated) apis, which merely use XML-RPC as their transport. I will happily agree that the awful mess that is the metaweblog api is a pain. But don't equate a cruddy API and buggy implementations with the underlying transport.