Sharky tea-infuser by Pablo Matteoda

 

sharky

I’m not much of a tea drinker, but if I had Sharky, I’d gladly have a cup of tea every morning. Unfortunately, it’s only a concept at the moment, but with its novelty appeal, I’m sure it’ll go into production sometime soon. One commenter at Looks Like Good Design did make a good point—”who owns clear tea cups?”

Disk-it sticky notes take me back

 

54_bk-disk-it-2

Disk-it sticky notes by Burak Kaynak certainly take me back to the days of 1.44mb. If you had papers for class that needed printing, drag those unformatted SimpleText .txt files over and hope you get to class early so you can snag the only Mac that supports your floppy. From the photos, it seems these are thick enough to be considered Zips, but that’s just me being picky. I’d love to see Jaz drive notebooks. Anyone else?

54_bk-disk-it-4

via Design Milk

Twitter's new retweets fail to fix an unbroken system

 

new_retweets

Twitter’s new retweet system isn’t exactly new anymore, but the way in which it is implemented feels like it would be an older system, reducing ease of use and accessibility. Prior to the ‘upgrade’, retweeting consisted of a simple tweet including the original tweet, tweeter and a marker. The marker first started as ‘RT’, but over time, variations were ‘invented.’ In the early DestroyTwiter days, Josh Corliss suggested using ‘>’ instead of ‘RT’, which saves a character and simply looks better. Many users reference tweets with ‘(via @username)’ or ‘/via @username’ to summarize instead of using word-for-word retweets. All of these options can be edited, daisy-chained, and commented on. They also appear in the retweeted user’s mentions timeline, notifying him/her of a retweet. With the new system, all of these features are either diminished or elongated.

To give an idea of the work on the developer, the new retweet system introduces the following API methods:

1
2
3
4
5
6
7
statuses/retweet
statuses/retweets
statuses/id/retweeted_by
statuses/id/retweeted_by/ids
statuses/retweeted_by_me
statuses/retweeted_to_me
statuses/retweeted_of_me

The original system requires only two:

1
2
statuses/update
statuses/mentions

Of course, the new system brings more control, but is it all necessary? In order to see which tweets of yours were retweeted and by whom, the statuses/retweeted_of_me method must be called, followed by the statuses/retweets method for each tweet. Unless you’re whitelisted (have 20,000 API calls), calling these methods, in addition to the common methods, could certainly add up quick. On top of that, both methods would need to be polled consistently to stay up-to-date in case additional retweets were made. Unless the developer of the app you use wants to bend over backwards to notify you of new retweets, you’re forced to visit Twitter.com to check.

Now, is it really such a big deal to know how many times or by whom your tweets are retweeted? Not entirely, but I personally gauge which tweets my followers react to the most by how many times the tweets are retweeted. If I tweet about DestroyTwitter and it’s retweeted a dozen times, then I tweet a video of my cat that only results in crickets, I’ll know to lay off the cat videos—but that’s just me. Other users find new people to follow by seeing who retweets their tweets.

With the new system, Twitter makes it harder on both developers and users. The original system worked and worked well. Many users, like myself, reject the new system and continue to use the original one. Because of this, users must reference multiple locations instead of one. This once simple-as-can-be feature is now a nuisance.

Twitter used to be simple. It still can be depending on which app you use, but if other features are ‘improved upon’ as retweets were, we might end up with unavoidable obstacles. I’m growing tired of services that start out beautifully, then take a turn for the worst after being packed full of unneeded additions. A prime example is Facebook, but that’s for another time.

(photo property of DreamWorks and Universal Studios)

3 years of support and inspiration

 

3yearanniversary

Today marks three years for Jen and me. She’s been my source of inspiration since the day we met and I wouldn’t be where I am now if it weren’t for her support and encouragement. She means everything to me and I simply can’t wait to see where the next three years take us.

"Congratulations, you now own an iPad. "

 

ipad

On Saturday, I joined the other 700,000 people who spent part of their day waiting in line at the Apple Store. What made my experience unique is that I was the only person in line at 3 pm—and remained the only person in line for the next 20 minutes.

I arrived at the Apple Store with my brother and saw the ropes outside with no one nearby, so I walked inside. An employee asked if she could help me and I said I was there to pick up an iPad. She said, “Congratulations!” and asked me to step outside and wait in the empty line. Since the iPad is for work, I just needed to pick one up—no need to play with one, decide between the different models, or pick out accessories. At any other store, I would’ve able to go straight to the cash register, purchase what I need and be on my way.

My personal salesman arrived, asked for my name and said, “Congratulations, Jonnie!” He turned to my brother and warned him that I’ll ignore him for the rest of the day. I told him I’m a software developer and I just need the 16gb model for testing. He said, “Need! I like that word. You need it!” He then said he’ll check in the back to see if they have any left—after waiting in the empty line that whole time.

He came back with box in hand and said, “Congratulations, we have one available for you.” Next was the long list of extras to sell me. I know it’s their job to get me to buy a dozen accessories, but I ended up repeating, at least a dozen times, that I only needed the iPad—half of them was to turn down Mobile Me after he insisted I wouldn’t be able to completely experience the iPad without it. Each time I said I didn’t need any accessories or additional services, he looked like a deer in headlights, as if no one has turned them down before. He then said, “Jonnie, you’re looking at me like I’m a putz.”

It was finally time to pay for it, so I handed him my company card, and he says, “Congratulations, you’ll be the first at your company with an iPad.” I laughed and said, “Actually, we already have ten.” He looked shocked, then continued processing the order with an uncomfortable look on his face. This entire time, I tried my best not to reveal I work for Adobe—to avoid any unnecessary awkwardness. For the receipt, they needed an email address, so I painstakingly said, “jhallman@…adobe.com.” He paused for a moment and asked if I work for Adobe. I said I did and he exclaimed, “You guys hate us!” I assured him we don’t and said we just want Apple to support our platforms.

After the order went through, he said, “Congratulations, you now own an iPad.” But before I can go he said they were required to activate the iPad in the store “to make sure it works.” Can you imagine if I was a fanboy, dying to video tape the unboxing? That would’ve hurt. He led me to the ‘activation girl’ and said, “Jonnie needs his iPad activated …He works for Adobe.” From the tone of his voice, I felt compelled to ask the girl if that was code for something.

The whole experience just made me feel so awkward. I remember when I could walk into an Apple Store, tell an employee what I need, pay for it and leave. They would treat me like a regular person and talk like one too. I realize it was the release of the iPad, but the entire time I felt like I won it or needed their approval in order to get it. Congratulations? I’m a consumer there to purchase a product. The ordeal left me a little sick, as if they expect me to be that Apple fanboy who flaunts every iGadget, helpless without them. I do own a Macbook Pro, an iPhone, and now an iPad, but I’m not that guy.

Unit testing Signal implementation

 

Robert Penner’s Signals has made my life so much easier these past few months. It avoids what I hate about Events while including features Events desperately need. There is one downside I have come across, which is mainly due to human error—making sure to dispatch a Signal with the correct value objects. If you set a Signal’s value classes like so:

public const timeChanged:Signal = new Signal(int, int, int); // hour, minute, second

…and dispatch it with incorrect value objects:

timeChanged.dispatch(1269874749); // unix timestamp

…Flash Builder throws an argument RTE. Since the RTE is thrown on call of dispatch and not at compile time, there is a possibility of missing the error, leaving your users with an unfortunate experience.

Now, this is easy to avoid by simply double checking your code, but if you’re working on a team, you can’t ensure this way that everything remains perfectly intact. You can, however, guarantee each signal fires correctly by unit testing. Sure, Robert has unit tested Signals to the max, but he hasn’t unit tested your implementation.

To do this, simply call dispatch of each Signal within a test method. The Signal will notify the runner if something is not right, indicating the line number and expected argument type as well. If you use a Signal bus to communicate throughout your app, your test will look something like this:

It’s that easy. Now you will know for sure if your Signal implementation is in tip top shape. All you need to do is run your unit test.

Displaying a context menu via hotkey crashes AIR

 

I love hotkeys and I try to build them into all of my apps. They greatly improve the desktop app experience, especially for the anti-mouse crowd. I recently thought of a handy way of using a hotkey—display a context menu upon pressing the spacebar with an item selected. This feature would be so sweet… if it worked.

I quickly typed up the implementation and tried it. Expecting to see a context menu, I was dumbfounded to see ADL crash without a single RTE stack trace. Here’s an example of the code that causes the crash every time:

At first, I thought it might be an ADL issue, so I compiled the AIR file, installed it, and the insanity continued. Instead of crashing instantly as the app did running on ADL, it first displayed this alert:

contextmenuhotkeybug

Let me known, I’m running the most recent build of AIR. Upon clicking ‘OK’, the app quits. I can run the app all day and a soon as I trigger the context menu to display, this alert appears. I checked the Console and found this:

I also added the full crash reports in the Gist. I’m not sure what it all means, but I filed the bug with Adobe and can only hope it’s fixed sooner than later—this feature would be too cool.

How would you prefer to shorten a URL?

 
Sorry, there are no polls available at the moment.

Using setter injection to provide a view for base mediators in Robotlegs

 

Yesterday, I came across an issue with an app I’m developing with Robotlegs. The app uses what I call “canvases” to represent each section. There’s some similar functionality between the canvases, so I decided to create a base mediator and extend it for the more specific functionality. A problem arose when I needed to access the view in the base mediator, while injecting it as the subclass in the extending mediator. At first, I tried this ghetto solution, since I only needed the view for one handler:

But as time went on, I added more handlers to the base mediator. The more handlers I added, the uglier the code became, with the AS2-reminiscent this['view'] in each function. I remembered reading something about injection types other than property-based, so I ventured out and discovered setter injection. With it, I can inject the subclass view into the subclass mediator, but still access the base view from the base mediator—classy! Here’s the implementation:

Though this works perfectly fine when extending a base mediator once, I already came across an issue—what do you do when your base mediator is extended twice? I suppose you could use a private getter in the in-between subclass, but if anyone has suggestions, feel free to drop them in the comments.

Paging through the Twitter stream

 

Working with an API can be a hassle—especially if you have no control over it. Twitter’s API has its fair share of obstacles, one of which is paging. When you first look at a method in the Twitter API, you will most likely go straight to the page parameter. It’s simple and expected—page 1 is the most recent and the page number increases as you navigate back in time. This seems like the right solution, but it’s not. The page parameter has a major downside.

twitter_paging_0

Since page 1 is the most recent, the entire paging system is relative and forever changing with every new tweet. This means if your user pages back in time, as new tweets arrive in the Twitter database (for his stream), he’ll see the same tweets finding their way into the next page. If the user pages older once and 20 new tweets arrive in Twitter database, he will see the exact same page the next time he pages older (if the count parameter is set to 20).

twitter_paging_1

This issue can be easily dodged by using the max_id parameter. With it, you can set the maximum tweet id number to appear in the stream, excluding all tweets that appear after it. This can be used in paging by setting max_id to one less than the id of the bottom tweet in the stream. There are, however, a few downsides. Since there is no min_id parameter, you need to store all of the previous max_id parameters, so you can find your way back (assuming you run your app off the raw API data and not a local database). Also, I’ve noticed Twitter caps the number of tweets you can retrieve to about 700 or 2 months (I’m not sure if this is a count-based limit or date-based). This is interesting, considering Twitter indicates in the API docs that they limit the number of retrievable to 3,200. They do note this under “pagination limits” using the page and count parameters, but I assumed we would see this same amount for max_id.

Now, another issue with Twitter pagination, and the original reason I decided to write this post, is gaps in the Twitter stream. If your Twitter app caches tweets to a local database, this is for you. Let’s say someone uses your application once, then takes a day off and returns the next day. In that interim, thousands upon thousands of tweets entered the Twitter database, and possibly your user’s stream. The next time this user starts the application, it loads in the latest tweets, but there is still a slew of tweets from the previous day. What do you do?

twitter_paging_2

Use a combination of the max_id and since_id parameters. Start loading older pages using max_id and when the return is empty, you’ve either caught up to the most recent tweet id from the previous session or you reached Twitter’s limit.

A few of Twitter’s newer methods use cursors for paging, where each result includes two numbers that are used to navigate to the newer or older page. I personally haven’t used any of these methods, so it’s unclear to me whether the numbers are relative or absolute—hopefully, the latter. In any case, I look forward to this implementation in some of the older methods like favorites that doesn’t even have since_id or max_id yet.