I got tired of waiting/hoping for a Focus mode on iOS, so I’ve hacked together a workaround using AppleScript and OF on the Mac. I call it “Deep Focus”, which is a dumb name, but it helps me differentiate the two.
The general idea is to select a focus area (e.g., a folder), and the script then iterates through all non-selected areas, places any Active projects in those areas On Hold, and tags them with an “Unfocused” tag. To switch back, a reset script iterates through Unfocused items and makes them Active again, then removes the tag.
I plan on using Jason Snell’s remote scripts idea to activate these scripts via Shortcuts on iPhone/iPad.
It’s not perfect, and I have a variety of improvements to make. (e.g., It should be updated to use whatever projects/folders are currently selected as the target thing to focus on—it currently relies on a prompt.)
Still, it essentially provides Focus and syncs the focus setting between platforms. This way, if my work day is haywire, I can turn on Deep Focus and all the flagged and Forecast and etc. tasks outside of my workplace projects will disappear 'til I get through it. I can then glance at my phone/iPad widget and watch and not get distracted by all the other important things I’m ignoring in lieu of looming deadlines.
The problem:
It takes maybe a minute for the script to iterate through the projects and switch them to On Hold. I’d love some suggestions on speeding it up.
The scripts
Activate Deep Focus
property pFolderList : {"Study", "Sundry", "Student Experience Office", "Home", "Defocus"}
property pDefaultFolder : "Defocus"
property pPrompt : "Deep focus setting?"
property debug : false
set resetScript to load script (POSIX file "/Users/ryanjamurphy/Library/Application Scripts/com.omnigroup.OmniFocus3/Reset Deep Focus.scpt")
tell application "OmniFocus"
activate
tell the default document
my resetScript's resetDeepFocus()
set allFolders to folders
set allProjects to flattened projects
set unfocusedTag to the first flattened tag whose name is "Unfocused"
if debug then
set folderNames to ""
repeat with eachFolder in allFolders
set folderNames to folderNames & "
" & name of eachFolder as string
end repeat
display dialog folderNames
end if
choose from list pFolderList ¬
with title "Set deep focus" with prompt pPrompt ¬
OK button name ¬
"Confirm" default items pDefaultFolder
if result is false then
return
else
set focusArea to the first folder whose name is my result
end if
repeat with eachFolder in allFolders
set focusCheck to true
set focusCheck to my checkFolder(eachFolder, focusArea)
if focusCheck is false then
if debug then
display dialog (name of eachFolder & " has been found to not be " & name of focusArea & ". We will now make each child project of the folder On Hold and add an Unfocused tag.")
end if
set theProjects to (the flattened projects of eachFolder whose status is active)
repeat with eachProject in theProjects
if debug then
display dialog (name of eachProject as string) & "'s status is " & status of eachProject & "."
end if
set eachProject's status to on hold
add unfocusedTag to the tags of eachProject
if debug then
display dialog (("Set " & name of eachProject as string) & " to On Hold. Added tag Unfocused.")
end if
end repeat
else
if debug then
display dialog "Projects in " & (name of eachFolder) & " will stay active."
end if
end if
end repeat
-- continue
end tell
end tell
-- A recursive method to see if a given folder is the focused folder. If not, return false. The main script body will then tag each active project in the given folder with "Unfocused" and set their status to On Hold.
on checkFolder(aFolder, theFocusArea)
tell application "OmniFocus"
tell default document
if debug then
display dialog (("Comparing " & name of aFolder as string) & " with " & name of theFocusArea as string) & "."
end if
if id of aFolder is equal to id of theFocusArea then
if debug then
display dialog ((name of aFolder as string) & " is the same as " & name of theFocusArea as string) & "."
end if
return true
else
return false
try
set subFolders to flattened folders of aFolder
if subFolders is not {} then
repeat with eachFolder in subFolders
set focusCheck to my checkFolder(eachFolder, theFocusArea)
return focusCheck
end repeat
end if
end try
end if
end tell
end tell
end checkFolder
Reset Deep Focus
Note: this one is a bit faster, because you can delete and re-create the Unfocused
tag to quickly remove it from all items.
property debug : false
tell application "OmniFocus"
activate
tell the default document
my resetDeepFocus()
end tell
end tell
on resetDeepFocus()
tell application "OmniFocus"
tell default document
set unfocusedTag to first flattened tag whose name is "Unfocused"
set unfocusedTasks to tasks of unfocusedTag
set unfocusedTaskCount to count of unfocusedTasks
set unfocusedTaskNames to ""
repeat with eachTask in unfocusedTasks
set unfocusedTaskNames to unfocusedTaskNames & "
" & name of eachTask
try
set theProject to the containing project of eachTask
set status of theProject to active
end try
end repeat
delete unfocusedTag
make tag with properties {name:"Unfocused"}
display alert "Deep focus has been reset. " & unfocusedTaskCount & " projects have been restored to active status."
if debug then
display dialog unfocusedTaskNames
end if
end tell
end tell
end resetDeepFocus