-
December 27, 2010
Hung Truong: Threadless Model!
Last week I took a train out to visit Chicago for a meeting with my favorite company, Threadless! Since I wrote that app I’ve been in contact with the founder et al, and they thought it would be cool for me to check out their offices. I won’t talk about what discussions went on (I’m being held by a “frieNd-DA“), but I can say that the Threadless office is mega sweet!
I got to hang out with some of the developers on Threadless and talked about the site and other random stuff (like t-shirt quality through the ages). I pointed out something that actually ended up being a bug that one of the dudes fixed almost immediately! Talk about transparency. At some point we were talking about how the Threadless t-shirt models are picked. Ivan (super nice guy) mentioned that the photographer might be looking for someone to model a shirt. He ended up replying and I got to model a brand new Threadless shirt in the cold, cold December Chicago air. The shirt’s called …To The Birds. Buy it today!
The Threadless office itself is pretty nice. They moved in relatively recently so it still looks a little bare. Apparently they have big plans for decorating. I was, once again, super star struck by seeing people who I feel I know very well through their pictures on the Threadless site. I met the beard guy, Red the dog (I think it’s a Shiba Inu) and other assorted celebrities. One of the developers I met was the guy in the Mr Tee photo and another was Mario in another shirt (I couldn’t figure out which one). Oh, and I said hi to Colleen and Kristen, who I first met at SXSW!
They let me go down to the warehouse and pick out some shirts to take home. It kind of took all the willpower in my being not to clean them out (they probably would not have let me). I got Upso, Mister Mittens and Houndstooth. I also got a cool I ♥ Threadless shirt that they don’t really sell anymore. Limited edition!
This is probably already obvious, but Threadless is an awesome place with some awesome people making awesome things (mostly shirts). I had a blast meeting the people behind it and I hope I can come back again really soon!
-
December 06, 2010
Letterpress Cactus Holiday Card
Yesterday I printed out some fun cactus holiday cards and today I put them on Etsy. This is my first time making cards using a decent quality paper (Arturo Stationery from Hollander’s). I got the cactus print block from Ebay and hand-set the type that says “Happy Holidays!”
I’m pretty happy with the result. I may end up buying the supplies to use photopolymer plates (a metal base) because this is way, way fun!
-
December 01, 2010
Conditional GETs in App Engine
I’m currently working on an app in Google App Engine that polls feeds periodically and then does stuff with them. I suppose I could use that pubsubhubbub thingy but I have a feeling that most feeds aren’t using this yet.
Anyway, I did a quick naive implementation of polling about every hour or so. Apparently the feed parser I’m using is pretty inefficient because it’s eating up a lot of resources (relatively speaking) on App Engine. I remembered that the http protocol is pretty smart, and there’s a way to figure out if stuff has changed since the last time you grabbed it.
Google’s urlfetch doesn’t seem to support conditional GETs (someone tell me if I am wrong). I looked around and found a few tutorials on how to accomplish this in Python using urllib2. The tutorials weren’t exactly what I wanted, so I had to change a few things here or there. Here’s a snippet of code that I’m using:
import urllib2 feed = Feed.get() #my feed object has a etag, last_modified and url property req = urllib2.Request(url) if feed.etag: req.add_header("If-None-Match", feed.etag) if feed.last_modified: req.add_header("If-Modified-Since", feed.last_modified) try: url_handle = urllib2.urlopen(req) content = url_handle.read() headers = url_handle.info() feed.etag = headers.getheader("ETag") feed.last_modified = headers.getheader("Last-Modified") feed.put() except Exception, e: logging.info(e) #just says 304 didn't change return dostuffwith(content)
This handles my use case, which is doing work if the feed is new, and ignoring it if it hasn’t been modified. I could probably wrap this into a function that returned false if it the file hadn’t changed, and the content if it was new… Probably will do that next.
-
November 28, 2010
♥s Threadless: iPhone App Launch!
Today my newest app was approved for the App Store (and should be propagating quickly)! ♥s Threadless is what I’ve been working on mostly for the past few weeks or so. Hurry up and download and review it, then come back here for more info about the app.
It’s no secret that I’ve been a huge fan of Threadless since I discovered it back in 2005 (see these blog posts for proof). I really love the fact that the community provides designs and decides which ones will be printed. The company is really only there to provide the machinery to make shirts and fulfill orders! I wanted to contribute to the community by making an unofficial Threadless app (and maybe get a little store credit to feed my t-shirt needs).
My main reasoning for writing a native Threadless app is that I found it pretty hard to browse shirts, even in a fully fledged web browser let alone an iPhone browser. The Threadless site is by no means bad, but it’s hard to see what designs look like when the images are small and on models. I prefer viewing the actual design. So I built an app that makes it easy to 1) browse and find cool shirts and 2) share them with your friends.
In order to do this, I needed to get a database of shirts on Threadless. It’s kind of unfortunate that Threadless doesn’t have an API. At all. Threadless does, however, has a few feeds of shirts: one for shirts that are in stock and another for the weekly additions. I parsed this list of shirts and saved them in an App Engine database along with some other metadata like image urls, category info, etc. I also figured out a way to get the list of all Threadless shirts, including the ones that aren’t currently in stock. What this means is that the ♥s Threadless app will help you find more shirts than even the official website can. You can filter by category, color and run fulltext searches on the entire shirt database.
As far as the front end work went, I had to build a custom table view cell to scroll through shirts and a nested scrollview to view shirt images. The shirt view looks a lot like the native photo browser app for the iPhone. I also added features for sharing, including saving the image to your photo album, posting the design on Twitter and Facebook and emailing the shirt design as an attachment. I figure that covers most bases as far as sharing goes.
So far I’ve only designed and built the iPhone version. I think an iPad version would be neat, too, but I want to gauge the interest in the iPhone/iPod app before putting more time into this. If you like the app, let me know and write up a review for it!
-
November 20, 2010
ObjTweet: Helper Class for Twitter on iOS
I’ve been working on a new app (I’ll write more about it in a week or so), part of which required opening a user’s Twitter client with a pre-populated tweet or opening Twitter on a particular user’s profile for easy following. There are a lot of Twitter clients out there, so it’s hard to predict what a particular user will have installed on their device. They might not even have any Twitter client installed.
Many (but not all) Twitter clients have url schemes that allow you to open them with a particular message filled out, etc. There’s a few here, but it’s not a definitive list by any means. I gathered a bunch of the more popular ones and wrapped them in a helper class called ObjTweet.
Since I want to give back (and I wouldn’t mind the recognition), I’ve licensed this class under the
GNU GPL licenseMIT License (thanks, Marcello for pointing out that the GPL license is pretty restrictive) and uploaded it to Github. Hopefully someone else finds it useful. My hope is also that people will help find some of the missing url schemes for other apps and build on ObjTweet. If you found this class and are using it, let me know! Hopefully it works as described.