Category Archives: Tech

WaterField’s iPad 1 suede jacket fits iPad 2 + Smart Cover perfectly

With the original iPad, I wanted something to protect the iPad from other objects in my bags, but I prefer using it “naked”. WaterField Designssuede jacket was the perfect solution. With iPad 2, the Smart Cover is a really neat accessory as it protects the screen and also tilts or stands up the iPad. From looking at the specs I had suspected the iPad 2 with Smart Cover might fit inside the suede jacket for iPad 1, last week when my iPad 2 arrived, I confirmed that it is indeed a perfect fit. I think this is the best option by far.

Waterfield

Waterfield

Don’t run MySQL 5.5 on OSX

So while setting up a Rails2 development environment with RVM for one of my clients on my new Mac, I came across the infamous uninitialized constant MysqlCompat::MysqlRes error. Typically this is because the mysql gem isn’t compiled with the right archflags, but of course that wasn’t the case. After messing with it for a bit, I found out that the MySQL server I was running was 5.5.10, and 5.1 is supposedly more stable. So I downgraded it and everything worked.

credit: this post helped a bit.

Switch your Flickr login from Yahoo! ID to Google or Facebook

Flickr/Yahoo just added Facebook Connect and Google OAuth support to their sign-in, this is great, coz now I no longer needs a Yahoo! account to use Flickr. (I assume you all loathe Yahoo! as much as I do right?)

Here’s how to change your Flickr account from your Yahoo! ID to your Google or Facebook account:

  • sign into Flickr with your Yahoo! account if you’re not already logged in
  • go to http://www.flickr.com/account/transfer/
  • hit “use existing Yahoo! ID”:
  • Flickr: Transfer your account

  • Hit “sign in as a different user”:
  • Dock-26

  • Choose Google, or Facebook (if you must):
  • Sign in to Yahoo!

  • signin and authorize your Google or Google Apps email and password, or if you chose Facebook, you probably will see a familiar oauth authorization window requesting some permissions
  • Click the “Okay, do it” button:
    Flickr: Transfer your account

Now is the time to downgrade your AT&T SMS plan

I’ve always had the $30 unlimited family text plan with our iPhones, I’ve switched to using SMS replacement apps with my most frequently texted contacts. I used to average about 700 messages a month in the plan, but the past several months I’ve gone under 200. Paying $30 a month for SMS is pretty ridiculous, worse yet, when I text between my 2 lines in my family plan, it counts on each line, while it’s free to actually place a voice call to any AT&T subscribers. I believe voice calling uses more network resource than an SMS.

So this Monday I downgraded the family text plan to the 200 messages plan for $5, going from $30 to $10 total. Here are the apps I use to replace SMS, there are many more, but these 2 use your existing mobile number as your identifier, which makes them real SMS replacements and allows easy contacts discovery.

  • WhatsApp: popular in Taiwan for some reason, $1
  • KakaoTalk: popular in Korea, free app.

In addition, I’m a huge BeejiveIM user, it’s the best IM app and definitely worth the $10. I’ve also dialed down my SMS from Twitter with push notifications from Boxcar and the Twitter app. Boxcar notifications consistently arrive before Twitter SMS when I had both turned on.

Looks like AT&T will be discontinuing the $5 SMS plan, so if you’ve been procrastinating to downgrade, now is the time to do it.

Leaked: New ATT text messaging plans in preparation for Verizon iPhone | Gear Live.

I used to love Skitch…

UPDATE (12/5/2010): With Skitch Plus, everything is awesome, definitely worth the $15/year. Pretty sure they looked at metrics/custdev to figure out what power users do and then they purposely made those things annoying with their new site and added Plus to make it awesome when you pay.

Preferences

Original post:

I’ve been using Skitch since very early beta, got all my friends to use it, I pretty much can’t work without it. I have about 1.5k images skitched on my current Mac.

I just want to get an URL to a skitched image as soon as I can, with Skitch, you have to upload, open the webpage, wait for the Flash to load, and copy the link to URL. Often time Flash will almost crash my browser in the process, and their new website makes this workflow even more annoying by hiding the share menu and adding a bunch of different copy-to-clipboard links that I don’t care about:
andrewng | skitch.com

It’s now at least 4 clicks and 10 seconds from skitching an image to getting its URL in my clipboard to share. The client app should be able to give me that with a single click.

I did try CloudApp, great idea, but I need to edit the image and Skitch’s editor is nice and simple.

One thing I will try is to symlink ~/Pictures/Skitch to my Dropbox, that way I just need to save the image in Skitch.app, and skip the whole web UI non-sense.

jQuery form submit handling and inline onsubmit woes

jQuery’s event handling triggers in the bubbling phase, which is fine for most usage. I had to write some JavaScript to traps the submission of forms on any webpage, naturally, I wrote something like this:

$('form').each(function(e){
  $(e).submit(function(e){
    console.log("submitted!");
}

This works for most forms, but since we don’t have any control of what types of forms our users put on their sites, it doesn’t work in 2 cases: (a) when there is an inline onsubmit on the form tag, this is pretty common, the Feedburner email subscribe form does this, and (b) when the form is within an iframe on the page.

The fix for (a) is not trivial, I found out that the bind submit event is called after the inline onsubmit, so first thought was to put what I need to do on submit into a function, and prepend that in the onsubmit. However, this didn’t work as $(‘form#some-id’).attr(“onsubmit”, “blah”) didn’t set the value. So after a bit of experimenting, I ended up having to remove that attribute, but remember the contents of it and call it in an annon function at the end of execution, it looks like this:

$('form').each(function(i,e){
  var onsubmit = $(e).attr("onsubmit");
  if (onsubmit != null) {
    $(e).removeAttr('onsubmit');
    onsubmit = new Function(onsubmit);
  }
  $(e).submit(function(e){
    console.log("submit pressed!");
    if (onsubmit != null) onsubmit();
  })
})

Now on to finding a solution for the (b) iframe case.

ubuntu lucid, apparmor, and mysql

I had to move the mysql datadir on my ec2 instance to a different EBS volume. After I move it over, and change the datadir setting in /etc/mysql/my.cnf, I kept getting errno 13 when I started mysql, the error in /var/log/mysql/error.log looks like this:

100819 15:10:20 [Note] Plugin 'FEDERATED' is disabled.
^G/usr/sbin/mysqld: Can't find file: './mysql/plugin.frm' (errno: 13)
100819 15:10:20 [ERROR] Can't open the mysql.plugin table. Please run mysql_upgrade to create it.
100819 15:10:20  InnoDB: Operating system error number 13 in a file operation.
InnoDB: The error means mysqld does not have the access rights to
InnoDB: the directory.
InnoDB: File name ./ibdata1
InnoDB: File operation call: 'open'.
InnoDB: Cannot continue operation.

errono 13 typically means your datadir permissions are messed up, but I double checked, and mysql owned and had permission to everything in there, I even set the shell of the mysql user from false to a real shell and su to it and I was able to read everything. After about 45 minutes of digging around, I asked on the mysql irc channel, and a user with the handle of thumbs told me to check apparmor config.

I just migrated from jaunty to lucid and had no idea what apparmor was. Turned out it had to know about the datadir change or else it won’t let it start (if you look at /etc/init/mysql.conf then it’s obvious, but upstart was new to me too). After modifying /etc/apparmor.d/usr.sbin.mysqld, mysql started up just fine.

Just thought I should post this here in case anyone is having a hard time figuring this out. I certainly did.

Migrating a “degraded” Amazon EC2 Instance

I’ve been using AWS for a few years now, and it has been rock solid. Last Sunday one of my sites became unreachable, when I got home a couple of hours later, I was able to ssh into the instance and everything seemed to be working perfectly. I checked utmp logs and the instance was rebooted. A while later I got this email from Amazon:

From: Amazon EC2 Notification Subject: Notice: Degraded Amazon EC2 Instance Hello, We have noticed that one or more of your instances are running on a host degraded due to hardware failure. i-xxxxxx The host needs to undergo maintenance and will be taken down at 12:00 GMT on 2010-06-23. Your instances will be terminated at this point. The risk of your instances failing is increased at this point. We cannot determine the health of any applications running on the instances. We recommend that you launch replacement instances and start migrating to them. Feel free to terminate the instances with the ec2-terminate-instance API when you are done with them. Sincerely, The Amazon EC2 Team Sounded like they would terminate the instance because of hardware failure, and that would be very bad – this is a high volume eCommerce site. I looked around to see what was the best way to “clone” the instance and relaunch it, and it turned out to be really simple. When I setup EC2 stuff I always use an EBS volume for the important data like the /home, the MySQL storage, most of the configurations in /etc like Apache vhost configs. I also use an Elastic IP address so I can switch it to another instance easily, and it won’t require modifying DNS records at all. So all I had to do was:

  • get all your AWS access keys, certs, and user id, onto the instance
  • create a folder for the AMI bundling work
  • bundle the root volume on the dying instance
    $ sudo mkdir /mnt/ami && sudo ec2-bundle-vol -d /mnt/ami -k pk-CKXXXXXXXXXXXX.pem -u 12345678 -c cert-CKXXXXXXXXXXXXXXX.pem
  • upload the bundle to S3 and register the AMI
    $ ec2-upload-bundle -b somesite-post-degraded -m /mnt/ami/image.manifest.xml -a XXXXXXXXXX -s XXXXXXXXXXXXX/00XX
    $ ec2-register somesite-post-degraded/image.manifest.xml
  • launch a new instance with the AMI
  • unattach the EBS volume from the old instance
  • attach the EBS volume to new instance
  • re-assign elastic IP to new instance You can do a lot of these tasks from the

AWS Management Console. All of that took about 2 hours, most of the time was spent waiting for the AMI to bundle and upload as it was pretty large. Everything worked perfectly after the migration, when I set up the EC2 infrastructure I had planned for things like these and in theory migration should go without any glitch, but I never actually had a need to migrate an instance. It’s good to know that everything actually worked as designed.

Extra space/row in UIPopoverController content?

If you’re using UISplitViewController in your iPad/Universal apps, you probably implemented the UISplitViewControllerDelegate to add a UIBarButtonItem to the detail view controller’s toolbar to display a popover. The popover might have some extra space before the first row after you rotate the simulator or the iPad from landscape to portrait, took me a few hours to figure this out, it is because the navigation bar’s translucent property is set to YES, set it to NO before you add the button and you won’t see the extra space. Also, if you instantiate the nav bar in your NIB, leave its style asdefault in Interface Builder, otherwise the popover will be messed up on load when you launch the app in portrait orientation. Set them in code instead.

- (void)viewWillAppear:(BOOL)animated {
	[super viewWillAppear:animated];
	
	self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
	self.navigationController.navigationBar.translucent = YES;
}

#pragma mark -
#pragma mark UISplitViewControllerDelegate methods

- (void)splitViewController:(UISplitViewController *)svc willHideViewController:(UIViewController *)aViewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)pc {
	self.navigationController.navigationBar.translucent = NO; //if I don't do this we get extra space in popover
	barButtonItem.title = @"Some Title";
	
	// Keep references to the popover controller and the popover button, and tell the detail view controller to show the button.
	self.popoverController = pc;
	self.rootPopoverButtonItem = barButtonItem;
	UIViewController <SubstitutableDetailViewController> *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
	[detailViewController showRootPopoverButtonItem:rootPopoverButtonItem];
}

- (void)splitViewController:(UISplitViewController *)svc willShowViewController:(UIViewController *)aViewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem {
	//setting it back to black translucent
	self.navigationController.navigationBar.barStyle = UIBarStyleBlack;
	self.navigationController.navigationBar.translucent = YES;
	
	// Nil out references to the popover controller and the popover button, and tell the detail view controller to hide the button.
	UIViewController <SubstitutableDetailViewController> *detailViewController = [splitViewController.viewControllers objectAtIndex:1];
	[detailViewController invalidateRootPopoverButtonItem:rootPopoverButtonItem];
	self.popoverController = nil;
	self.rootPopoverButtonItem = nil;
}