Do Not Disturb touchbar button nolonger reacts with Monterey

Updated to Mac OS Monterey and the Do Not Disturb touch bar button doesn't react to the changed state. The function of the button itself works but the icon on the touch bar is stuck on alternate button icon.

and help would be appreciated thanks!

Bump! Anyone?

unfortunately there is currently no way to get the do not disturb state on Monterey. If I find a way I’ll update BTT to support it, but it doesn’t look like Apple included something that can be accessed by third party apps.

Thats really unfortunate :frowning: Thanks for the reply!

Have you already looked here?
Where is the Focus Status API | Apple Developer Forums


import Intents

/// Retrieve the current authorization status: INFocusStatusAuthorizationStatus

/// Request authorization to check Focus Status
INFocusStatusCenter.default.requestAuthorization { status in
    /// Provides a INFocusStatusAuthorizationStatus

/// Check if Focus is enabled. INFocusStatusAuthorizationStatus must be .authorized

According to the documentation, it applies to iOS 15, watchOS 8.0 and Catalyst, but the corresponding API seems to be already present on macOS 12. However, I could not retrieve a status so far (return is always: false):

use framework "Foundation"

set sc to current application's INFocusStatusCenter's defaultCenter()
return sc's focusStatus's isFocused as boolean

--> false

Apparently you have to request authorization and be registered as a communication app beforehand.

Yes, the "be registered as a communication app" part is killing it for BTT unfortunately. Apple would not approve that.

Ah wait, it seems that this is an entitlement that does not need apple approval! I was doing so much with special entitlements that need Apple approval lately, I didn't think about it being an entitlement anybody could use :slight_smile:

In this case this might work, I'll have a look!


Here is an AppleScript which returns the current focus status.
If no focus is active, "No Focus" is returned (can be changed in the script). Otherwise the name of the active focus. Works also if the focus is set by a trigger (App, Schedule).

Note: If multiple schedules are stored that currently apply, the first focus that matches the schedule is returned.

use scripting additions
use framework "Foundation"
property ca : a reference to current application


--> No Focus
--> Do Not Disturb
--> Personal
--> Work
--> Sleep
--> etc…

------- handler -------

on getFocusStatus()
	set config to readJSONFile("~/Library/DoNotDisturb/DB/ModeConfigurations.json")'s |data|'s firstObject()'s modeConfigurations
	set assert to readJSONFile("~/Library/DoNotDisturb/DB/Assertions.json")'s |data|'s firstObject()
	if (assert's valueForKey:"storeAssertionRecords") is not missing value then
		return (config's valueForKey:(assert's storeAssertionRecords's firstObject()'s assertionDetails's assertionDetailsModeIdentifier))'s mode's |name| as text
		set now to ((current date)'s hours) * 60 + ((current date)'s minutes)
		repeat with k in (config's allKeys()) as list
			set configuration to (config's valueForKey:k)
			repeat with i from 0 to ((configuration's triggers's triggers's |count|()) - 1)
				set trigger to (configuration's triggers's triggers's objectAtIndex:i)
				if trigger's enabledSetting as integer is 2 then
					if (trigger's valueForKey:"timePeriodWeekdays") is not missing value then
						if (do shell script "echo $(((" & (trigger's timePeriodWeekdays as integer) & " & ((2**($(date +%u) - 1)))) != 0))") = "1" then
							set startTime to (trigger's timePeriodStartTimeHour as integer) * 60 + (trigger's timePeriodStartTimeMinute as integer)
							set endTime to (trigger's timePeriodEndTimeHour as integer) * 60 + (trigger's timePeriodEndTimeMinute as integer)
							if (startTime < endTime) then
								if now ≥ startTime and now < endTime then
									return configuration's mode's |name| as text
								end if
							else if (startTime > endTime) then
								if now ≥ startTime or now < endTime then
									return configuration's mode's |name| as text
								end if
							end if
						end if
					end if
				end if
			end repeat
		end repeat
		return "No Focus"
	end if
end getFocusStatus

on readJSONFile(filePath)
	set filePath to (ca's NSString's stringWithString:filePath)'s stringByExpandingTildeInPath()
	set theURL to ca's NSURL's fileURLWithPath:filePath
	set theData to ca's NSData's dataWithContentsOfURL:theURL
	set theString to ca's NSString's alloc()'s initWithData:theData encoding:(ca's NSUTF8StringEncoding)
	set {x, e} to ca's NSJSONSerialization's JSONObjectWithData:((ca's NSString's stringWithString:theString)'s dataUsingEncoding:(parent's NSUTF8StringEncoding)) options:0 |error|:(reference)
	return (ca's NSArray's arrayWithObject:x)'s firstObject()
end readJSONFile
1 Like

This works but something strange is going on. Using BetterTouchTool's "Toogle Do Not Disturb" action with this script does not trigger the Alternate Color Regex. The button's function itself works to toggle DND but the script only returns "Do Not Disturb" as a result if you turn on DND manually by clicking the moon -> Do Not Disturb in the menu bar.

Seems like BTT toggle is only kind of half toggling DND or something..

You are right! As far as the focus is set via the control center or a trigger (except by a schedule), then a storeAssertionRecord entry is set in the Assertions.json file. In case of a schedule, it is not set, so I go through all schedules and check if they are valid. When set by BTT, no storeAssertionRecord is set either.

I'll look later to see if I can find another meaningful entry somewhere in the files that indicates focus status.

PS: As workaround You can use a shortcut to enable the focus:

tell application "Shortcuts Events"
    run shortcut "Shortcut-Name"
end tell

Really appreciate your help with this!
shortcut workaround - not quite sure how to create a Focus Mode shortcut that toggles upon run rather than just turns on or turns off...

Apple obviously forgot that too (there is no status query)! I would create two shortcuts (Focus-On and Focus-Off) and ask the script before, which one you have to take.

Or you can use this: Toggle-Focus (Shortcut)

1 Like

Thanks so much for this

Imprint | Privacy Policy