├── README.md ├── infocus.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist ├── xcshareddata │ └── xcschemes │ │ └── infocus.xcscheme └── xcuserdata │ └── rea094.xcuserdatad │ └── xcschemes │ ├── infocuscli.xcscheme │ └── xcschememanagement.plist ├── infocus ├── AppDelegate.swift ├── Assets.xcassets │ ├── AccentColor.colorset │ │ └── Contents.json │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── infocus-1.png │ │ ├── infocus-2.png │ │ ├── infocus.png │ │ ├── infocus_16.png │ │ ├── install-1.png │ │ ├── install-2.png │ │ ├── install-3.png │ │ ├── install-4.png │ │ ├── install-5.png │ │ └── install.png │ └── Contents.json ├── Base.lproj │ └── MainMenu.xib ├── checkDND.swift ├── checkDNDcli.swift ├── infocus.entitlements └── plistFromData.swift ├── infocusTests └── infocusTests.swift ├── infocusUITests ├── infocusUITests.swift └── infocusUITestsLaunchTests.swift └── infocuscli └── main.swift /README.md: -------------------------------------------------------------------------------- 1 | # infocus 2 | 3 | [![swift-version](https://img.shields.io/badge/Swift-5.0-brightgreen)](https://developer.apple.com/documentation/swift) ![macos-version](https://img.shields.io/badge/macOS-11+-blue) [![xcode-version](https://img.shields.io/badge/xcode-13.1-red)](https://developer.apple.com/xcode/) 4 | 5 | ![install](https://user-images.githubusercontent.com/3598965/133254387-74923520-32c7-48c2-ad98-916ab2f77ad3.png) 6 | 7 | ## What 8 | 9 | Small app for Mac Admins that checks focus status under macOS 11 and 12 and can be used to add Do Not Disturb support to management scripts. 10 | 11 | Infocus runs from the command line. If the user has a Focus mode set, infocus exits with code 1, otherwise exits with code 0 12 | 13 | For a pre-built preview, check the [Releases](https://github.com/bartreardon/infocus/releases) page. 14 | 15 | ## Why 16 | 17 | Because you're a nice #MacAdmin that doesn't want to disturb your users with some popup or other event that ordinarily wouldn't adhere to macOS Notification framework. 18 | 19 | ## How 20 | 21 | Through the Magic of Swift! on macOS 11 it reads a local plist to get DND data. Under macOS 12 it uses the communications notifications entitlements but because of app sandbox rules that come with adding the entitlements, required for macOS 12, there is a seperate `infocuscli` binary included in the app bundle for use on macOS 11. Within the sandbox the app can't read the local plist. Fun. 22 | 23 | 24 | ## Demo 25 | 26 | The following script will run the correct version for the OS, check focus state and exit if focus/DND is enabled 27 | 28 | ```zsh 29 | #!/bin/zsh 30 | 31 | infocusapppath="/Applications/Utilities/infocus.app" 32 | 33 | autoload is-at-least 34 | if is-at-least 12.0 $(sw_vers -productVersion); then 35 | infocus="${infocusapppath}/Contents/MacOS/infocus" 36 | else 37 | infocus="${infocusapppath}/Contents/Resources/infocuscli" 38 | fi 39 | 40 | # Running Infocus - if DND is enabled (i.e. exit code is 1), then exit 41 | if [[ -e ${infocus} ]]; then 42 | ${infocus} || exit 0 43 | else 44 | echo "Infocus is not installed - Do Not Disturb preferences will not be considered" 45 | fi 46 | 47 | # ... continuing with the rest of the script if focus/DND is not enabled. 48 | # ... 49 | 50 | ``` 51 | 52 | ## Compiling 53 | 54 | Requires Xcode 13.1 or newer, which includes the correct frameworks for macOS 12. 55 | 56 | After building, run `codesign --force --deep --sign - infocus.app` on the app bundle to fix the signature for distribution. 57 | -------------------------------------------------------------------------------- /infocus.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 54; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 414B9ABC26F587FD000505B3 /* main.swift in Sources */ = {isa = PBXBuildFile; fileRef = 414B9AB526F58671000505B3 /* main.swift */; }; 11 | 414B9ABE26F5C423000505B3 /* checkDNDcli.swift in Sources */ = {isa = PBXBuildFile; fileRef = 414B9ABD26F5C423000505B3 /* checkDNDcli.swift */; }; 12 | 414B9AC026F5C492000505B3 /* plistFromData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 414B9ABF26F5C492000505B3 /* plistFromData.swift */; }; 13 | 414B9AC126F5C492000505B3 /* plistFromData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 414B9ABF26F5C492000505B3 /* plistFromData.swift */; }; 14 | 4166B65726F0C4F20050ED29 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4166B65626F0C4F20050ED29 /* Assets.xcassets */; }; 15 | 41A426852722232300DB91CA /* infocuscli in Resources */ = {isa = PBXBuildFile; fileRef = 414B9AB326F58671000505B3 /* infocuscli */; }; 16 | 41BA9EBE26F0C07500A78F80 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BA9EBD26F0C07500A78F80 /* AppDelegate.swift */; }; 17 | 41BA9EC326F0C07500A78F80 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 41BA9EC126F0C07500A78F80 /* MainMenu.xib */; }; 18 | 41BA9ECD26F0C07500A78F80 /* infocusTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BA9ECC26F0C07500A78F80 /* infocusTests.swift */; }; 19 | 41BA9ED726F0C07500A78F80 /* infocusUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BA9ED626F0C07500A78F80 /* infocusUITests.swift */; }; 20 | 41BA9ED926F0C07500A78F80 /* infocusUITestsLaunchTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BA9ED826F0C07500A78F80 /* infocusUITestsLaunchTests.swift */; }; 21 | 41BA9EE726F0C0A100A78F80 /* checkDND.swift in Sources */ = {isa = PBXBuildFile; fileRef = 41BA9EE626F0C0A100A78F80 /* checkDND.swift */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 41BA9EC926F0C07500A78F80 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 41BA9EB226F0C07500A78F80 /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 41BA9EB926F0C07500A78F80; 30 | remoteInfo = infocus; 31 | }; 32 | 41BA9ED326F0C07500A78F80 /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = 41BA9EB226F0C07500A78F80 /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = 41BA9EB926F0C07500A78F80; 37 | remoteInfo = infocus; 38 | }; 39 | /* End PBXContainerItemProxy section */ 40 | 41 | /* Begin PBXCopyFilesBuildPhase section */ 42 | 414B9AB126F58671000505B3 /* CopyFiles */ = { 43 | isa = PBXCopyFilesBuildPhase; 44 | buildActionMask = 2147483647; 45 | dstPath = /usr/share/man/man1/; 46 | dstSubfolderSpec = 0; 47 | files = ( 48 | ); 49 | runOnlyForDeploymentPostprocessing = 1; 50 | }; 51 | /* End PBXCopyFilesBuildPhase section */ 52 | 53 | /* Begin PBXFileReference section */ 54 | 414B9AB326F58671000505B3 /* infocuscli */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = infocuscli; sourceTree = BUILT_PRODUCTS_DIR; }; 55 | 414B9AB526F58671000505B3 /* main.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = main.swift; sourceTree = ""; }; 56 | 414B9ABD26F5C423000505B3 /* checkDNDcli.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = checkDNDcli.swift; sourceTree = ""; }; 57 | 414B9ABF26F5C492000505B3 /* plistFromData.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = plistFromData.swift; sourceTree = ""; }; 58 | 4166B65626F0C4F20050ED29 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 59 | 41BA9EBA26F0C07500A78F80 /* infocus.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = infocus.app; sourceTree = BUILT_PRODUCTS_DIR; }; 60 | 41BA9EBD26F0C07500A78F80 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 61 | 41BA9EC226F0C07500A78F80 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 62 | 41BA9EC826F0C07500A78F80 /* infocusTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = infocusTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 63 | 41BA9ECC26F0C07500A78F80 /* infocusTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = infocusTests.swift; sourceTree = ""; }; 64 | 41BA9ED226F0C07500A78F80 /* infocusUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = infocusUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 65 | 41BA9ED626F0C07500A78F80 /* infocusUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = infocusUITests.swift; sourceTree = ""; }; 66 | 41BA9ED826F0C07500A78F80 /* infocusUITestsLaunchTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = infocusUITestsLaunchTests.swift; sourceTree = ""; }; 67 | 41BA9EE526F0C08800A78F80 /* infocus.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = infocus.entitlements; sourceTree = ""; }; 68 | 41BA9EE626F0C0A100A78F80 /* checkDND.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = checkDND.swift; sourceTree = ""; }; 69 | /* End PBXFileReference section */ 70 | 71 | /* Begin PBXFrameworksBuildPhase section */ 72 | 414B9AB026F58671000505B3 /* Frameworks */ = { 73 | isa = PBXFrameworksBuildPhase; 74 | buildActionMask = 2147483647; 75 | files = ( 76 | ); 77 | runOnlyForDeploymentPostprocessing = 0; 78 | }; 79 | 41BA9EB726F0C07500A78F80 /* Frameworks */ = { 80 | isa = PBXFrameworksBuildPhase; 81 | buildActionMask = 2147483647; 82 | files = ( 83 | ); 84 | runOnlyForDeploymentPostprocessing = 0; 85 | }; 86 | 41BA9EC526F0C07500A78F80 /* Frameworks */ = { 87 | isa = PBXFrameworksBuildPhase; 88 | buildActionMask = 2147483647; 89 | files = ( 90 | ); 91 | runOnlyForDeploymentPostprocessing = 0; 92 | }; 93 | 41BA9ECF26F0C07500A78F80 /* Frameworks */ = { 94 | isa = PBXFrameworksBuildPhase; 95 | buildActionMask = 2147483647; 96 | files = ( 97 | ); 98 | runOnlyForDeploymentPostprocessing = 0; 99 | }; 100 | /* End PBXFrameworksBuildPhase section */ 101 | 102 | /* Begin PBXGroup section */ 103 | 414B9AB426F58671000505B3 /* infocuscli */ = { 104 | isa = PBXGroup; 105 | children = ( 106 | 414B9AB526F58671000505B3 /* main.swift */, 107 | ); 108 | path = infocuscli; 109 | sourceTree = ""; 110 | }; 111 | 41BA9EB126F0C07500A78F80 = { 112 | isa = PBXGroup; 113 | children = ( 114 | 41BA9EBC26F0C07500A78F80 /* infocus */, 115 | 41BA9ECB26F0C07500A78F80 /* infocusTests */, 116 | 41BA9ED526F0C07500A78F80 /* infocusUITests */, 117 | 414B9AB426F58671000505B3 /* infocuscli */, 118 | 41BA9EBB26F0C07500A78F80 /* Products */, 119 | ); 120 | sourceTree = ""; 121 | }; 122 | 41BA9EBB26F0C07500A78F80 /* Products */ = { 123 | isa = PBXGroup; 124 | children = ( 125 | 41BA9EBA26F0C07500A78F80 /* infocus.app */, 126 | 41BA9EC826F0C07500A78F80 /* infocusTests.xctest */, 127 | 41BA9ED226F0C07500A78F80 /* infocusUITests.xctest */, 128 | 414B9AB326F58671000505B3 /* infocuscli */, 129 | ); 130 | name = Products; 131 | sourceTree = ""; 132 | }; 133 | 41BA9EBC26F0C07500A78F80 /* infocus */ = { 134 | isa = PBXGroup; 135 | children = ( 136 | 41BA9EE526F0C08800A78F80 /* infocus.entitlements */, 137 | 41BA9EBD26F0C07500A78F80 /* AppDelegate.swift */, 138 | 4166B65626F0C4F20050ED29 /* Assets.xcassets */, 139 | 41BA9EC126F0C07500A78F80 /* MainMenu.xib */, 140 | 41BA9EE626F0C0A100A78F80 /* checkDND.swift */, 141 | 414B9ABF26F5C492000505B3 /* plistFromData.swift */, 142 | 414B9ABD26F5C423000505B3 /* checkDNDcli.swift */, 143 | ); 144 | path = infocus; 145 | sourceTree = ""; 146 | }; 147 | 41BA9ECB26F0C07500A78F80 /* infocusTests */ = { 148 | isa = PBXGroup; 149 | children = ( 150 | 41BA9ECC26F0C07500A78F80 /* infocusTests.swift */, 151 | ); 152 | path = infocusTests; 153 | sourceTree = ""; 154 | }; 155 | 41BA9ED526F0C07500A78F80 /* infocusUITests */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 41BA9ED626F0C07500A78F80 /* infocusUITests.swift */, 159 | 41BA9ED826F0C07500A78F80 /* infocusUITestsLaunchTests.swift */, 160 | ); 161 | path = infocusUITests; 162 | sourceTree = ""; 163 | }; 164 | /* End PBXGroup section */ 165 | 166 | /* Begin PBXNativeTarget section */ 167 | 414B9AB226F58671000505B3 /* infocuscli */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = 414B9AB926F58671000505B3 /* Build configuration list for PBXNativeTarget "infocuscli" */; 170 | buildPhases = ( 171 | 414B9AAF26F58671000505B3 /* Sources */, 172 | 414B9AB026F58671000505B3 /* Frameworks */, 173 | 414B9AB126F58671000505B3 /* CopyFiles */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | ); 179 | name = infocuscli; 180 | productName = infocuscli; 181 | productReference = 414B9AB326F58671000505B3 /* infocuscli */; 182 | productType = "com.apple.product-type.tool"; 183 | }; 184 | 41BA9EB926F0C07500A78F80 /* infocus */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = 41BA9EDC26F0C07500A78F80 /* Build configuration list for PBXNativeTarget "infocus" */; 187 | buildPhases = ( 188 | 41BA9EB626F0C07500A78F80 /* Sources */, 189 | 41BA9EB726F0C07500A78F80 /* Frameworks */, 190 | 41BA9EB826F0C07500A78F80 /* Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | ); 196 | name = infocus; 197 | productName = infocus; 198 | productReference = 41BA9EBA26F0C07500A78F80 /* infocus.app */; 199 | productType = "com.apple.product-type.application"; 200 | }; 201 | 41BA9EC726F0C07500A78F80 /* infocusTests */ = { 202 | isa = PBXNativeTarget; 203 | buildConfigurationList = 41BA9EDF26F0C07500A78F80 /* Build configuration list for PBXNativeTarget "infocusTests" */; 204 | buildPhases = ( 205 | 41BA9EC426F0C07500A78F80 /* Sources */, 206 | 41BA9EC526F0C07500A78F80 /* Frameworks */, 207 | 41BA9EC626F0C07500A78F80 /* Resources */, 208 | ); 209 | buildRules = ( 210 | ); 211 | dependencies = ( 212 | 41BA9ECA26F0C07500A78F80 /* PBXTargetDependency */, 213 | ); 214 | name = infocusTests; 215 | productName = infocusTests; 216 | productReference = 41BA9EC826F0C07500A78F80 /* infocusTests.xctest */; 217 | productType = "com.apple.product-type.bundle.unit-test"; 218 | }; 219 | 41BA9ED126F0C07500A78F80 /* infocusUITests */ = { 220 | isa = PBXNativeTarget; 221 | buildConfigurationList = 41BA9EE226F0C07500A78F80 /* Build configuration list for PBXNativeTarget "infocusUITests" */; 222 | buildPhases = ( 223 | 41BA9ECE26F0C07500A78F80 /* Sources */, 224 | 41BA9ECF26F0C07500A78F80 /* Frameworks */, 225 | 41BA9ED026F0C07500A78F80 /* Resources */, 226 | ); 227 | buildRules = ( 228 | ); 229 | dependencies = ( 230 | 41BA9ED426F0C07500A78F80 /* PBXTargetDependency */, 231 | ); 232 | name = infocusUITests; 233 | productName = infocusUITests; 234 | productReference = 41BA9ED226F0C07500A78F80 /* infocusUITests.xctest */; 235 | productType = "com.apple.product-type.bundle.ui-testing"; 236 | }; 237 | /* End PBXNativeTarget section */ 238 | 239 | /* Begin PBXProject section */ 240 | 41BA9EB226F0C07500A78F80 /* Project object */ = { 241 | isa = PBXProject; 242 | attributes = { 243 | BuildIndependentTargetsInParallel = 1; 244 | LastSwiftUpdateCheck = 1300; 245 | LastUpgradeCheck = 1300; 246 | TargetAttributes = { 247 | 414B9AB226F58671000505B3 = { 248 | CreatedOnToolsVersion = 13.0; 249 | }; 250 | 41BA9EB926F0C07500A78F80 = { 251 | CreatedOnToolsVersion = 13.0; 252 | }; 253 | 41BA9EC726F0C07500A78F80 = { 254 | CreatedOnToolsVersion = 13.0; 255 | TestTargetID = 41BA9EB926F0C07500A78F80; 256 | }; 257 | 41BA9ED126F0C07500A78F80 = { 258 | CreatedOnToolsVersion = 13.0; 259 | TestTargetID = 41BA9EB926F0C07500A78F80; 260 | }; 261 | }; 262 | }; 263 | buildConfigurationList = 41BA9EB526F0C07500A78F80 /* Build configuration list for PBXProject "infocus" */; 264 | compatibilityVersion = "Xcode 12.0"; 265 | developmentRegion = en; 266 | hasScannedForEncodings = 0; 267 | knownRegions = ( 268 | en, 269 | Base, 270 | ); 271 | mainGroup = 41BA9EB126F0C07500A78F80; 272 | productRefGroup = 41BA9EBB26F0C07500A78F80 /* Products */; 273 | projectDirPath = ""; 274 | projectRoot = ""; 275 | targets = ( 276 | 41BA9EB926F0C07500A78F80 /* infocus */, 277 | 41BA9EC726F0C07500A78F80 /* infocusTests */, 278 | 41BA9ED126F0C07500A78F80 /* infocusUITests */, 279 | 414B9AB226F58671000505B3 /* infocuscli */, 280 | ); 281 | }; 282 | /* End PBXProject section */ 283 | 284 | /* Begin PBXResourcesBuildPhase section */ 285 | 41BA9EB826F0C07500A78F80 /* Resources */ = { 286 | isa = PBXResourcesBuildPhase; 287 | buildActionMask = 2147483647; 288 | files = ( 289 | 41A426852722232300DB91CA /* infocuscli in Resources */, 290 | 4166B65726F0C4F20050ED29 /* Assets.xcassets in Resources */, 291 | 41BA9EC326F0C07500A78F80 /* MainMenu.xib in Resources */, 292 | ); 293 | runOnlyForDeploymentPostprocessing = 0; 294 | }; 295 | 41BA9EC626F0C07500A78F80 /* Resources */ = { 296 | isa = PBXResourcesBuildPhase; 297 | buildActionMask = 2147483647; 298 | files = ( 299 | ); 300 | runOnlyForDeploymentPostprocessing = 0; 301 | }; 302 | 41BA9ED026F0C07500A78F80 /* Resources */ = { 303 | isa = PBXResourcesBuildPhase; 304 | buildActionMask = 2147483647; 305 | files = ( 306 | ); 307 | runOnlyForDeploymentPostprocessing = 0; 308 | }; 309 | /* End PBXResourcesBuildPhase section */ 310 | 311 | /* Begin PBXSourcesBuildPhase section */ 312 | 414B9AAF26F58671000505B3 /* Sources */ = { 313 | isa = PBXSourcesBuildPhase; 314 | buildActionMask = 2147483647; 315 | files = ( 316 | 414B9ABC26F587FD000505B3 /* main.swift in Sources */, 317 | 414B9AC126F5C492000505B3 /* plistFromData.swift in Sources */, 318 | 414B9ABE26F5C423000505B3 /* checkDNDcli.swift in Sources */, 319 | ); 320 | runOnlyForDeploymentPostprocessing = 0; 321 | }; 322 | 41BA9EB626F0C07500A78F80 /* Sources */ = { 323 | isa = PBXSourcesBuildPhase; 324 | buildActionMask = 2147483647; 325 | files = ( 326 | 41BA9EBE26F0C07500A78F80 /* AppDelegate.swift in Sources */, 327 | 414B9AC026F5C492000505B3 /* plistFromData.swift in Sources */, 328 | 41BA9EE726F0C0A100A78F80 /* checkDND.swift in Sources */, 329 | ); 330 | runOnlyForDeploymentPostprocessing = 0; 331 | }; 332 | 41BA9EC426F0C07500A78F80 /* Sources */ = { 333 | isa = PBXSourcesBuildPhase; 334 | buildActionMask = 2147483647; 335 | files = ( 336 | 41BA9ECD26F0C07500A78F80 /* infocusTests.swift in Sources */, 337 | ); 338 | runOnlyForDeploymentPostprocessing = 0; 339 | }; 340 | 41BA9ECE26F0C07500A78F80 /* Sources */ = { 341 | isa = PBXSourcesBuildPhase; 342 | buildActionMask = 2147483647; 343 | files = ( 344 | 41BA9ED926F0C07500A78F80 /* infocusUITestsLaunchTests.swift in Sources */, 345 | 41BA9ED726F0C07500A78F80 /* infocusUITests.swift in Sources */, 346 | ); 347 | runOnlyForDeploymentPostprocessing = 0; 348 | }; 349 | /* End PBXSourcesBuildPhase section */ 350 | 351 | /* Begin PBXTargetDependency section */ 352 | 41BA9ECA26F0C07500A78F80 /* PBXTargetDependency */ = { 353 | isa = PBXTargetDependency; 354 | target = 41BA9EB926F0C07500A78F80 /* infocus */; 355 | targetProxy = 41BA9EC926F0C07500A78F80 /* PBXContainerItemProxy */; 356 | }; 357 | 41BA9ED426F0C07500A78F80 /* PBXTargetDependency */ = { 358 | isa = PBXTargetDependency; 359 | target = 41BA9EB926F0C07500A78F80 /* infocus */; 360 | targetProxy = 41BA9ED326F0C07500A78F80 /* PBXContainerItemProxy */; 361 | }; 362 | /* End PBXTargetDependency section */ 363 | 364 | /* Begin PBXVariantGroup section */ 365 | 41BA9EC126F0C07500A78F80 /* MainMenu.xib */ = { 366 | isa = PBXVariantGroup; 367 | children = ( 368 | 41BA9EC226F0C07500A78F80 /* Base */, 369 | ); 370 | name = MainMenu.xib; 371 | sourceTree = ""; 372 | }; 373 | /* End PBXVariantGroup section */ 374 | 375 | /* Begin XCBuildConfiguration section */ 376 | 414B9AB726F58671000505B3 /* Debug */ = { 377 | isa = XCBuildConfiguration; 378 | buildSettings = { 379 | CODE_SIGN_STYLE = Automatic; 380 | DEVELOPMENT_TEAM = N8GJ2Y5Z9T; 381 | ENABLE_HARDENED_RUNTIME = YES; 382 | MACOSX_DEPLOYMENT_TARGET = 10.15; 383 | PRODUCT_NAME = "$(TARGET_NAME)"; 384 | SWIFT_VERSION = 5.0; 385 | }; 386 | name = Debug; 387 | }; 388 | 414B9AB826F58671000505B3 /* Release */ = { 389 | isa = XCBuildConfiguration; 390 | buildSettings = { 391 | CODE_SIGN_STYLE = Automatic; 392 | DEVELOPMENT_TEAM = N8GJ2Y5Z9T; 393 | ENABLE_HARDENED_RUNTIME = YES; 394 | MACOSX_DEPLOYMENT_TARGET = 10.15; 395 | PRODUCT_NAME = "$(TARGET_NAME)"; 396 | SWIFT_VERSION = 5.0; 397 | }; 398 | name = Release; 399 | }; 400 | 41BA9EDA26F0C07500A78F80 /* Debug */ = { 401 | isa = XCBuildConfiguration; 402 | buildSettings = { 403 | ALWAYS_SEARCH_USER_PATHS = NO; 404 | CLANG_ANALYZER_NONNULL = YES; 405 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 406 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 407 | CLANG_CXX_LIBRARY = "libc++"; 408 | CLANG_ENABLE_MODULES = YES; 409 | CLANG_ENABLE_OBJC_ARC = YES; 410 | CLANG_ENABLE_OBJC_WEAK = YES; 411 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 412 | CLANG_WARN_BOOL_CONVERSION = YES; 413 | CLANG_WARN_COMMA = YES; 414 | CLANG_WARN_CONSTANT_CONVERSION = YES; 415 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 416 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 417 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 418 | CLANG_WARN_EMPTY_BODY = YES; 419 | CLANG_WARN_ENUM_CONVERSION = YES; 420 | CLANG_WARN_INFINITE_RECURSION = YES; 421 | CLANG_WARN_INT_CONVERSION = YES; 422 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 423 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 424 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 425 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 426 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 427 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 428 | CLANG_WARN_STRICT_PROTOTYPES = YES; 429 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 430 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 431 | CLANG_WARN_UNREACHABLE_CODE = YES; 432 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 433 | COPY_PHASE_STRIP = NO; 434 | DEBUG_INFORMATION_FORMAT = dwarf; 435 | ENABLE_STRICT_OBJC_MSGSEND = YES; 436 | ENABLE_TESTABILITY = YES; 437 | GCC_C_LANGUAGE_STANDARD = gnu11; 438 | GCC_DYNAMIC_NO_PIC = NO; 439 | GCC_NO_COMMON_BLOCKS = YES; 440 | GCC_OPTIMIZATION_LEVEL = 0; 441 | GCC_PREPROCESSOR_DEFINITIONS = ( 442 | "DEBUG=1", 443 | "$(inherited)", 444 | ); 445 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 446 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 447 | GCC_WARN_UNDECLARED_SELECTOR = YES; 448 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 449 | GCC_WARN_UNUSED_FUNCTION = YES; 450 | GCC_WARN_UNUSED_VARIABLE = YES; 451 | MACOSX_DEPLOYMENT_TARGET = 12.0; 452 | MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE; 453 | MTL_FAST_MATH = YES; 454 | ONLY_ACTIVE_ARCH = YES; 455 | SDKROOT = macosx; 456 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 457 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 458 | }; 459 | name = Debug; 460 | }; 461 | 41BA9EDB26F0C07500A78F80 /* Release */ = { 462 | isa = XCBuildConfiguration; 463 | buildSettings = { 464 | ALWAYS_SEARCH_USER_PATHS = NO; 465 | CLANG_ANALYZER_NONNULL = YES; 466 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 467 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++17"; 468 | CLANG_CXX_LIBRARY = "libc++"; 469 | CLANG_ENABLE_MODULES = YES; 470 | CLANG_ENABLE_OBJC_ARC = YES; 471 | CLANG_ENABLE_OBJC_WEAK = YES; 472 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 473 | CLANG_WARN_BOOL_CONVERSION = YES; 474 | CLANG_WARN_COMMA = YES; 475 | CLANG_WARN_CONSTANT_CONVERSION = YES; 476 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 477 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 478 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 479 | CLANG_WARN_EMPTY_BODY = YES; 480 | CLANG_WARN_ENUM_CONVERSION = YES; 481 | CLANG_WARN_INFINITE_RECURSION = YES; 482 | CLANG_WARN_INT_CONVERSION = YES; 483 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 484 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 485 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 486 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 487 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; 488 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 489 | CLANG_WARN_STRICT_PROTOTYPES = YES; 490 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 491 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 492 | CLANG_WARN_UNREACHABLE_CODE = YES; 493 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 494 | COPY_PHASE_STRIP = NO; 495 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 496 | ENABLE_NS_ASSERTIONS = NO; 497 | ENABLE_STRICT_OBJC_MSGSEND = YES; 498 | GCC_C_LANGUAGE_STANDARD = gnu11; 499 | GCC_NO_COMMON_BLOCKS = YES; 500 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 501 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 502 | GCC_WARN_UNDECLARED_SELECTOR = YES; 503 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 504 | GCC_WARN_UNUSED_FUNCTION = YES; 505 | GCC_WARN_UNUSED_VARIABLE = YES; 506 | MACOSX_DEPLOYMENT_TARGET = 12.0; 507 | MTL_ENABLE_DEBUG_INFO = NO; 508 | MTL_FAST_MATH = YES; 509 | SDKROOT = macosx; 510 | SWIFT_COMPILATION_MODE = wholemodule; 511 | SWIFT_OPTIMIZATION_LEVEL = "-O"; 512 | }; 513 | name = Release; 514 | }; 515 | 41BA9EDD26F0C07500A78F80 /* Debug */ = { 516 | isa = XCBuildConfiguration; 517 | buildSettings = { 518 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 519 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 520 | CODE_SIGN_ENTITLEMENTS = infocus/infocus.entitlements; 521 | CODE_SIGN_STYLE = Automatic; 522 | COMBINE_HIDPI_IMAGES = YES; 523 | CURRENT_PROJECT_VERSION = 1; 524 | DEVELOPMENT_TEAM = N8GJ2Y5Z9T; 525 | ENABLE_APP_SANDBOX = YES; 526 | ENABLE_HARDENED_RUNTIME = YES; 527 | ENABLE_USER_SELECTED_FILES = readonly; 528 | GENERATE_INFOPLIST_FILE = YES; 529 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 530 | INFOPLIST_KEY_NSMainNibFile = MainMenu; 531 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 532 | LD_RUNPATH_SEARCH_PATHS = ( 533 | "$(inherited)", 534 | "@executable_path/../Frameworks", 535 | ); 536 | MACOSX_DEPLOYMENT_TARGET = 10.15; 537 | MARKETING_VERSION = 0.1; 538 | PRODUCT_BUNDLE_IDENTIFIER = au.csiro.infocus; 539 | PRODUCT_NAME = "$(TARGET_NAME)"; 540 | SWIFT_EMIT_LOC_STRINGS = YES; 541 | SWIFT_VERSION = 5.0; 542 | }; 543 | name = Debug; 544 | }; 545 | 41BA9EDE26F0C07500A78F80 /* Release */ = { 546 | isa = XCBuildConfiguration; 547 | buildSettings = { 548 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 549 | ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor; 550 | CODE_SIGN_ENTITLEMENTS = infocus/infocus.entitlements; 551 | CODE_SIGN_STYLE = Automatic; 552 | COMBINE_HIDPI_IMAGES = YES; 553 | CURRENT_PROJECT_VERSION = 1; 554 | DEVELOPMENT_TEAM = N8GJ2Y5Z9T; 555 | ENABLE_APP_SANDBOX = YES; 556 | ENABLE_HARDENED_RUNTIME = YES; 557 | ENABLE_USER_SELECTED_FILES = readonly; 558 | GENERATE_INFOPLIST_FILE = YES; 559 | INFOPLIST_KEY_NSHumanReadableCopyright = ""; 560 | INFOPLIST_KEY_NSMainNibFile = MainMenu; 561 | INFOPLIST_KEY_NSPrincipalClass = NSApplication; 562 | LD_RUNPATH_SEARCH_PATHS = ( 563 | "$(inherited)", 564 | "@executable_path/../Frameworks", 565 | ); 566 | MACOSX_DEPLOYMENT_TARGET = 10.15; 567 | MARKETING_VERSION = 0.1; 568 | PRODUCT_BUNDLE_IDENTIFIER = au.csiro.infocus; 569 | PRODUCT_NAME = "$(TARGET_NAME)"; 570 | SWIFT_EMIT_LOC_STRINGS = YES; 571 | SWIFT_VERSION = 5.0; 572 | }; 573 | name = Release; 574 | }; 575 | 41BA9EE026F0C07500A78F80 /* Debug */ = { 576 | isa = XCBuildConfiguration; 577 | buildSettings = { 578 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 579 | BUNDLE_LOADER = "$(TEST_HOST)"; 580 | CODE_SIGN_STYLE = Automatic; 581 | COMBINE_HIDPI_IMAGES = YES; 582 | CURRENT_PROJECT_VERSION = 1; 583 | DEVELOPMENT_TEAM = N8GJ2Y5Z9T; 584 | GENERATE_INFOPLIST_FILE = YES; 585 | LD_RUNPATH_SEARCH_PATHS = ( 586 | "$(inherited)", 587 | "@executable_path/../Frameworks", 588 | "@loader_path/../Frameworks", 589 | ); 590 | MACOSX_DEPLOYMENT_TARGET = 12.0; 591 | MARKETING_VERSION = 1.0; 592 | PRODUCT_BUNDLE_IDENTIFIER = au.csiro.infocusTests; 593 | PRODUCT_NAME = "$(TARGET_NAME)"; 594 | SWIFT_EMIT_LOC_STRINGS = NO; 595 | SWIFT_VERSION = 5.0; 596 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/infocus.app/Contents/MacOS/infocus"; 597 | }; 598 | name = Debug; 599 | }; 600 | 41BA9EE126F0C07500A78F80 /* Release */ = { 601 | isa = XCBuildConfiguration; 602 | buildSettings = { 603 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 604 | BUNDLE_LOADER = "$(TEST_HOST)"; 605 | CODE_SIGN_STYLE = Automatic; 606 | COMBINE_HIDPI_IMAGES = YES; 607 | CURRENT_PROJECT_VERSION = 1; 608 | DEVELOPMENT_TEAM = N8GJ2Y5Z9T; 609 | GENERATE_INFOPLIST_FILE = YES; 610 | LD_RUNPATH_SEARCH_PATHS = ( 611 | "$(inherited)", 612 | "@executable_path/../Frameworks", 613 | "@loader_path/../Frameworks", 614 | ); 615 | MACOSX_DEPLOYMENT_TARGET = 12.0; 616 | MARKETING_VERSION = 1.0; 617 | PRODUCT_BUNDLE_IDENTIFIER = au.csiro.infocusTests; 618 | PRODUCT_NAME = "$(TARGET_NAME)"; 619 | SWIFT_EMIT_LOC_STRINGS = NO; 620 | SWIFT_VERSION = 5.0; 621 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/infocus.app/Contents/MacOS/infocus"; 622 | }; 623 | name = Release; 624 | }; 625 | 41BA9EE326F0C07500A78F80 /* Debug */ = { 626 | isa = XCBuildConfiguration; 627 | buildSettings = { 628 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 629 | CODE_SIGN_STYLE = Automatic; 630 | COMBINE_HIDPI_IMAGES = YES; 631 | CURRENT_PROJECT_VERSION = 1; 632 | DEVELOPMENT_TEAM = N8GJ2Y5Z9T; 633 | GENERATE_INFOPLIST_FILE = YES; 634 | LD_RUNPATH_SEARCH_PATHS = ( 635 | "$(inherited)", 636 | "@executable_path/../Frameworks", 637 | "@loader_path/../Frameworks", 638 | ); 639 | MARKETING_VERSION = 1.0; 640 | PRODUCT_BUNDLE_IDENTIFIER = au.csiro.infocusUITests; 641 | PRODUCT_NAME = "$(TARGET_NAME)"; 642 | SWIFT_EMIT_LOC_STRINGS = NO; 643 | SWIFT_VERSION = 5.0; 644 | TEST_TARGET_NAME = infocus; 645 | }; 646 | name = Debug; 647 | }; 648 | 41BA9EE426F0C07500A78F80 /* Release */ = { 649 | isa = XCBuildConfiguration; 650 | buildSettings = { 651 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 652 | CODE_SIGN_STYLE = Automatic; 653 | COMBINE_HIDPI_IMAGES = YES; 654 | CURRENT_PROJECT_VERSION = 1; 655 | DEVELOPMENT_TEAM = N8GJ2Y5Z9T; 656 | GENERATE_INFOPLIST_FILE = YES; 657 | LD_RUNPATH_SEARCH_PATHS = ( 658 | "$(inherited)", 659 | "@executable_path/../Frameworks", 660 | "@loader_path/../Frameworks", 661 | ); 662 | MARKETING_VERSION = 1.0; 663 | PRODUCT_BUNDLE_IDENTIFIER = au.csiro.infocusUITests; 664 | PRODUCT_NAME = "$(TARGET_NAME)"; 665 | SWIFT_EMIT_LOC_STRINGS = NO; 666 | SWIFT_VERSION = 5.0; 667 | TEST_TARGET_NAME = infocus; 668 | }; 669 | name = Release; 670 | }; 671 | /* End XCBuildConfiguration section */ 672 | 673 | /* Begin XCConfigurationList section */ 674 | 414B9AB926F58671000505B3 /* Build configuration list for PBXNativeTarget "infocuscli" */ = { 675 | isa = XCConfigurationList; 676 | buildConfigurations = ( 677 | 414B9AB726F58671000505B3 /* Debug */, 678 | 414B9AB826F58671000505B3 /* Release */, 679 | ); 680 | defaultConfigurationIsVisible = 0; 681 | defaultConfigurationName = Release; 682 | }; 683 | 41BA9EB526F0C07500A78F80 /* Build configuration list for PBXProject "infocus" */ = { 684 | isa = XCConfigurationList; 685 | buildConfigurations = ( 686 | 41BA9EDA26F0C07500A78F80 /* Debug */, 687 | 41BA9EDB26F0C07500A78F80 /* Release */, 688 | ); 689 | defaultConfigurationIsVisible = 0; 690 | defaultConfigurationName = Release; 691 | }; 692 | 41BA9EDC26F0C07500A78F80 /* Build configuration list for PBXNativeTarget "infocus" */ = { 693 | isa = XCConfigurationList; 694 | buildConfigurations = ( 695 | 41BA9EDD26F0C07500A78F80 /* Debug */, 696 | 41BA9EDE26F0C07500A78F80 /* Release */, 697 | ); 698 | defaultConfigurationIsVisible = 0; 699 | defaultConfigurationName = Release; 700 | }; 701 | 41BA9EDF26F0C07500A78F80 /* Build configuration list for PBXNativeTarget "infocusTests" */ = { 702 | isa = XCConfigurationList; 703 | buildConfigurations = ( 704 | 41BA9EE026F0C07500A78F80 /* Debug */, 705 | 41BA9EE126F0C07500A78F80 /* Release */, 706 | ); 707 | defaultConfigurationIsVisible = 0; 708 | defaultConfigurationName = Release; 709 | }; 710 | 41BA9EE226F0C07500A78F80 /* Build configuration list for PBXNativeTarget "infocusUITests" */ = { 711 | isa = XCConfigurationList; 712 | buildConfigurations = ( 713 | 41BA9EE326F0C07500A78F80 /* Debug */, 714 | 41BA9EE426F0C07500A78F80 /* Release */, 715 | ); 716 | defaultConfigurationIsVisible = 0; 717 | defaultConfigurationName = Release; 718 | }; 719 | /* End XCConfigurationList section */ 720 | }; 721 | rootObject = 41BA9EB226F0C07500A78F80 /* Project object */; 722 | } 723 | -------------------------------------------------------------------------------- /infocus.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /infocus.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /infocus.xcodeproj/xcshareddata/xcschemes/infocus.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 57 | 63 | 64 | 65 | 66 | 67 | 77 | 79 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /infocus.xcodeproj/xcuserdata/rea094.xcuserdatad/xcschemes/infocuscli.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 57 | 63 | 64 | 65 | 66 | 67 | 77 | 79 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /infocus.xcodeproj/xcuserdata/rea094.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | infocus.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 1 11 | 12 | infocuscli.xcscheme 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | SuppressBuildableAutocreation 19 | 20 | 41BA9EB926F0C07500A78F80 21 | 22 | primary 23 | 24 | 25 | 41BA9EC726F0C07500A78F80 26 | 27 | primary 28 | 29 | 30 | 41BA9ED126F0C07500A78F80 31 | 32 | primary 33 | 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /infocus/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // infocus 4 | // 5 | // Created by Bart Reardon on 14/9/21. 6 | // 7 | 8 | import Cocoa 9 | 10 | @main 11 | class AppDelegate: NSObject, NSApplicationDelegate { 12 | 13 | @IBOutlet var window: NSWindow! 14 | 15 | func applicationWillFinishLaunching(_ notification: Notification) { 16 | if checkDND() { 17 | print("STATUS: Do Not Disturb is enabled") 18 | exit(1) 19 | } 20 | exit(0) 21 | } 22 | 23 | func applicationDidFinishLaunching(_ aNotification: Notification) { 24 | // Insert code here to initialize your application 25 | } 26 | 27 | func applicationWillTerminate(_ aNotification: Notification) { 28 | // Insert code here to tear down your application 29 | } 30 | 31 | func applicationSupportsSecureRestorableState(_ app: NSApplication) -> Bool { 32 | return true 33 | } 34 | 35 | 36 | } 37 | 38 | -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AccentColor.colorset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "colors" : [ 3 | { 4 | "idiom" : "universal" 5 | } 6 | ], 7 | "info" : { 8 | "author" : "xcode", 9 | "version" : 1 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "filename" : "infocus_16.png", 5 | "idiom" : "mac", 6 | "scale" : "1x", 7 | "size" : "16x16" 8 | }, 9 | { 10 | "filename" : "infocus-2.png", 11 | "idiom" : "mac", 12 | "scale" : "2x", 13 | "size" : "16x16" 14 | }, 15 | { 16 | "filename" : "infocus-1.png", 17 | "idiom" : "mac", 18 | "scale" : "1x", 19 | "size" : "32x32" 20 | }, 21 | { 22 | "filename" : "install-5.png", 23 | "idiom" : "mac", 24 | "scale" : "2x", 25 | "size" : "32x32" 26 | }, 27 | { 28 | "filename" : "install-4.png", 29 | "idiom" : "mac", 30 | "scale" : "1x", 31 | "size" : "128x128" 32 | }, 33 | { 34 | "filename" : "install-3.png", 35 | "idiom" : "mac", 36 | "scale" : "2x", 37 | "size" : "128x128" 38 | }, 39 | { 40 | "filename" : "install-2.png", 41 | "idiom" : "mac", 42 | "scale" : "1x", 43 | "size" : "256x256" 44 | }, 45 | { 46 | "filename" : "install-1.png", 47 | "idiom" : "mac", 48 | "scale" : "2x", 49 | "size" : "256x256" 50 | }, 51 | { 52 | "filename" : "install.png", 53 | "idiom" : "mac", 54 | "scale" : "1x", 55 | "size" : "512x512" 56 | }, 57 | { 58 | "filename" : "infocus.png", 59 | "idiom" : "mac", 60 | "scale" : "2x", 61 | "size" : "512x512" 62 | } 63 | ], 64 | "info" : { 65 | "author" : "xcode", 66 | "version" : 1 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/infocus-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/infocus-1.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/infocus-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/infocus-2.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/infocus.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/infocus.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/infocus_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/infocus_16.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/install-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/install-1.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/install-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/install-2.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/install-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/install-3.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/install-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/install-4.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/install-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/install-5.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/AppIcon.appiconset/install.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/bartreardon/infocus/ebb9a518a9fa568b8f5298c88d04afd7cd0ea89c/infocus/Assets.xcassets/AppIcon.appiconset/install.png -------------------------------------------------------------------------------- /infocus/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "author" : "xcode", 4 | "version" : 1 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /infocus/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /infocus/checkDND.swift: -------------------------------------------------------------------------------- 1 | // 2 | // checkDND.swift 3 | // checkDND 4 | // 5 | // Created by Bart Reardon on 14/9/21. 6 | // 7 | 8 | import Foundation 9 | import Intents 10 | import SystemConfiguration 11 | 12 | 13 | func checkDND() -> Bool { 14 | 15 | if #available(macOS 12.0, *) { 16 | // Request authorization to check Focus Status 17 | 18 | INFocusStatusCenter.default.requestAuthorization { status in 19 | 20 | } 21 | 22 | let focusStatusisFocused = INFocusStatusCenter.default.focusStatus.isFocused ?? false 23 | 24 | return focusStatusisFocused 25 | 26 | } else { 27 | 28 | let bundlePath = Bundle.main.bundlePath 29 | 30 | let infocusCLIPath = "\(bundlePath)/Contents/Resources/infocuscli" 31 | 32 | print("Running the Infocus app bundle is not supported under macOS 11 or older due to the DND settings being not available from the app sandbox.") 33 | print("Call the cli utility directly instead,which is located at:") 34 | print(infocusCLIPath) 35 | 36 | } 37 | return false 38 | } 39 | -------------------------------------------------------------------------------- /infocus/checkDNDcli.swift: -------------------------------------------------------------------------------- 1 | // 2 | // checkDNDcli.swift 3 | // infocuscli 4 | // 5 | // Created by Bart Reardon on 18/9/21. 6 | // 7 | 8 | import Foundation 9 | import SystemConfiguration 10 | 11 | func checkDNDcli() -> Bool { 12 | 13 | if #available(macOS 12.0, *) { 14 | // Request authorization to check Focus Status 15 | 16 | print("The CLI utility is not supported under macOS 12 or above. Use the app bundle binary instead") 17 | 18 | } else { 19 | 20 | // Fallback on earlier versions 21 | print("checking older version") 22 | 23 | let consoleUser = SCDynamicStoreCopyConsoleUser(nil, nil , nil) 24 | let consoleUserHomeDir = FileManager.default.homeDirectory(forUser: consoleUser! as String)?.path ?? "" 25 | 26 | let ncprefsUrl = URL( 27 | fileURLWithPath: String("\(consoleUserHomeDir)/Library/Preferences/com.apple.ncprefs.plist") 28 | ) 29 | 30 | do { 31 | let prefsList = try plistFromData(try Data(contentsOf: ncprefsUrl)) 32 | let dndPrefsData = prefsList["dnd_prefs"] as! Data 33 | let dndPrefsList = try plistFromData(dndPrefsData) 34 | 35 | if let userPref = dndPrefsList["userPref"] as? [String:Any] { 36 | return userPref["enabled"] as! Bool 37 | } 38 | } catch { 39 | print("DND Prefs unavailable") 40 | } 41 | } 42 | return false 43 | } 44 | -------------------------------------------------------------------------------- /infocus/infocus.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.developer.usernotifications.communication 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /infocus/plistFromData.swift: -------------------------------------------------------------------------------- 1 | // 2 | // File.swift 3 | // infocus 4 | // 5 | // Created by Bart Reardon on 18/9/21. 6 | // 7 | 8 | import Foundation 9 | 10 | func plistFromData(_ data: Data) throws -> [String:Any] { 11 | try PropertyListSerialization.propertyList( 12 | from: data, 13 | format: nil 14 | ) as! [String:Any] 15 | } 16 | -------------------------------------------------------------------------------- /infocusTests/infocusTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // infocusTests.swift 3 | // infocusTests 4 | // 5 | // Created by Bart Reardon on 14/9/21. 6 | // 7 | 8 | import XCTest 9 | @testable import infocus 10 | 11 | class infocusTests: XCTestCase { 12 | 13 | override func setUpWithError() throws { 14 | // Put setup code here. This method is called before the invocation of each test method in the class. 15 | } 16 | 17 | override func tearDownWithError() throws { 18 | // Put teardown code here. This method is called after the invocation of each test method in the class. 19 | } 20 | 21 | func testExample() throws { 22 | // This is an example of a functional test case. 23 | // Use XCTAssert and related functions to verify your tests produce the correct results. 24 | } 25 | 26 | func testPerformanceExample() throws { 27 | // This is an example of a performance test case. 28 | self.measure { 29 | // Put the code you want to measure the time of here. 30 | } 31 | } 32 | 33 | } 34 | -------------------------------------------------------------------------------- /infocusUITests/infocusUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // infocusUITests.swift 3 | // infocusUITests 4 | // 5 | // Created by Bart Reardon on 14/9/21. 6 | // 7 | 8 | import XCTest 9 | 10 | class infocusUITests: XCTestCase { 11 | 12 | override func setUpWithError() throws { 13 | // Put setup code here. This method is called before the invocation of each test method in the class. 14 | 15 | // In UI tests it is usually best to stop immediately when a failure occurs. 16 | continueAfterFailure = false 17 | 18 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 19 | } 20 | 21 | override func tearDownWithError() throws { 22 | // Put teardown code here. This method is called after the invocation of each test method in the class. 23 | } 24 | 25 | func testExample() throws { 26 | // UI tests must launch the application that they test. 27 | let app = XCUIApplication() 28 | app.launch() 29 | 30 | // Use recording to get started writing UI tests. 31 | // Use XCTAssert and related functions to verify your tests produce the correct results. 32 | } 33 | 34 | func testLaunchPerformance() throws { 35 | if #available(macOS 10.15, iOS 13.0, tvOS 13.0, watchOS 7.0, *) { 36 | // This measures how long it takes to launch your application. 37 | measure(metrics: [XCTApplicationLaunchMetric()]) { 38 | XCUIApplication().launch() 39 | } 40 | } 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /infocusUITests/infocusUITestsLaunchTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // infocusUITestsLaunchTests.swift 3 | // infocusUITests 4 | // 5 | // Created by Bart Reardon on 14/9/21. 6 | // 7 | 8 | import XCTest 9 | 10 | class infocusUITestsLaunchTests: XCTestCase { 11 | 12 | override class var runsForEachTargetApplicationUIConfiguration: Bool { 13 | true 14 | } 15 | 16 | override func setUpWithError() throws { 17 | continueAfterFailure = false 18 | } 19 | 20 | func testLaunch() throws { 21 | let app = XCUIApplication() 22 | app.launch() 23 | 24 | // Insert steps here to perform after app launch but before taking a screenshot, 25 | // such as logging into a test account or navigating somewhere in the app 26 | 27 | let attachment = XCTAttachment(screenshot: app.screenshot()) 28 | attachment.name = "Launch Screen" 29 | attachment.lifetime = .keepAlways 30 | add(attachment) 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /infocuscli/main.swift: -------------------------------------------------------------------------------- 1 | // 2 | // main.swift 3 | // infocuscli 4 | // 5 | // Created by Bart Reardon on 18/9/21. 6 | // 7 | 8 | import Foundation 9 | 10 | if checkDNDcli() { 11 | print("STATUS: Do Not Disturb is enabled") 12 | exit(1) 13 | } else { 14 | print("STATUS: Do Not Disturb is disabled") 15 | } 16 | exit(0) 17 | 18 | --------------------------------------------------------------------------------