Growl and OS X Dashboard widgets (cont’d)

After discussing Growl integration with OS X Dashboard widgets in my first article, I was lucky enough to hear back from Andrew Hedges, who suggested:

The more likely explanation is that Dashboard is having trouble running multiple instances of osascript through widget.system. This would be a great question for the Dashboard-Dev mailing list, on which several Apple engineers lurk.

For those interested, you can see my Dashboard-dev thread here. Although it currently remains unanswered, I decided to post here about some additional work I’ve done regarding Growl integration in the Dashboard.

Being relatively obsessive about presentation, I made an effort to solve one of the gotchas I listed previously. Specifically: I wanted to get rid of the default Dashboard icon on Growl notifications and replace it with the (far prettier) Airmailr icon.

There were two possible solutions to this problem, and both are hinted at on the official Growl ActionScript support page. The first possibility was to extend Mr. Hedges initial AppleScript to contain raw graphic data. Not only did this seem slightly messy, it also meant that the Airmailr logo would essentially exist twice within my widget bundle, increasing the overall size of the distributable and making any logo updates a pain.

The second possibility was to use the image from location attribute and pass Growl an absolute path to the widgets icon. To do this, I use the following code:

1
2
 var widgetLocation = window.location.href;
 var widgetRootLocation = widgetLocation.substring( 0, widgetLocation.lastIndexOf('/') )+'/';

By using the window.location object and grabbing the href attribute, I’m passed the absolute path of my widgets .html file (main.html, in most cases). From there, I trim off anything after the last forward slash. This gives me the absolute path to my widgets ‘root’ directory.

From there, if we want to grab the absolute location of our icon, it’s just a case of doing something like this:

1
var widgetIconLocation = widgetRootLocation+'img/icon.png';

Once we have our icons absolute path, it should be relatively painless to update Mr. Hedges AppleScript to accept an icon path as it’s sixth parameter:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
on run argv
	tell application "GrowlHelperApp"
		set the allNotificationsList to {item 1 of argv}
		set the enabledNotificationsList to {item 1 of argv}
		register as application ¬
			item 2 of argv all notifications allNotificationsList ¬
			default notifications enabledNotificationsList ¬
			icon of application item 3 of argv
		notify with name ¬
			item 1 of argv title item 4 of argv ¬
			description ¬
			item 5 of argv application name item 2 of argv ¬
			image from location item 6 of argv
	end tell
end run

And that’s it! Nice, simple and with some very pretty results.

Accessing Growl via OS X Dashboard widgets

Recently, while working on the latest version of Airmailr, a user suggested the introduction of Growl integration. Initially I thought this would be impossible, given that OS X’s dashboard widgets run primarily via JavaScript. After having dug around in Apple’s Dashboard Programming Topics, however, I came across an article entitled Creating a widget plug-in, which documents the creation of an Objective-C Cocoa bundle and the ability to link it to your Dashcode projects.

Being something of an XCode newbie, I continued my Google search for possible alternatives, which is when I came across Andrew Hedges article: Sending Growl notifications from Dashboard widgets. Mr. Hedges suggests the use of a shell script to check for the existence of the GrowlHelperApp before executing an AppleScript that passes Growl the necessary notification data (as specified on the official Growl website).

While this makes the process of Growl notifications via Dashboard apps much simpler for users such as myself, there are a few gotchas people need to be aware of. Mr Hedges states his need for Dashboard Growl integration as follows:

My use case was that users of my URL shortening widgets wanted to be able to exit Dashboard and be notified when the URL had been shortened and copied to the pasteboard.

What’s important to note here is not the task itself but the probability of multiple, repeated Growl notifications. You see, unlike Mr. Hedges URL shortening widget, Airmailr needs to be capable of sending multiple Growl notifications (more specifically, a Growl notification for each new tweet a user receives). In testing, I’ve noticed patchy behaviour on excessive use of this technique, often with a number of notifications passing the initial shell script test but never appearing on screen. I wonder, is there some sort of flood control mechanism built into Growl that I’m not aware of?

Secondly, it’s important to escape any quotation marks within the notification title and body elements. Otherwise you’re bound to see a few nasty, corrupted notifications.

Finally, I’ve yet to find a way to pass Growl any kind of meaningful application icons. Ideally, I’d like to use user avatars, but I’m not sure that Growl is capable of accepting remote URLs. The best I’ve managed to do is to supply Growl notifications sent in this manner with the default Dashboard icon.