--- /dev/null
+ASSERT_PATH="$HOME/Library/DoNotDisturb/DB/Assertions.json"
+MODECONFIG_PATH="$HOME/Library/DoNotDisturb/DB/ModeConfigurations.json"
+
+###############################################################################
+#
+# USAGE:
+#
+# You can ask a script to only continue if it matches a focus mode, or to halt
+# if it encounters it. You can do this by passing pipe separated values to
+# VAR_RUN_ON_FOCUS or VAR_HALT_ON_FOCUS and then calling focus_check.
+# For example, this will only run the script if "Personal" or "Do Not Disturb"
+# are active:
+#
+# VAR_RUN_ON_FOCUS="Personal|Do Not Disturb"
+# focus_check
+#
+# And this will halt the script only if the focus is Work
+#
+# VAR_HALT_ON_FOCUS="Work"
+# focus_check
+#
+# If neither variable is set, then all checks will be disabled.
+#
+# SETUP:
+#
+# Copy focus.utils.sh to your SwiftBar directory and include it if it exists.
+#
+# if [[ -f "${BASH_SOURCE%/*}/focus.utils.sh" ]]; then
+# source "${BASH_SOURCE%/*}/focus.utils.sh"
+# focus_check
+# fi
+#
+# PERMISSIONS:
+#
+# Accessing these databases requires that SwiftBar has full disk access
+# permissions. If the checks are enabled but the database files can't be read
+# it will instead return an error with instructions on what to do.
+#
+# ADDITIONAL FUNCTIONS:
+#
+# If you need custom behavior you can use the get_focus and is_focus_active
+#
+# get_focus will return the name of the currently active focus, or an empty
+# string if there's no focus enabled.
+#
+# is_focus_active receives a pipe delimited string and will return 0 if the
+# current focus is in the list, or 1 if the current focus is not present.
+#
+###############################################################################
+# Internal Utilities
+###############################################################################
+
+_assert_permissions() {
+
+ if [[ ! -r "$ASSERT_PATH" ]] || [[ ! -r "$MODECONFIG_PATH" ]]; then
+ echo ":light.beacon.max:"
+ echo "---"
+ echo "Focus database not readable.\nAllow SwiftBar in System Settings > Privacy & Security > Full Disk Access."
+ exit 0
+ fi
+}
+
+_run_on_focus() {
+ [[ -z "${VAR_RUN_ON_FOCUS}" ]] && return 0
+ _assert_permissions
+ is_focus_active $VAR_RUN_ON_FOCUS || exit 0
+ return 0
+}
+
+_halt_on_focus() {
+ [[ -z "${VAR_HALT_ON_FOCUS}" ]] && return 0
+ _assert_permissions
+ is_focus_active $VAR_HALT_ON_FOCUS || return 0
+ exit 0
+}
+
+###############################################################################
+# Public Functions
+###############################################################################
+
+get_focus() {
+ local focus=""
+
+ # Check for active assertions
+ if [[ -f "$ASSERT_PATH" ]]; then
+ local modeid=$(jq -r '.data[0].storeAssertionRecords[0].assertionDetails.assertionDetailsModeIdentifier // empty' "$ASSERT_PATH")
+
+ if [[ -n "$modeid" ]]; then
+ focus=$(jq -r --arg mid "$modeid" '.data[0].modeConfigurations[$mid].mode.name' "$MODECONFIG_PATH")
+ echo "$focus"
+ return
+ fi
+ fi
+
+ # Calculate current time in minutes
+ local hour=$(date +%H)
+ local minute=$(date +%M)
+ local now=$((hour * 60 + minute))
+
+ # Process scheduled triggers
+ jq -r '.data[0].modeConfigurations | to_entries[] | select(.value.triggers.triggers[0] != null) |
+ select(.value.triggers.triggers[0].enabledSetting == 2) |
+ {
+ id: .key,
+ name: .value.mode.name,
+ start: (.value.triggers.triggers[0].timePeriodStartTimeHour * 60 + .value.triggers.triggers[0].timePeriodStartTimeMinute),
+ end: (.value.triggers.triggers[0].timePeriodEndTimeHour * 60 + .value.triggers.triggers[0].timePeriodEndTimeMinute)
+ } | @json' "$MODECONFIG_PATH" 2>/dev/null | while read -r line; do
+ local start=$(echo "$line" | jq -r '.start')
+ local end=$(echo "$line" | jq -r '.end')
+ local name=$(echo "$line" | jq -r '.name')
+
+ if [[ $start -lt $end ]]; then
+ if [[ $now -ge $start && $now -lt $end ]]; then
+ focus="$name"
+ break
+ fi
+ elif [[ $start -gt $end ]]; then
+ if [[ $now -ge $start || $now -lt $end ]]; then
+ focus="$name"
+ break
+ fi
+ fi
+ done
+
+ echo -n "$focus" | xargs
+}
+
+is_focus_active() {
+ local current_focus=$(get_focus)
+ [[ "$current_focus" =~ ^($1)$ ]] && return 0
+ return 1
+}
+
+focus_check() {
+ _run_on_focus
+ _halt_on_focus
+}
# <xbar.dependencies>curl,jq</xbar.dependencies>
# <xbar.abouturl>https://r.bdr.sh/swiftbar_scripts.html</xbar.abouturl>
# <xbar.var>string(VAR_MONITORCITO_URL): Your monitorcito API URL.</xbar.var>
+# <xbar.var>string(VAR_RUN_ON_FOCUS): Focus in which to run.</xbar.var>
+# <xbar.var>string(VAR_HALT_ON_FOCUS): Focus in which to halt.</xbar.var>
# <swiftbar.hideRunInTerminal>true</swiftbar.hideRunInTerminal>
-# <swiftbar.environment>VAR_MONITORCITO_URL=no</swiftbar.environment>
+# <swiftbar.environment>VAR_MONITORCITO_URL=no, VAR_RUN_ON_FOCUS=, VAR_HALT_ON_FOCUS=</swiftbar.environment>
###############################################################################
# The Variables
###############################################################################
VAR_MONITORCITO_URL=${VAR_MONITORCITO_URL:-'https://monitor.srv.bdr.sh/api'}
+VAR_RUN_ON_FOCUS=
+VAR_HALT_ON_FOCUS=
+
+###############################################################################
+# Focus Check
+###############################################################################
+
+if [[ -f "${BASH_SOURCE%/*}/focus.utils.sh" ]]; then
+ source "${BASH_SOURCE%/*}/focus.utils.sh"
+ focus_check
+fi
###############################################################################
# The Code
# <xbar.abouturl>https://r.bdr.sh/swiftbar_scripts.html</xbar.abouturl>
# <xbar.var>string(VAR_SOURCEHUT_API_TOKEN): Your sourcehut API Token.</xbar.var>
# <xbar.var>number(VAR_BUILD_COUNT=10): How many items to show.</xbar.var>
+# <xbar.var>string(VAR_RUN_ON_FOCUS): Focus in which to run.</xbar.var>
+# <xbar.var>string(VAR_HALT_ON_FOCUS): Focus in which to halt.</xbar.var>
# <swiftbar.hideRunInTerminal>true</swiftbar.hideRunInTerminal>
-# <swiftbar.environment>VAR_SOURCEHUT_API_TOKEN=no, VAR_BUILD_COUNT=9</swiftbar.environment>
+# <swiftbar.environment>VAR_SOURCEHUT_API_TOKEN=no, VAR_BUILD_COUNT=9, VAR_RUN_ON_FOCUS=, VAR_HALT_ON_FOCUS=</swiftbar.environment>
###############################################################################
# The Variables
###############################################################################
VAR_SOURCEHUT_API_TOKEN=${VAR_SOURCEHUT_API_TOKEN:-'ADD YOUR TOKEN HERE'}
VAR_BUILD_COUNT=${VAR_BUILD_COUNT:-10}
+VAR_RUN_ON_FOCUS=
+VAR_HALT_ON_FOCUS=
+
+###############################################################################
+# Focus Check
+###############################################################################
+
+if [[ -f "${BASH_SOURCE%/*}/focus.utils.sh" ]]; then
+ source "${BASH_SOURCE%/*}/focus.utils.sh"
+ focus_check
+fi
###############################################################################
# The Code