The way I wish all software subscriptions worked

Published on by Geoff Taylor

Due is a fantastic reminder app that I’ve been using for almost five years, according to the screenshot below. Due gets a lot of things right: It’s powerful, yet not overly complicated. The interface looks really nice. Automation is relatively easy thanks to its well-documented URL scheme. Add to that the most consumer-friendly subscription model I’ve seen to date.

I have mixed feelings about software subscriptions. Some are very valuable to me, and I pay for them without a second thought. Others I just can’t justify, no matter how much I like the app. When the developer of Due announced that it was moving to a subscription model, I wasn’t sure which category it would fall into. But then I read the blog post explaining how the subscription works. It’s actually something that I wish more apps would do. When you subscribe, you get access to all new features released during your one-year subscription period, in addition to all existing paid features that you haven’t already unlocked. If you choose to cancel the subscription, you get to keep all of the features that you paid for, and you still get free app updates (but not access to new features). And I think it’s reasonably priced at $4.99.

I really like what the developer has done with the app’s subscription screen. It tells you when you purchased Due, when your access to upgrades ended, which paid features you’ve unlocked, and which features you’ll unlock (forever) if you subscribe.

Due subscription screen
Due's subscription screen

I decided to subscribe for the improved Siri Shortcuts implementation. Knowing that I won’t lose any functionality if I decide to cancel certainly made the decision easier.

Use Keyboard Maestro to connect a Mac to an iPad via Sidecar

Published on by Geoff Taylor

If you use your iPad as a second display for your Mac via Sidecar, you can connect to it using a keyboard shortcut with Keyboard Maestro.

You can download the macro here or create it yourself using the following instructions. (If you download it, you’ll still need to set the device name as described below.)

Create a macro with an Execute AppleScript action. Copy and paste this code into the action:

set deviceName to "The name of your iPad"

tell application "System Events"
	tell process "SystemUIServer"
		click (menu bar item 1 of menu bar 1 whose description contains "Displays")
		set displaymenu to menu 1 of result
		if ((menu item 1 where its name starts with deviceName) of displaymenu) exists then
			-- Not connected, so click the name of the device to connect
			click ((menu item 1 where its name starts with deviceName) of displaymenu)
		else
			-- Connected, so click "Disconnect" to disconnect
			click ((menu item 1 where its name starts with "Disconnect") of displaymenu)
		end if
	end tell
end tell

In the first line of the script, change "The name of your iPad" to the real name of your iPad (leave the quotation marks around the name). (You can find your iPad’s name in the AirPlay menu.)

  Name of device in AirPlay menu
Find your iPad’s name in the AirPlay menu

Set your desired hot key (I’m using ⌃ Key Pad +), and you’re all set. Press the hot key, and your Mac will connect to the iPad. Press the hot key again, and it will disconnect.

(You could probably connect to an Apple TV using the same script, but I don’t have an Apple TV, so I can’t verify it.)

JXA: How to use openForAccess

Published on by Geoff Taylor

Apple’s documentation shows that to open a file for writing in a JXA script, you call the openForAccess method on an Application instance. What the documentation doesn’t make clear is that you must call openForAccess on the instance returned by Application.currentApplication(). Anything else will fail.

If you run this code in Script Editor…

let app = Application('Finder');
app.includeStandardAdditions = true;
let desktop = app.pathTo('desktop').toString();
let myFile = `${desktop}/temp.txt`;
let openedFile = app.openForAccess(Path(myFile), { writePermission: true });
app.closeAccess(openedFile);

… it produces an privilege violation error.

  Script Editor error message

Script Editor even helpfully tells you that the privilege violation occurred on the line where we attempted to open the file.

But if you change Application('Finder') to Application.currentApplication(), it works.

let app = Application.currentApplication();
app.includeStandardAdditions = true;
let desktop = app.pathTo('desktop').toString();
let myFile = `${desktop}/temp.txt`;
let openedFile = app.openForAccess(Path(myFile), { writePermission: true });
app.closeAccess(openedFile);
  Script Editor no error message

(“Undefined” simply means the last statement didn’t return a value.)

If you need to open a file for writing, you must set a variable to Application.currentApplication() and call openForAccess on that Application instance — even if you’re already working with another application.

JXA: Find My Purchased Music

Published on by Geoff Taylor

I was looking at one of my playlists and wanted to know which songs I owned and which were from Apple Music, so I wrote a JXA (JavaScript for Automation) script. It works in macOS Catalina (10.15) and Mojave (10.14). Learn more and download the script from the GitHub repository.

Last light

Published on by Geoff Taylor

Last light
Last light