Two years ago, I began working on a new Twitter client for iPhone, named Streamlines. I hinted at it about a year ago, and has been a driving force in my development of MGTwitterEngine and a ton of open source projects. I've come to the conclusion that I won't have time to finish and release it, as there's still probably another 6 months of development needed to really ship it, and hostility from Twitter and from users of other Twitter clients make effort into building one unsustainable. However, I think there are UI concepts in there which are totally unique and have never been seen before, so I'd like to share them with you before this project is lost to the annals of dead projects.
Here's a video walking through some of the main UI concepts found in Streamlines.
Streamlines is a social networking client that is designed to show you what you want to see, and hide what you don't care about. To do this, it avoids using tab bars and navigation stacks, and instead uses a card interface with a horizontal swipe, similar to the iPhone's Weather app or WebOS' multitasking UI. You pick which timelines you want to see.
On top of that, you can merge multiple timelines together, across all types of timelines, accounts, and services. For example, if you use Lists on Twitter and Facebook to organize, say, your family members, you can create one contiguous timeline which combines both those lists and shows you what your family members are doing, regardless of where they posted it to. Or, you can combine your Twitter followers, mentions, and direct messages together, similar to how Twitterrific works. This saves you time, as it lets you create your own timelines which show you new perspectives on your social networks that you simply can't get with most Twitter clients.
Streamlines tries to make sure you always are looking at the best data, so for every tweet you see on screen, it will update the relative date in real time. So if a tweet is 6 seconds old, it'll update live to say "6s", "7s", "8s", etc. The time is always up to date, so you know how long ago someone actually posted something. Streamlines accounts for API rate limiting, using some advanced heuristics to schedule API requests so that you never run out. This was more a problem two years ago, when you had 30 API requests per hour shared across all your Twitter clients, but still handy. And it handles incoming and outgoing attachments, so if you or someone else embeds content from another site, Streamlines will replace the URL inline with a preview of the image or video.
Under the Hood
Streamlines is backed by two frameworks I wrote, BirdNest and BirdNestUI. They're frameworks because, well, I actually have about 8 apps which use the same Twitter source code, spanning iPhone, iPad, and Mac. This framework tries to encapsulate a lot of functionality - it includes multiple accounts (with credentials stored in the Keychain) spanning multiple services (Twitter and Facebook, with plans to expand into other timeline services like Google Buzz, Foursquare/Gowalla, Yelp, etc.), networking, persistent data, and lots more. It's powered with Core Data and has about 12 open source projects which make up various pieces. The UI framework contains views for showing and creating accounts and timelines, creating tweets or wall posts, and showing timelines in tables (and there's a corresponding UI framework for Mac).
Why Won't It Ship?
There are many reasons. First and foremost, it's at least 6 months out from being released, and that's optimistic. There are lots of bugs, crashes, and UI problems alone, not to mention whole views just not having been built yet. So there's a huge body of work still to be done. I haven't had much opportunity to work on it recently, and there's not much to suggest I'll have more soon.
On top of that, building a Twitter client has become far less appealing than it was two years ago. In those two years, Twitter has drastically increased their feature set to include a TON of things, including geolocation, native retweets, and lists to name a few. The only way to remain competitive is to iterate extremely fast to include every new feature, whenever Twitter announces them. At the same time, Twitter has made several very hostile moves to make it even less appealing to develop on their platform; the most egregious of which was the acquisition of Atebits and their Twitter client Tweetie. There's now such tremendous market saturation for Twitter clients, especially on iPhone. Releasing a new Twitter app now is difficult, as nobody really pays attention to new Twitter clients any more.
Competing with Twitter's free app is hard enough. Even if I could get it to market, there are tons of users who will demand that every feature Twitter offers be crammed into every new release. And everybody's list of must-haves is different; some people will only care about lists, and will rail on you if they can't edit lists. Some will only care about the geolocation feature and if you can put that on a map. Some will only care about native retweets and seeing a list of people who retweeted. Every one of those features, to these users, is a line item on a checklist that needs to exist. To a developer, every one of those features can take weeks or even months to build properly. But every one has to be in there. Oh, and all of those features need to coexist, cleanly, on a small screen, with a fantastic user interface. It is an insanely complex problem to solve.
All of which needs to be built for an app that will not receive much attention, that will be crowded out of the market and will need to be priced cheaply to compensate, and that will be overshadowed by Twitter's own app anyway. There just simply isn't much reason to build a Twitter client anymore. I would much rather spend my time building an app that users will judge for its own merits, not for its completeness in binding to another service.
I'm not sure what to do with Streamlines as it is today. I do think there is a market for niche apps which use Twitter, and I still have some intention of bringing those to market. But I can't say when, and if they ever come, they will not be full Twitter clients.
I'm considering open-sourcing the code, but I'm not convinced of its practicality yet. I'm hesitant to think that someone will want to adopt a monolithic framework for building their own Twitter apps. It's possible they do. But the code is not the cleanest, and there are surely lots of bugs.
That being said, if anyone wishes to build an app with a similar interface, they have my full blessing and encouragement to do it without any permission from or attribution to me needed. I'd like to see more variance in Twitter client UI in general, as the tab bar metaphor is pretty worn at this point.
I would love to hear any and all feedback, positive or negative, either by Twitter or by leaving comments on the YouTube video above. Thanks for watching and reading.
Twitter recently introduced a feature on its website called "Who To Follow". This feature presents you with a list of people you aren't following already, but who are active in your social graph. However, I happen to be very proactive in finding new people to follow through a variety of means, and have no need for Twitter to point it out to me. I thought it was a bit obnoxious to see, especially considering both of my first recommendations were people I had blocked.
This Safari extension removes that box from the Twitter homepage, whether you have it turned on for you or not. It's a simple CSS stylesheet that sets display:none on that box. You'll never have to see it again.
You can download it here. I'm still a bit new at Safari extensions, but it should auto-update in the future if I ever release an update.
Update 9/18/2010: Follow Freely 1.1 has been released, with support for the new Twitter web client. It also fixes the issue where Safari would constantly say there was an update available.
For a little less than a year, I've been writing code built atop Twitter, specifically Matt Gemmell's MGTwitterEngine. I've got a few things running on this code, which I've not talked about publicly (other than minor hints on Twitter), but have been well-received by the few people who have seen it. Still, these projects have needed to extend both MGTwitterEngine and related libraries to add functionality or fix bugs. I'll spend this blog post documenting some of those changes across the different projects.
Most of these changes were made to make the engine's behavior a bit more extensible. Here's the GitHub repository.
MGTwitterEngineIDis a typedef for unsigned long long values. Everywhere a user ID or tweet ID is returned, it will return one of these. You will want to check your existing Twitter code to make sure there are no potential Twitpocalypse-related problems, updating old data types to the new
- Subclasses of
MGTwitterEnginecan now override a new method,
-_sendRequest:withRequestType:responseType:, if they want to use custom networking code (such as with an
NSURLRequestqueue class). I use this to implement both Twitter's password authentication and OAuth, and decide at runtime which to use.
- Added a
MGTwitterEngineDelegate, which can be used to update your UI.
- Fixed a few bugs in the YAJL parser which crashed or parsed incorrectly.
Things I still need to do:
In my custom subclass ofUpdate: Thanks to Uli Kusterer, the dependency on
MGTwitterEngine, I use a class I wrote called
TCDownload, which I'll talk about below. There are still a few references to it in my
MGTwitterEngineclass; those should be fairly straightforward to remove.
TCDownloadhas been removed. The changes have been merged from his fork into mine.
- Add full support for Twitter lists. I have some basic Twitter list functionality working in a private subclass, but far from all of it. There are some problems with the YAJL parser that don't appear easily fixable with the stock
MGTwitterEngine(specifically, the API key for the list description is the same as the key for the user's bio, and these are overwriting each other internally). I'm going to look into replacing the manual parsers
- Add full support for new-style retweets. Haven't started this yet.
- Add support for geolocation in incoming and outgoing tweets. Haven't started this yet.
I've forked yajl to support 64-bit tweet IDs, mainly by changing the callback methods and the string parser from
strtoull. Here is the GitHub repository.
This is a repository of scattered classes which serve various purposes. There are two classes which are relevant for our discussion,
TCOAuthDownload. You will need the
TCDownload class if you use the vanilla
MGTwitterEngine fork, although I'll be removing those dependencies. Here is the GitHub repository
TCDownloadis a generic wrapper that encapsulates an HTTP request to the interwebs. It wraps NSURLRequest and NSURLConnection under the hood. It automatically queues request and gets callbacks on a background thread (although you can change either of these). I use it a few places inside my
MGTwitterEnginefork, but removed most of those changes and put them in a subclass.
TCOAuthDownloadis a subclass of
TCDownloadwhich accepts OAuth tokens and sends out requests with the correct headers. It relies on the
OAuthConsumerframework, which I'll talk about below.
This framework deals with OAuth. Twitter has officially announced that basic auth will be dead in June 2010, so getting on the OAuth bandwagon now is a good idea. Here's my fork of the OAuthConsumer framework on GitHub.
- Changed the signature code to use Common Crypto instead of the C libraries' HMAC APIs. This seems to work more consistently on both Mac and iPhone.
- Added a
-parseHTTPKey:value:method which is used to parse extended attributes in OAuth access tokens. Twitter uses this to pass some special metadata, like the username of the logged-in user. Subclasses of
OATokencan extend this to parse those tokens.
This isn't strictly a tool for doing Twitter development, but it can be handy when learning how to implement the OAuth login flow. I posted about it more back in January, and you can find the code and a prebuilt app over at GitHub.
Twitter uses OAuth as its supported form of authentication. This is fine for some apps like clients where users need to authenticate themselves, but it doesn't work well for bots or scripts run by one person. If the bot needs an access token, it can be a real pain to obtain without writing the intermediate code.
This application, OAuthery, serves a simple purpose. You supply it the consumer key and secret for your OAuth application. It creates a request token and the URL for authorizing it. You complete the authorization in a web browser and get a PIN number. You then enter that PIN number back into the application, and it spits out your access key and secret. At this point, the user authentication is complete, and you can add those credentials to your script, and access API resources.
This is largely intended as a developer tool for people developing applications with Twitter's OAuth impelmentation. It also provides code to show exactly how to perform the authentication process with OAuth and Twitter, so that developers who wish to implement such functionality in their own apps can use this as reference.
Inactive, because it's a simple tool that serves a limited purpose.