Communicating with a webview in BTT Mobile from the Mac

I have a floating menu consisting of a single webview menu item which can run on either my Mac or on BTT Mobile. I know that I can execute JavaScript in the webview when it runs on the Mac via:

tell application "BetterTouchTool"
	webview_menu_item_load_html_url_js "4EF60C00-08CF-43D3-93F1-47FFBC2D2A23" javascript_to_execute "setBackground('red');"
end tell

where setBackground() is a simple helper function that sets the background of the <body> element to whatever colour was passed as an argument. However, if I have the floating menu running on BTT Mobile, it seems that the AppleScript call isn’t executed. This would be super useful to have, because bidirectional communication between BTT Mobile and the Mac would not only allow executing arbitrary code, but you could also pass images, audio, and even video to the BTT Mobile webview by sending the file in base64 encoding.

Is it possible to use AppleScript to communicate with a floating menu in BTT Mobile? If so, am I using the wrong syntax/command in the above?

Many thanks,

Jason

The reason I ask is that, for the floating menu on my Mac, I’ve created context-specific <div> elements that appear or disappear depending on what the current app is. Here’s the basic idea…

First, in the webview, create <div> elements of the following form: <div data-app-name=’id.of.app.to.target’> which contain the content you want to conditionally display, where data-app-name is set to the value of the bundle identifier for the app.

Second, define in the webview a simple function as follows:

function appChanged(appName) {
				$("[data-app-name]").each( function() {
					let element_app = $(this).attr("data-app-name");
					if (element_app.includes(appName) == false) {
						$(this).addClass("hidden");
					} else {
						$(this).removeClass("hidden");
					}
				});
			}

where ā€˜hidden’ is a CSS class which sets ā€˜display: none’ and nothing else.

Third, set up a trigger for ā€œActive App Did Changeā€ with the following action (replace the UUID with the one corresponding to your element):

tell application "BetterTouchTool"
	set appName to get_string_variable "BTTActiveAppBundleIdentifier"
	set cmd to "appChanged('" & appName & "');"
	webview_menu_item_load_html_url_js "4EF60C00-08CF-43D3-93F1-47FFBC2D2A23" javascript_to_execute cmd
end tell

This calls the appChanged() function, giving it the bundle ID of the current app. When executed, it will go through and toggle the display status of all the <div> elements which match/don’t match the condition.

It’s trivial to handle conditions like data-except-app-name which would show the content except for when the specified app is active. And you could trivially implement OR conditions by assuming multiple bundle IDs are separate by commas and adjusting the logic in the appChanged() function to suit.

So, for a BTT Mobile floating menu on an iOS device, this would allow buttons and other elements to appear / disappear depending on the currently active app on the Mac. Pretty cool!

Jason

I need to check but I think this is included with the upcoming webview scripting additions. (will probably be on Testflight early next week)

:raising_hands: Superstar!

Thank you! That’s awesome.

Might you please consider creating a function that would make it easy to generate the base64 encoding for passing image / audio / video data into a webview item? Maybe this is already trivially possible but, if not, it would be really useful.

When all this is working, I’ll write a Substack post explaining how to create a user-defined control panel in BTT Mobile using HTML on an iOS device which involves bidirectional communication. The AppleScript support is really important because that turns the BTT Mobile webview into a real-time information display panel with touch support.

Jason

1 Like