THIS WEEK'S SPONSOR:

Concepts

Sketch, Note, Draw


How To Open iCloud Tabs In Editorial for iPad

Editorial iCloud Tabs

Editorial iCloud Tabs

I’ve always wanted to be able to access my iCloud Tabs directly from Editorial, but, unfortunately, due to the lack of an iCloud Tabs API, that’s currently not possible. Last week, however, when I linked to the iCloudTabs for Alfred project by Kevin Marchand and saw that the workflow was based on a bit of Python code, I realized that I could modify his script to find a way to make Editorial read constantly-updated iCloud Tabs from a text file.

What follows is a combination of a server-side script and an Editorial workflow to read and open iCloud Tabs within the app. The system works and I’ve been using it every day for the past week with good results.

There are some requirements:

  • A Mac capable of running a Python script in the background. I use a Mac mini with Hazel, and I tested it both on Mountain Lion and Mavericks.
  • A text file you can access with a URL. You can put this text file on your FTP server, in your Dropbox, or on a CDN. As long as it’s got a URL you can access from Editorial at the end of the process, it’s fine. I recommend using Dropbox to get started.
  • Editorial for iPad. I built the workflow for Editorial, and while it can be further modified and used in other scenarios, I won’t cover those here.

And a clarification: the script doesn’t access your iCloud credentials in any way. iCloud Tabs are stored in a .plist file on OS X, which Python can read and parse. The script doesn’t know anything about iCloud – it just reads a file that contains webpage titles and URLs, plus device names.

If you can keep a Mac running to turn your iCloud Tabs into a text file that later becomes a popover in Editorial, you’ll find the necessary scripts and workflow below.

The Python Script

The script is a simple modification of Kevin’s work, but instead of passing results to Alfred, we build a text file that stores iCloud Tabs as lines. These lines are formatted for Editorial, which means that they contain both a webpage’s title and URL, separated by a tab.

#!/usr/bin/python
import os
import shutil
import tempfile
import plistlib
import json

# Based on Kevin Marchand's iCloudTabs project for Alfred
# https://github.com/kmarchand/iCloudTabsAlfredWorkflow
# Best used in combination with Editorial for iOS
# http://omz-software.com/editorial/index.html

# The local path of the file that will store and pass URLs to Editorial or other apps
fileLocation = '~/Desktop/alltabs.txt'

def create_temporary_copy(path):
    temp_dir = tempfile.gettempdir()
    temp_path = os.path.join(temp_dir, 'safari_sync_plist_copy.plist')
    shutil.copy2(os.path.expanduser(path), temp_path)
    return temp_path


# make a temp copy of the plist file

temp_plist = create_temporary_copy(
    '~/Library/SyncedPreferences/com.apple.Safari.plist')

# Use plutil to convert binary plist to xml

os.system('plutil -convert xml1 %s' % temp_plist)


# Use plistlib to convert plist XML to a dictionary

info = plistlib.readPlist(temp_plist)

# Clean up (delete) temp file

os.remove(temp_plist)

# Pull out the device elements from the info dict for easier parsing later

devicetabs = []

for uid in info['values'].values():
    try:
        devicetabs.append([uid['value']['DeviceName'], uid['value']['Tabs']])
    except:
        pass

dev = ''

# Create string for text file
for i in range(len(devicetabs)):
	dev += '\n' + '----- ' + str(devicetabs[i][0].encode('utf-8')) + ' -----'
	for machine in devicetabs[i][1]:
		dev += '\n' + machine['Title'].encode('utf-8') + '\t' + machine['URL'].encode('utf-8')
		
# Write to file
outfile = os.path.expanduser(fileLocation)

f = open(outfile, 'w')
print >> f, dev
f.close()

All you need to do to make the script ready for your needs is change the fileLocation variable on line 14. This determines the local path of the text file (called “alltabs.txt”) that will store your iCloud Tabs. By default, the path is “~/Dropbox/alltabs.txt”.

When you’re using Safari on iOS or OS X, the convenience of iCloud Tabs is that they’re constantly updated by iCloud as you close and open tabs in the browser. I wanted to replicate that in my workflow by ensuring that the text file would always have the latest set of tabs from all iCloud-enabled devices. To do this, you need to find a way to run the script everytime the Safari’s tab file (under “~/Library/SyncedPreferences/com.apple.Safari.plist”) is changed, overwriting the text file with updated tabs.

Hazel

Hazel

For my workflow, I let Hazel do this job. Every time the .plist is changed, the text file is updated with new tabs, and because the file name is the same, its URL doesn’t change.

Reading iCloud Tabs from Editorial

In Editorial, all the app needs to do is read lines from the text file and present them in a popover. We can do so with just six actions.

Editorial

Editorial

First, Editorial needs to know where iCloud Tabs are stored in the form of a text file. Install the workflow, open the workflow editor, and change the first Set Variable action to the URL of your text file. If you keep your file in Dropbox, you want to use the direct Dropbox URL that displays the contents of the text file in a browser – Editorial will be able to read that.

With the URL, Editorial can run a simple Python script to read each tab from the text file and show all tabs in a popover. Note how the workflow removes duplicate lines from the list of iCloud Tabs – if the same URL is open on multiple devices, Editorial will only show it once.

In the popover, tabs are shown with titles under the device they belong to; to open a tab in the Editorial browser, just tap it. Unfortunately, due to Editorial’s lack of more advanced UI tools, the device names are tappable in the list too, but I made sure they stand out enough to be different from regular tabs.

Wrap-Up

There’s a probably a more elegant way to store iCloud Tabs in a file and access them with Python (JSON comes to mind), but the simple text file works fine and is fast. I’ve been using the workflow for the past week to re-open webpages I first opened on my Mac and iPhone, and I really like the convenience of having iCloud Tabs available in my text editor and research browser.

Feel free to modify the workflow above, and if you create something different off of it, I’d love to know. You can download the workflow here.

Note: The screenshot above shows a beta version of Editorial, currently in testing.

Unlock More with Club MacStories

Founded in 2015, Club MacStories has delivered exclusive content every week for over six years.

In that time, members have enjoyed nearly 400 weekly and monthly newsletters packed with more of your favorite MacStories writing as well as Club-only podcasts, eBooks, discounts on apps, icons, and services. Join today, and you’ll get everything new that we publish every week, plus access to our entire archive of back issues and downloadable perks.

The Club expanded in 2021 with Club MacStories+ and Club Premier. Club MacStories+ members enjoy even more exclusive stories, a vibrant Discord community, a rotating roster of app discounts, and more. And, with Club Premier, you get everything we offer at every Club level plus an extended, ad-free version of our podcast AppStories that is delivered early each week in high-bitrate audio.

Choose the Club plan that’s right for you:

  • Club MacStories: Weekly and monthly newsletters via email and the web that are brimming with app collections, tips, automation workflows, longform writing, a Club-only podcast, periodic giveaways, and more;
  • Club MacStories+: Everything that Club MacStories offers, plus exclusive content like Federico’s Automation Academy and John’s Macintosh Desktop Experience, a powerful web app for searching and exploring over 6 years of content and creating custom RSS feeds of Club content, an active Discord community, and a rotating collection of discounts, and more;
  • Club Premier: Everything in from our other plans and AppStories+, an extended version of our flagship podcast that’s delivered early, ad-free, and in high-bitrate audio.