├── .gitignore ├── NSUserNotificationPrivate.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── NSUserNotificationPrivate ├── Base.lproj │ └── MainMenu.xib ├── INDAppDelegate.h ├── INDAppDelegate.m ├── INDDragAndDropImageWell.h ├── INDDragAndDropImageWell.m ├── Images.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json ├── NSUserNotificationPrivate-Info.plist ├── NSUserNotificationPrivate-Prefix.pch ├── NSUserNotification_Private.h ├── en.lproj │ ├── Credits.rtf │ └── InfoPlist.strings └── main.m ├── NSUserNotificationPrivateTests ├── NSUserNotificationPrivateTests-Info.plist ├── NSUserNotificationPrivateTests.m └── en.lproj │ └── InfoPlist.strings ├── README.md └── images ├── custom-items.png ├── example-ui.png └── itunes-notification.png /.gitignore: -------------------------------------------------------------------------------- 1 | # OS X 2 | .DS_Store 3 | 4 | # Xcode 5 | build/ 6 | *.pbxuser 7 | !default.pbxuser 8 | *.mode1v3 9 | !default.mode1v3 10 | *.mode2v3 11 | !default.mode2v3 12 | *.perspectivev3 13 | !default.perspectivev3 14 | xcuserdata 15 | *.xccheckout 16 | profile 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | 22 | # CocoaPods 23 | Pods -------------------------------------------------------------------------------- /NSUserNotificationPrivate.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 033DD46C185584630033B621 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033DD46B185584630033B621 /* Cocoa.framework */; }; 11 | 033DD476185584630033B621 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 033DD474185584630033B621 /* InfoPlist.strings */; }; 12 | 033DD478185584630033B621 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 033DD477185584630033B621 /* main.m */; }; 13 | 033DD47C185584630033B621 /* Credits.rtf in Resources */ = {isa = PBXBuildFile; fileRef = 033DD47A185584630033B621 /* Credits.rtf */; }; 14 | 033DD47F185584630033B621 /* INDAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 033DD47E185584630033B621 /* INDAppDelegate.m */; }; 15 | 033DD482185584630033B621 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 033DD480185584630033B621 /* MainMenu.xib */; }; 16 | 033DD484185584630033B621 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 033DD483185584630033B621 /* Images.xcassets */; }; 17 | 033DD48B185584630033B621 /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033DD48A185584630033B621 /* XCTest.framework */; }; 18 | 033DD48C185584630033B621 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 033DD46B185584630033B621 /* Cocoa.framework */; }; 19 | 033DD494185584630033B621 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 033DD492185584630033B621 /* InfoPlist.strings */; }; 20 | 033DD496185584630033B621 /* NSUserNotificationPrivateTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 033DD495185584630033B621 /* NSUserNotificationPrivateTests.m */; }; 21 | 033DD4A2185588BA0033B621 /* INDDragAndDropImageWell.m in Sources */ = {isa = PBXBuildFile; fileRef = 033DD4A1185588BA0033B621 /* INDDragAndDropImageWell.m */; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | 033DD48D185584630033B621 /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = 033DD460185584630033B621 /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = 033DD467185584630033B621; 30 | remoteInfo = NSUserNotificationPrivate; 31 | }; 32 | /* End PBXContainerItemProxy section */ 33 | 34 | /* Begin PBXFileReference section */ 35 | 033DD468185584630033B621 /* NSUserNotificationPrivate.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NSUserNotificationPrivate.app; sourceTree = BUILT_PRODUCTS_DIR; }; 36 | 033DD46B185584630033B621 /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; }; 37 | 033DD46E185584630033B621 /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; }; 38 | 033DD46F185584630033B621 /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; }; 39 | 033DD470185584630033B621 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 40 | 033DD473185584630033B621 /* NSUserNotificationPrivate-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NSUserNotificationPrivate-Info.plist"; sourceTree = ""; }; 41 | 033DD475185584630033B621 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 42 | 033DD477185584630033B621 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 43 | 033DD479185584630033B621 /* NSUserNotificationPrivate-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "NSUserNotificationPrivate-Prefix.pch"; sourceTree = ""; }; 44 | 033DD47B185584630033B621 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.rtf; name = en; path = en.lproj/Credits.rtf; sourceTree = ""; }; 45 | 033DD47D185584630033B621 /* INDAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = INDAppDelegate.h; sourceTree = ""; }; 46 | 033DD47E185584630033B621 /* INDAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = INDAppDelegate.m; sourceTree = ""; }; 47 | 033DD481185584630033B621 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/MainMenu.xib; sourceTree = ""; }; 48 | 033DD483185584630033B621 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 49 | 033DD489185584630033B621 /* NSUserNotificationPrivateTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = NSUserNotificationPrivateTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 50 | 033DD48A185584630033B621 /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; 51 | 033DD491185584630033B621 /* NSUserNotificationPrivateTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "NSUserNotificationPrivateTests-Info.plist"; sourceTree = ""; }; 52 | 033DD493185584630033B621 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 53 | 033DD495185584630033B621 /* NSUserNotificationPrivateTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = NSUserNotificationPrivateTests.m; sourceTree = ""; }; 54 | 033DD49F185584860033B621 /* NSUserNotification_Private.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NSUserNotification_Private.h; sourceTree = ""; }; 55 | 033DD4A0185588BA0033B621 /* INDDragAndDropImageWell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = INDDragAndDropImageWell.h; sourceTree = ""; }; 56 | 033DD4A1185588BA0033B621 /* INDDragAndDropImageWell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = INDDragAndDropImageWell.m; sourceTree = ""; }; 57 | /* End PBXFileReference section */ 58 | 59 | /* Begin PBXFrameworksBuildPhase section */ 60 | 033DD465185584630033B621 /* Frameworks */ = { 61 | isa = PBXFrameworksBuildPhase; 62 | buildActionMask = 2147483647; 63 | files = ( 64 | 033DD46C185584630033B621 /* Cocoa.framework in Frameworks */, 65 | ); 66 | runOnlyForDeploymentPostprocessing = 0; 67 | }; 68 | 033DD486185584630033B621 /* Frameworks */ = { 69 | isa = PBXFrameworksBuildPhase; 70 | buildActionMask = 2147483647; 71 | files = ( 72 | 033DD48C185584630033B621 /* Cocoa.framework in Frameworks */, 73 | 033DD48B185584630033B621 /* XCTest.framework in Frameworks */, 74 | ); 75 | runOnlyForDeploymentPostprocessing = 0; 76 | }; 77 | /* End PBXFrameworksBuildPhase section */ 78 | 79 | /* Begin PBXGroup section */ 80 | 033DD45F185584630033B621 = { 81 | isa = PBXGroup; 82 | children = ( 83 | 033DD471185584630033B621 /* NSUserNotificationPrivate */, 84 | 033DD48F185584630033B621 /* NSUserNotificationPrivateTests */, 85 | 033DD46A185584630033B621 /* Frameworks */, 86 | 033DD469185584630033B621 /* Products */, 87 | ); 88 | sourceTree = ""; 89 | }; 90 | 033DD469185584630033B621 /* Products */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | 033DD468185584630033B621 /* NSUserNotificationPrivate.app */, 94 | 033DD489185584630033B621 /* NSUserNotificationPrivateTests.xctest */, 95 | ); 96 | name = Products; 97 | sourceTree = ""; 98 | }; 99 | 033DD46A185584630033B621 /* Frameworks */ = { 100 | isa = PBXGroup; 101 | children = ( 102 | 033DD46B185584630033B621 /* Cocoa.framework */, 103 | 033DD48A185584630033B621 /* XCTest.framework */, 104 | 033DD46D185584630033B621 /* Other Frameworks */, 105 | ); 106 | name = Frameworks; 107 | sourceTree = ""; 108 | }; 109 | 033DD46D185584630033B621 /* Other Frameworks */ = { 110 | isa = PBXGroup; 111 | children = ( 112 | 033DD46E185584630033B621 /* AppKit.framework */, 113 | 033DD46F185584630033B621 /* CoreData.framework */, 114 | 033DD470185584630033B621 /* Foundation.framework */, 115 | ); 116 | name = "Other Frameworks"; 117 | sourceTree = ""; 118 | }; 119 | 033DD471185584630033B621 /* NSUserNotificationPrivate */ = { 120 | isa = PBXGroup; 121 | children = ( 122 | 033DD49F185584860033B621 /* NSUserNotification_Private.h */, 123 | 033DD47D185584630033B621 /* INDAppDelegate.h */, 124 | 033DD47E185584630033B621 /* INDAppDelegate.m */, 125 | 033DD480185584630033B621 /* MainMenu.xib */, 126 | 033DD483185584630033B621 /* Images.xcassets */, 127 | 033DD472185584630033B621 /* Supporting Files */, 128 | 033DD4A0185588BA0033B621 /* INDDragAndDropImageWell.h */, 129 | 033DD4A1185588BA0033B621 /* INDDragAndDropImageWell.m */, 130 | ); 131 | path = NSUserNotificationPrivate; 132 | sourceTree = ""; 133 | }; 134 | 033DD472185584630033B621 /* Supporting Files */ = { 135 | isa = PBXGroup; 136 | children = ( 137 | 033DD473185584630033B621 /* NSUserNotificationPrivate-Info.plist */, 138 | 033DD474185584630033B621 /* InfoPlist.strings */, 139 | 033DD477185584630033B621 /* main.m */, 140 | 033DD479185584630033B621 /* NSUserNotificationPrivate-Prefix.pch */, 141 | 033DD47A185584630033B621 /* Credits.rtf */, 142 | ); 143 | name = "Supporting Files"; 144 | sourceTree = ""; 145 | }; 146 | 033DD48F185584630033B621 /* NSUserNotificationPrivateTests */ = { 147 | isa = PBXGroup; 148 | children = ( 149 | 033DD495185584630033B621 /* NSUserNotificationPrivateTests.m */, 150 | 033DD490185584630033B621 /* Supporting Files */, 151 | ); 152 | path = NSUserNotificationPrivateTests; 153 | sourceTree = ""; 154 | }; 155 | 033DD490185584630033B621 /* Supporting Files */ = { 156 | isa = PBXGroup; 157 | children = ( 158 | 033DD491185584630033B621 /* NSUserNotificationPrivateTests-Info.plist */, 159 | 033DD492185584630033B621 /* InfoPlist.strings */, 160 | ); 161 | name = "Supporting Files"; 162 | sourceTree = ""; 163 | }; 164 | /* End PBXGroup section */ 165 | 166 | /* Begin PBXNativeTarget section */ 167 | 033DD467185584630033B621 /* NSUserNotificationPrivate */ = { 168 | isa = PBXNativeTarget; 169 | buildConfigurationList = 033DD499185584630033B621 /* Build configuration list for PBXNativeTarget "NSUserNotificationPrivate" */; 170 | buildPhases = ( 171 | 033DD464185584630033B621 /* Sources */, 172 | 033DD465185584630033B621 /* Frameworks */, 173 | 033DD466185584630033B621 /* Resources */, 174 | ); 175 | buildRules = ( 176 | ); 177 | dependencies = ( 178 | ); 179 | name = NSUserNotificationPrivate; 180 | productName = NSUserNotificationPrivate; 181 | productReference = 033DD468185584630033B621 /* NSUserNotificationPrivate.app */; 182 | productType = "com.apple.product-type.application"; 183 | }; 184 | 033DD488185584630033B621 /* NSUserNotificationPrivateTests */ = { 185 | isa = PBXNativeTarget; 186 | buildConfigurationList = 033DD49C185584630033B621 /* Build configuration list for PBXNativeTarget "NSUserNotificationPrivateTests" */; 187 | buildPhases = ( 188 | 033DD485185584630033B621 /* Sources */, 189 | 033DD486185584630033B621 /* Frameworks */, 190 | 033DD487185584630033B621 /* Resources */, 191 | ); 192 | buildRules = ( 193 | ); 194 | dependencies = ( 195 | 033DD48E185584630033B621 /* PBXTargetDependency */, 196 | ); 197 | name = NSUserNotificationPrivateTests; 198 | productName = NSUserNotificationPrivateTests; 199 | productReference = 033DD489185584630033B621 /* NSUserNotificationPrivateTests.xctest */; 200 | productType = "com.apple.product-type.bundle.unit-test"; 201 | }; 202 | /* End PBXNativeTarget section */ 203 | 204 | /* Begin PBXProject section */ 205 | 033DD460185584630033B621 /* Project object */ = { 206 | isa = PBXProject; 207 | attributes = { 208 | CLASSPREFIX = IND; 209 | LastUpgradeCheck = 0500; 210 | ORGANIZATIONNAME = "Indragie Karunaratne"; 211 | TargetAttributes = { 212 | 033DD488185584630033B621 = { 213 | TestTargetID = 033DD467185584630033B621; 214 | }; 215 | }; 216 | }; 217 | buildConfigurationList = 033DD463185584630033B621 /* Build configuration list for PBXProject "NSUserNotificationPrivate" */; 218 | compatibilityVersion = "Xcode 3.2"; 219 | developmentRegion = English; 220 | hasScannedForEncodings = 0; 221 | knownRegions = ( 222 | en, 223 | Base, 224 | ); 225 | mainGroup = 033DD45F185584630033B621; 226 | productRefGroup = 033DD469185584630033B621 /* Products */; 227 | projectDirPath = ""; 228 | projectRoot = ""; 229 | targets = ( 230 | 033DD467185584630033B621 /* NSUserNotificationPrivate */, 231 | 033DD488185584630033B621 /* NSUserNotificationPrivateTests */, 232 | ); 233 | }; 234 | /* End PBXProject section */ 235 | 236 | /* Begin PBXResourcesBuildPhase section */ 237 | 033DD466185584630033B621 /* Resources */ = { 238 | isa = PBXResourcesBuildPhase; 239 | buildActionMask = 2147483647; 240 | files = ( 241 | 033DD476185584630033B621 /* InfoPlist.strings in Resources */, 242 | 033DD484185584630033B621 /* Images.xcassets in Resources */, 243 | 033DD47C185584630033B621 /* Credits.rtf in Resources */, 244 | 033DD482185584630033B621 /* MainMenu.xib in Resources */, 245 | ); 246 | runOnlyForDeploymentPostprocessing = 0; 247 | }; 248 | 033DD487185584630033B621 /* Resources */ = { 249 | isa = PBXResourcesBuildPhase; 250 | buildActionMask = 2147483647; 251 | files = ( 252 | 033DD494185584630033B621 /* InfoPlist.strings in Resources */, 253 | ); 254 | runOnlyForDeploymentPostprocessing = 0; 255 | }; 256 | /* End PBXResourcesBuildPhase section */ 257 | 258 | /* Begin PBXSourcesBuildPhase section */ 259 | 033DD464185584630033B621 /* Sources */ = { 260 | isa = PBXSourcesBuildPhase; 261 | buildActionMask = 2147483647; 262 | files = ( 263 | 033DD47F185584630033B621 /* INDAppDelegate.m in Sources */, 264 | 033DD4A2185588BA0033B621 /* INDDragAndDropImageWell.m in Sources */, 265 | 033DD478185584630033B621 /* main.m in Sources */, 266 | ); 267 | runOnlyForDeploymentPostprocessing = 0; 268 | }; 269 | 033DD485185584630033B621 /* Sources */ = { 270 | isa = PBXSourcesBuildPhase; 271 | buildActionMask = 2147483647; 272 | files = ( 273 | 033DD496185584630033B621 /* NSUserNotificationPrivateTests.m in Sources */, 274 | ); 275 | runOnlyForDeploymentPostprocessing = 0; 276 | }; 277 | /* End PBXSourcesBuildPhase section */ 278 | 279 | /* Begin PBXTargetDependency section */ 280 | 033DD48E185584630033B621 /* PBXTargetDependency */ = { 281 | isa = PBXTargetDependency; 282 | target = 033DD467185584630033B621 /* NSUserNotificationPrivate */; 283 | targetProxy = 033DD48D185584630033B621 /* PBXContainerItemProxy */; 284 | }; 285 | /* End PBXTargetDependency section */ 286 | 287 | /* Begin PBXVariantGroup section */ 288 | 033DD474185584630033B621 /* InfoPlist.strings */ = { 289 | isa = PBXVariantGroup; 290 | children = ( 291 | 033DD475185584630033B621 /* en */, 292 | ); 293 | name = InfoPlist.strings; 294 | sourceTree = ""; 295 | }; 296 | 033DD47A185584630033B621 /* Credits.rtf */ = { 297 | isa = PBXVariantGroup; 298 | children = ( 299 | 033DD47B185584630033B621 /* en */, 300 | ); 301 | name = Credits.rtf; 302 | sourceTree = ""; 303 | }; 304 | 033DD480185584630033B621 /* MainMenu.xib */ = { 305 | isa = PBXVariantGroup; 306 | children = ( 307 | 033DD481185584630033B621 /* Base */, 308 | ); 309 | name = MainMenu.xib; 310 | sourceTree = ""; 311 | }; 312 | 033DD492185584630033B621 /* InfoPlist.strings */ = { 313 | isa = PBXVariantGroup; 314 | children = ( 315 | 033DD493185584630033B621 /* en */, 316 | ); 317 | name = InfoPlist.strings; 318 | sourceTree = ""; 319 | }; 320 | /* End PBXVariantGroup section */ 321 | 322 | /* Begin XCBuildConfiguration section */ 323 | 033DD497185584630033B621 /* Debug */ = { 324 | isa = XCBuildConfiguration; 325 | buildSettings = { 326 | ALWAYS_SEARCH_USER_PATHS = NO; 327 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 328 | CLANG_CXX_LIBRARY = "libc++"; 329 | CLANG_ENABLE_OBJC_ARC = YES; 330 | CLANG_WARN_BOOL_CONVERSION = YES; 331 | CLANG_WARN_CONSTANT_CONVERSION = YES; 332 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 333 | CLANG_WARN_EMPTY_BODY = YES; 334 | CLANG_WARN_ENUM_CONVERSION = YES; 335 | CLANG_WARN_INT_CONVERSION = YES; 336 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 337 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 338 | COPY_PHASE_STRIP = NO; 339 | GCC_C_LANGUAGE_STANDARD = gnu99; 340 | GCC_DYNAMIC_NO_PIC = NO; 341 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 342 | GCC_OPTIMIZATION_LEVEL = 0; 343 | GCC_PREPROCESSOR_DEFINITIONS = ( 344 | "DEBUG=1", 345 | "$(inherited)", 346 | ); 347 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 348 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 349 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 350 | GCC_WARN_UNDECLARED_SELECTOR = YES; 351 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 352 | GCC_WARN_UNUSED_FUNCTION = YES; 353 | GCC_WARN_UNUSED_VARIABLE = YES; 354 | MACOSX_DEPLOYMENT_TARGET = 10.9; 355 | ONLY_ACTIVE_ARCH = YES; 356 | SDKROOT = macosx; 357 | }; 358 | name = Debug; 359 | }; 360 | 033DD498185584630033B621 /* Release */ = { 361 | isa = XCBuildConfiguration; 362 | buildSettings = { 363 | ALWAYS_SEARCH_USER_PATHS = NO; 364 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 365 | CLANG_CXX_LIBRARY = "libc++"; 366 | CLANG_ENABLE_OBJC_ARC = YES; 367 | CLANG_WARN_BOOL_CONVERSION = YES; 368 | CLANG_WARN_CONSTANT_CONVERSION = YES; 369 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 370 | CLANG_WARN_EMPTY_BODY = YES; 371 | CLANG_WARN_ENUM_CONVERSION = YES; 372 | CLANG_WARN_INT_CONVERSION = YES; 373 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 374 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 375 | COPY_PHASE_STRIP = YES; 376 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 377 | ENABLE_NS_ASSERTIONS = NO; 378 | GCC_C_LANGUAGE_STANDARD = gnu99; 379 | GCC_ENABLE_OBJC_EXCEPTIONS = YES; 380 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 381 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 382 | GCC_WARN_UNDECLARED_SELECTOR = YES; 383 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 384 | GCC_WARN_UNUSED_FUNCTION = YES; 385 | GCC_WARN_UNUSED_VARIABLE = YES; 386 | MACOSX_DEPLOYMENT_TARGET = 10.9; 387 | SDKROOT = macosx; 388 | }; 389 | name = Release; 390 | }; 391 | 033DD49A185584630033B621 /* Debug */ = { 392 | isa = XCBuildConfiguration; 393 | buildSettings = { 394 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 395 | COMBINE_HIDPI_IMAGES = YES; 396 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 397 | GCC_PREFIX_HEADER = "NSUserNotificationPrivate/NSUserNotificationPrivate-Prefix.pch"; 398 | INFOPLIST_FILE = "NSUserNotificationPrivate/NSUserNotificationPrivate-Info.plist"; 399 | PRODUCT_NAME = "$(TARGET_NAME)"; 400 | WRAPPER_EXTENSION = app; 401 | }; 402 | name = Debug; 403 | }; 404 | 033DD49B185584630033B621 /* Release */ = { 405 | isa = XCBuildConfiguration; 406 | buildSettings = { 407 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 408 | COMBINE_HIDPI_IMAGES = YES; 409 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 410 | GCC_PREFIX_HEADER = "NSUserNotificationPrivate/NSUserNotificationPrivate-Prefix.pch"; 411 | INFOPLIST_FILE = "NSUserNotificationPrivate/NSUserNotificationPrivate-Info.plist"; 412 | PRODUCT_NAME = "$(TARGET_NAME)"; 413 | WRAPPER_EXTENSION = app; 414 | }; 415 | name = Release; 416 | }; 417 | 033DD49D185584630033B621 /* Debug */ = { 418 | isa = XCBuildConfiguration; 419 | buildSettings = { 420 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/NSUserNotificationPrivate.app/Contents/MacOS/NSUserNotificationPrivate"; 421 | COMBINE_HIDPI_IMAGES = YES; 422 | FRAMEWORK_SEARCH_PATHS = ( 423 | "$(DEVELOPER_FRAMEWORKS_DIR)", 424 | "$(inherited)", 425 | ); 426 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 427 | GCC_PREFIX_HEADER = "NSUserNotificationPrivate/NSUserNotificationPrivate-Prefix.pch"; 428 | GCC_PREPROCESSOR_DEFINITIONS = ( 429 | "DEBUG=1", 430 | "$(inherited)", 431 | ); 432 | INFOPLIST_FILE = "NSUserNotificationPrivateTests/NSUserNotificationPrivateTests-Info.plist"; 433 | PRODUCT_NAME = "$(TARGET_NAME)"; 434 | TEST_HOST = "$(BUNDLE_LOADER)"; 435 | WRAPPER_EXTENSION = xctest; 436 | }; 437 | name = Debug; 438 | }; 439 | 033DD49E185584630033B621 /* Release */ = { 440 | isa = XCBuildConfiguration; 441 | buildSettings = { 442 | BUNDLE_LOADER = "$(BUILT_PRODUCTS_DIR)/NSUserNotificationPrivate.app/Contents/MacOS/NSUserNotificationPrivate"; 443 | COMBINE_HIDPI_IMAGES = YES; 444 | FRAMEWORK_SEARCH_PATHS = ( 445 | "$(DEVELOPER_FRAMEWORKS_DIR)", 446 | "$(inherited)", 447 | ); 448 | GCC_PRECOMPILE_PREFIX_HEADER = YES; 449 | GCC_PREFIX_HEADER = "NSUserNotificationPrivate/NSUserNotificationPrivate-Prefix.pch"; 450 | INFOPLIST_FILE = "NSUserNotificationPrivateTests/NSUserNotificationPrivateTests-Info.plist"; 451 | PRODUCT_NAME = "$(TARGET_NAME)"; 452 | TEST_HOST = "$(BUNDLE_LOADER)"; 453 | WRAPPER_EXTENSION = xctest; 454 | }; 455 | name = Release; 456 | }; 457 | /* End XCBuildConfiguration section */ 458 | 459 | /* Begin XCConfigurationList section */ 460 | 033DD463185584630033B621 /* Build configuration list for PBXProject "NSUserNotificationPrivate" */ = { 461 | isa = XCConfigurationList; 462 | buildConfigurations = ( 463 | 033DD497185584630033B621 /* Debug */, 464 | 033DD498185584630033B621 /* Release */, 465 | ); 466 | defaultConfigurationIsVisible = 0; 467 | defaultConfigurationName = Release; 468 | }; 469 | 033DD499185584630033B621 /* Build configuration list for PBXNativeTarget "NSUserNotificationPrivate" */ = { 470 | isa = XCConfigurationList; 471 | buildConfigurations = ( 472 | 033DD49A185584630033B621 /* Debug */, 473 | 033DD49B185584630033B621 /* Release */, 474 | ); 475 | defaultConfigurationIsVisible = 0; 476 | }; 477 | 033DD49C185584630033B621 /* Build configuration list for PBXNativeTarget "NSUserNotificationPrivateTests" */ = { 478 | isa = XCConfigurationList; 479 | buildConfigurations = ( 480 | 033DD49D185584630033B621 /* Debug */, 481 | 033DD49E185584630033B621 /* Release */, 482 | ); 483 | defaultConfigurationIsVisible = 0; 484 | }; 485 | /* End XCConfigurationList section */ 486 | }; 487 | rootObject = 033DD460185584630033B621 /* Project object */; 488 | } 489 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/Base.lproj/MainMenu.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 276 | 277 | 278 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 286 | 287 | 288 | 289 | 290 | 291 | 292 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | 317 | 318 | 319 | 320 | 321 | 322 | 323 | 324 | 325 | 326 | 327 | 328 | 329 | 330 | 331 | 332 | 333 | 334 | 335 | 336 | 337 | 338 | 339 | 340 | 341 | 342 | 343 | 344 | 345 | 346 | 347 | 348 | 349 | 350 | 351 | 352 | 353 | 354 | 355 | 356 | 357 | 358 | 359 | 360 | 361 | 362 | 363 | 364 | 365 | 366 | 367 | 368 | 369 | 370 | 371 | 372 | 373 | 374 | 375 | 376 | 377 | 378 | 379 | 380 | 381 | 382 | 383 | 384 | 385 | 386 | 387 | 388 | 389 | 390 | 391 | 392 | 393 | 394 | 395 | 396 | 397 | 398 | 399 | 400 | 401 | 402 | 403 | 404 | 405 | 406 | 407 | 408 | 409 | 410 | 411 | 412 | 413 | 414 | 415 | 416 | 417 | 418 | 419 | 420 | 421 | 422 | 423 | 424 | 425 | 426 | 427 | 428 | 429 | 430 | 431 | 432 | 433 | 434 | 435 | 436 | 437 | 438 | 439 | 440 | 441 | 442 | 443 | 444 | 445 | 446 | 447 | 448 | 449 | 450 | 451 | 452 | 453 | 454 | 455 | 456 | 457 | 458 | 459 | 460 | 461 | 462 | 463 | 464 | 465 | 466 | 467 | 468 | 469 | 470 | 471 | 472 | 473 | 474 | 475 | 476 | 477 | 478 | 479 | 480 | 481 | 482 | 483 | 484 | 485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | 495 | 496 | 497 | 498 | 499 | 500 | 501 | 502 | 503 | 504 | 505 | 506 | 507 | 508 | 509 | 510 | 511 | 512 | 513 | 514 | 515 | 516 | 517 | 518 | 519 | 520 | 521 | Default 522 | 523 | 524 | 525 | 526 | 527 | 528 | Left to Right 529 | 530 | 531 | 532 | 533 | 534 | 535 | Right to Left 536 | 537 | 538 | 539 | 540 | 541 | 542 | 543 | 544 | 545 | 546 | Default 547 | 548 | 549 | 550 | 551 | 552 | 553 | Left to Right 554 | 555 | 556 | 557 | 558 | 559 | 560 | Right to Left 561 | 562 | 563 | 564 | 565 | 566 | 567 | 568 | 569 | 570 | 571 | 572 | 573 | 574 | 575 | 576 | 577 | 578 | 579 | 580 | 581 | 582 | 583 | 584 | 585 | 586 | 587 | 588 | 589 | 590 | 591 | 592 | 593 | 594 | 595 | 596 | 597 | 598 | 599 | 600 | 601 | 602 | 603 | 604 | 605 | 606 | 607 | 608 | 609 | 610 | 611 | 612 | 613 | 614 | 615 | 616 | 617 | 618 | 619 | 620 | 621 | 622 | 623 | 624 | 625 | 626 | 627 | 628 | 629 | 630 | 631 | 632 | 633 | 634 | 635 | 636 | 637 | 638 | 639 | 640 | 641 | 642 | 643 | 644 | 645 | 646 | 647 | 648 | 649 | 650 | 651 | 652 | 653 | 654 | 655 | 656 | 657 | 658 | 659 | 660 | 661 | 662 | 663 | 664 | 665 | 666 | 667 | 668 | 669 | 670 | 671 | 672 | 673 | 674 | 675 | 676 | 677 | 678 | 679 | 680 | 681 | 682 | 683 | 684 | 685 | 686 | 687 | 688 | 689 | 690 | 691 | 692 | 693 | 694 | 695 | 696 | 697 | 698 | 699 | 700 | 701 | 702 | 703 | 704 | 705 | 706 | 707 | 708 | 709 | 710 | 711 | 712 | 713 | 714 | 715 | 716 | 717 | 718 | 719 | 720 | 721 | 722 | 723 | 724 | 725 | 726 | 727 | 728 | 729 | 730 | 731 | 732 | 733 | 734 | 735 | 736 | 737 | 738 | 739 | 740 | 741 | 742 | 743 | 744 | 745 | 746 | 747 | 748 | 749 | 750 | 751 | 752 | 753 | 754 | 755 | 766 | 777 | 778 | 779 | 780 | 781 | 782 | 783 | 784 | 785 | 786 | 797 | 808 | 819 | 820 | 821 | 822 | 823 | 824 | Check the code to see how the titles for the alternate action buttons are set. Only works when notification type is set to "Alert" in System Preferences. 825 | 826 | 827 | 828 | 829 | 840 | 841 | 842 | 843 | 844 | 845 | 846 | 847 | 848 | 849 | 850 | 851 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/INDAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // INDAppDelegate.h 3 | // NSUserNotificationPrivate 4 | // 5 | // Created by Indragie Karunaratne on 12/8/2013. 6 | // Copyright (c) 2013 Indragie Karunaratne. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface INDAppDelegate : NSObject 12 | 13 | @property (assign) IBOutlet NSWindow *window; 14 | @property (nonatomic, copy) NSString *title; 15 | @property (nonatomic, copy) NSString *subtitle; 16 | @property (nonatomic, copy) NSString *message; 17 | @property (nonatomic, assign) BOOL identityImageHasBorder; 18 | @property (nonatomic, strong) NSImage *identityImage; 19 | @property (nonatomic, strong) NSImage *contentImage; 20 | @property (nonatomic, assign) BOOL ignoresDoNotDisturb; 21 | @property (nonatomic, assign) BOOL lockscreenOnly; 22 | @property (nonatomic, assign) BOOL showAlternateActionMenu; 23 | @property (nonatomic, assign) BOOL poofsOnCancel; 24 | 25 | - (IBAction)post:(id)sender; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/INDAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // INDAppDelegate.m 3 | // NSUserNotificationPrivate 4 | // 5 | // Created by Indragie Karunaratne on 12/8/2013. 6 | // Copyright (c) 2013 Indragie Karunaratne. All rights reserved. 7 | // 8 | 9 | #import "INDAppDelegate.h" 10 | 11 | @interface INDAppDelegate () 12 | @end 13 | 14 | @implementation INDAppDelegate 15 | 16 | - (void)applicationDidFinishLaunching:(NSNotification *)notification 17 | { 18 | NSUserNotificationCenter.defaultUserNotificationCenter.delegate = self; 19 | // Default options from NSUserNotification 20 | self.poofsOnCancel = YES; 21 | self.identityImageHasBorder = YES; 22 | } 23 | 24 | - (IBAction)post:(id)sender 25 | { 26 | NSUserNotification *n = [NSUserNotification new]; 27 | n.title = self.title; 28 | n.subtitle = self.subtitle; 29 | n.informativeText = self.message; 30 | n.contentImage = self.contentImage; 31 | n.hasActionButton = YES; 32 | n.actionButtonTitle = @"Action"; 33 | n.otherButtonTitle = @"Other"; 34 | 35 | /** Everything below is private **/ 36 | [n setValue:self.identityImage forKey:@"_identityImage"]; 37 | [n setValue:@(self.identityImageHasBorder) forKey:@"_identityImageHasBorder"]; 38 | [n setValue:@(self.ignoresDoNotDisturb) forKey:@"_ignoresDoNotDisturb"]; 39 | [n setValue:@(self.lockscreenOnly) forKey:@"_lockscreenOnly"]; 40 | [n setValue:@(self.poofsOnCancel) forKey:@"_poofsOnCancel"]; 41 | if (self.showAlternateActionMenu) { 42 | [n setValue:@[@"Test", @"Test1"] forKey:@"_alternateActionButtonTitles"]; 43 | [n setValue:@YES forKey:@"_alwaysShowAlternateActionMenu"]; 44 | } 45 | [NSUserNotificationCenter.defaultUserNotificationCenter deliverNotification:n]; 46 | } 47 | 48 | - (BOOL)userNotificationCenter:(NSUserNotificationCenter *)center shouldPresentNotification:(NSUserNotification *)notification { 49 | return YES; 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/INDDragAndDropImageWell.h: -------------------------------------------------------------------------------- 1 | // 2 | // INDDragAndDropImageWell.h 3 | // NSUserNotificationPrivate 4 | // 5 | // Created by Indragie Karunaratne on 12/8/2013. 6 | // Copyright (c) 2013 Indragie Karunaratne. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface INDDragAndDropImageWell : NSImageView 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/INDDragAndDropImageWell.m: -------------------------------------------------------------------------------- 1 | // 2 | // INDDragAndDropImageWell.m 3 | // NSUserNotificationPrivate 4 | // 5 | // Created by Indragie Karunaratne on 12/8/2013. 6 | // Copyright (c) 2013 Indragie Karunaratne. All rights reserved. 7 | // 8 | 9 | #import "INDDragAndDropImageWell.h" 10 | 11 | @implementation INDDragAndDropImageWell 12 | 13 | #pragma mark - Initialization 14 | 15 | - (id)initWithFrame:(NSRect)frameRect 16 | { 17 | if ((self = [super initWithFrame:frameRect])) { 18 | [self commonInitForINDDragAndDropImageWell]; 19 | } 20 | return self; 21 | } 22 | 23 | - (id)initWithCoder:(NSCoder *)aDecoder 24 | { 25 | if ((self = [super initWithCoder:aDecoder])) { 26 | [self commonInitForINDDragAndDropImageWell]; 27 | } 28 | return self; 29 | } 30 | 31 | - (void)commonInitForINDDragAndDropImageWell 32 | { 33 | [self registerForDraggedTypes:@[NSFilenamesPboardType]]; 34 | } 35 | 36 | #pragma mark - NSDraggingDestination 37 | 38 | - (NSDragOperation)draggingEntered:(id < NSDraggingInfo >)sender 39 | { 40 | NSPasteboard *pboard = [sender draggingPasteboard]; 41 | NSArray *files = [pboard propertyListForType:NSFilenamesPboardType]; 42 | for (NSString *file in files) { 43 | CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension, (__bridge CFStringRef)file.pathExtension, NULL); 44 | Boolean conforms = UTTypeConformsTo(UTI, kUTTypeImage); 45 | if (UTI) CFRelease(UTI); 46 | if (conforms) return NSDragOperationCopy; 47 | } 48 | return NSDragOperationNone; 49 | } 50 | 51 | - (BOOL)prepareForDragOperation:(id < NSDraggingInfo >)sender 52 | { 53 | return YES; 54 | } 55 | 56 | - (BOOL)performDragOperation:(id < NSDraggingInfo >)sender 57 | { 58 | NSPasteboard *pboard = [sender draggingPasteboard]; 59 | NSString *file = [pboard propertyListForType:NSFilenamesPboardType][0]; 60 | self.image = [[NSImage alloc] initWithContentsOfFile:file]; 61 | return (self.image != nil); 62 | } 63 | 64 | 65 | @end 66 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "mac", 5 | "size" : "16x16", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "mac", 10 | "size" : "16x16", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "mac", 15 | "size" : "32x32", 16 | "scale" : "1x" 17 | }, 18 | { 19 | "idiom" : "mac", 20 | "size" : "32x32", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "mac", 25 | "size" : "128x128", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "idiom" : "mac", 30 | "size" : "128x128", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "idiom" : "mac", 35 | "size" : "256x256", 36 | "scale" : "1x" 37 | }, 38 | { 39 | "idiom" : "mac", 40 | "size" : "256x256", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "mac", 45 | "size" : "512x512", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "mac", 50 | "size" : "512x512", 51 | "scale" : "2x" 52 | } 53 | ], 54 | "info" : { 55 | "version" : 1, 56 | "author" : "xcode" 57 | } 58 | } -------------------------------------------------------------------------------- /NSUserNotificationPrivate/NSUserNotificationPrivate-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIconFile 10 | 11 | CFBundleIdentifier 12 | com.indragie.${PRODUCT_NAME:rfc1034identifier} 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | ${PRODUCT_NAME} 17 | CFBundlePackageType 18 | APPL 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1 25 | LSMinimumSystemVersion 26 | ${MACOSX_DEPLOYMENT_TARGET} 27 | NSHumanReadableCopyright 28 | Copyright © 2013 Indragie Karunaratne. All rights reserved. 29 | NSMainNibFile 30 | MainMenu 31 | NSPrincipalClass 32 | NSApplication 33 | 34 | 35 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/NSUserNotificationPrivate-Prefix.pch: -------------------------------------------------------------------------------- 1 | // 2 | // Prefix header 3 | // 4 | // The contents of this file are implicitly included at the beginning of every source file. 5 | // 6 | 7 | #ifdef __OBJC__ 8 | #import 9 | #endif 10 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/NSUserNotification_Private.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Generated by class-dump 3.4 (64 bit). 3 | * 4 | * class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2012 by Steve Nygard. 5 | */ 6 | 7 | #import 8 | 9 | @interface NSUserNotification (INDPrivate) 10 | 11 | + (void)_closestDatesForStartDate:(id)arg1 earliestDate:(id)arg2 timeZone:(id)arg3 deliveryRepeatInterval:(id)arg4 returnDateBefore:(id *)arg5 returnDateAfter:(id *)arg6; 12 | + (id)allocWithZone:(struct _NSZone *)arg1; 13 | + (id)alloc; 14 | @property(readonly, nonatomic) NSData *_identityImageData; 15 | - (void)_setIdentityImage:(id)arg1 withIdentifier:(id)arg2; 16 | @property(readonly, nonatomic) BOOL _hasContentImage; 17 | @property(copy) NSImage *contentImage; // @dynamic contentImage; 18 | - (BOOL)_areIdentifiersEqual:(id)arg1; 19 | - (void)_setActivationType:(long long)arg1; 20 | - (void)_setSnoozedDate:(double)arg1; 21 | - (void)_setSnoozeInterval:(double)arg1; 22 | - (void)_setSnoozed:(BOOL)arg1; 23 | - (void)_setRemote:(BOOL)arg1; 24 | @property(readonly) NSDate *_nextFireDate; 25 | - (void)_setPresented:(BOOL)arg1; 26 | - (void)_setActualDeliveryDate:(id)arg1; 27 | - (id)copyWithZone:(struct _NSZone *)arg1; 28 | - (void)encodeWithCoder:(id)arg1; 29 | - (id)initWithCoder:(id)arg1; 30 | - (id)init; 31 | 32 | // Remaining properties 33 | @property BOOL _actionButtonIsSnooze; // @dynamic _actionButtonIsSnooze; 34 | @property(getter=_isAllDayEvent) BOOL _allDayEvent; // @dynamic _allDayEvent; 35 | @property(copy) NSArray *_alternateActionButtonTitles; // @dynamic _alternateActionButtonTitles; 36 | @property(readonly) unsigned long long _alternateActionIndex; // @dynamic _alternateActionIndex; 37 | @property BOOL _alwaysShowAlternateActionMenu; // @dynamic _alwaysShowAlternateActionMenu; 38 | @property unsigned long long _badgeCount; // @dynamic _badgeCount; 39 | @property BOOL _clearable; // @dynamic _clearable; 40 | @property(copy) NSString *_dateString; // @dynamic _dateString; 41 | @property(copy) NSDateComponents *_deliveryExpiration; // @dynamic _deliveryExpiration; 42 | @property BOOL _dismissAfterDuration; // @dynamic _dismissAfterDuration; 43 | @property unsigned long long _displayStyle; // @dynamic _displayStyle; 44 | @property(copy) NSDate *_eventDate; // @dynamic _eventDate; 45 | @property(copy) NSImage *_identityImage; // @dynamic _identityImage; 46 | @property BOOL _identityImageHasBorder; // @dynamic _identityImageHasBorder; 47 | @property BOOL _ignoresDoNotDisturb; // @dynamic _ignoresDoNotDisturb; 48 | @property(copy) NSURL *_imageURL; // @dynamic _imageURL; 49 | @property BOOL _lockscreenOnly; // @dynamic _lockscreenOnly; 50 | @property BOOL _persistent; // @dynamic _persistent; 51 | @property BOOL _poofsOnCancel; // @dynamic _poofsOnCancel; 52 | @property(readonly, getter=_isRemote) BOOL _remote; // @dynamic _remote; 53 | @property BOOL _showsButtons; // @dynamic _showsButtons; 54 | @property(readonly) double _snoozeInterval; // @dynamic _snoozeInterval; 55 | @property(readonly) BOOL _snoozed; // @dynamic _snoozed; 56 | @property(readonly) double _snoozedDate; // @dynamic _snoozedDate; 57 | @property(retain) id _storageID; // @dynamic _storageID; 58 | @property unsigned long long _style; // @dynamic _style; 59 | @property BOOL _substitutesEmojiInResponse; // @dynamic _substitutesEmojiInResponse; 60 | @property(copy) NSString *actionButtonTitle; // @dynamic actionButtonTitle; 61 | @property(readonly) long long activationType; // @dynamic activationType; 62 | @property(readonly) NSDate *actualDeliveryDate; // @dynamic actualDeliveryDate; 63 | @property(copy) NSDate *deliveryDate; // @dynamic deliveryDate; 64 | @property(copy) NSDateComponents *deliveryRepeatInterval; // @dynamic deliveryRepeatInterval; 65 | @property(copy) NSTimeZone *deliveryTimeZone; // @dynamic deliveryTimeZone; 66 | @property(copy) NSDateComponents *duration; // @dynamic duration; 67 | @property BOOL hasActionButton; // @dynamic hasActionButton; 68 | @property BOOL hasReplyButton; // @dynamic hasReplyButton; 69 | @property(copy) NSString *identifier; // @dynamic identifier; 70 | @property(copy) NSString *informativeText; // @dynamic informativeText; 71 | @property(copy) NSString *otherButtonTitle; // @dynamic otherButtonTitle; 72 | @property(readonly, getter=isPresented) BOOL presented; // @dynamic presented; 73 | @property(readonly, getter=isRemote) BOOL remote; // @dynamic remote; 74 | @property(readonly) NSAttributedString *response; // @dynamic response; 75 | @property(copy) NSString *responsePlaceholder; // @dynamic responsePlaceholder; 76 | @property(copy) NSString *soundName; // @dynamic soundName; 77 | @property(copy) NSString *subtitle; // @dynamic subtitle; 78 | @property(copy) NSString *title; // @dynamic title; 79 | @property(copy) NSDictionary *userInfo; // @dynamic userInfo; 80 | 81 | @end 82 | 83 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/en.lproj/Credits.rtf: -------------------------------------------------------------------------------- 1 | {\rtf0\ansi{\fonttbl\f0\fswiss Helvetica;} 2 | {\colortbl;\red255\green255\blue255;} 3 | \paperw9840\paperh8400 4 | \pard\tx560\tx1120\tx1680\tx2240\tx2800\tx3360\tx3920\tx4480\tx5040\tx5600\tx6160\tx6720\ql\qnatural 5 | 6 | \f0\b\fs24 \cf0 Engineering: 7 | \b0 \ 8 | Some people\ 9 | \ 10 | 11 | \b Human Interface Design: 12 | \b0 \ 13 | Some other people\ 14 | \ 15 | 16 | \b Testing: 17 | \b0 \ 18 | Hopefully not nobody\ 19 | \ 20 | 21 | \b Documentation: 22 | \b0 \ 23 | Whoever\ 24 | \ 25 | 26 | \b With special thanks to: 27 | \b0 \ 28 | Mom\ 29 | } 30 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /NSUserNotificationPrivate/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // NSUserNotificationPrivate 4 | // 5 | // Created by Indragie Karunaratne on 12/8/2013. 6 | // Copyright (c) 2013 Indragie Karunaratne. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | int main(int argc, const char * argv[]) 12 | { 13 | return NSApplicationMain(argc, argv); 14 | } 15 | -------------------------------------------------------------------------------- /NSUserNotificationPrivateTests/NSUserNotificationPrivateTests-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | ${EXECUTABLE_NAME} 9 | CFBundleIdentifier 10 | com.indragie.${PRODUCT_NAME:rfc1034identifier} 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundlePackageType 14 | BNDL 15 | CFBundleShortVersionString 16 | 1.0 17 | CFBundleSignature 18 | ???? 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /NSUserNotificationPrivateTests/NSUserNotificationPrivateTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSUserNotificationPrivateTests.m 3 | // NSUserNotificationPrivateTests 4 | // 5 | // Created by Indragie Karunaratne on 12/8/2013. 6 | // Copyright (c) 2013 Indragie Karunaratne. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSUserNotificationPrivateTests : XCTestCase 12 | 13 | @end 14 | 15 | @implementation NSUserNotificationPrivateTests 16 | 17 | - (void)setUp 18 | { 19 | [super setUp]; 20 | // Put setup code here. This method is called before the invocation of each test method in the class. 21 | } 22 | 23 | - (void)tearDown 24 | { 25 | // Put teardown code here. This method is called after the invocation of each test method in the class. 26 | [super tearDown]; 27 | } 28 | 29 | - (void)testExample 30 | { 31 | XCTFail(@"No implementation for \"%s\"", __PRETTY_FUNCTION__); 32 | } 33 | 34 | @end 35 | -------------------------------------------------------------------------------- /NSUserNotificationPrivateTests/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ### NSUserNotificationPrivate 2 | #### Private API showcase for NSUserNotification 3 | 4 | ![Example app](https://raw.github.com/indragiek/NSUserNotificationPrivate/master/images/example-ui.png) 5 | 6 | Around OS X, you can see quite a few features in the Notification Center API (`NSUserNotification` et. al) that aren't being exposed to developers publicly. For example, the way that iTunes uses album artwork in place of its icon. 7 | 8 | I class-dumped the `NSUserNotification` header and quickly found how to access these features and put together an example app to make it easy to try each one. Here's an overview of the private stuff I found (there's probably more): 9 | 10 | (**NOTE: This should go without saying, but using any of this will result in your app being rejected from the MAS and potentially breaking if the APIs change. This is just for fun.**) 11 | 12 | #### Identity Image 13 | 14 | This is how iTunes swaps in album artwork for the icon. When the `_identityImage` property is set, it shows the set image in place of the icon and moves the app icon to the left of the notification title. The default value of `nil` makes it use the app icon. The result looks like this: 15 | 16 | ![Identity image](https://raw.github.com/indragiek/NSUserNotificationPrivate/master/images/itunes-notification.png) 17 | 18 | There's even an option to turn off the default border by setting the `_identityImageHasBorder` to `NO`. 19 | 20 | #### Ignore Do Not Disturb 21 | 22 | The `_ignoresDoNotDisturb` property allows you to override the user's Do Not Disturb settings and post the notification anyways. Default value is `NO`. 23 | 24 | #### Lockscreen Only 25 | 26 | The `_lockscreenOnly` property allows you to make it so that a notification is only posted if the computer is locked. This means that you can only see the missed notification in the lock screen and it disappears as soon as you unlock the computer. Default value is `NO`. 27 | 28 | #### Poofs on Cancel 29 | 30 | If the notification type is set to "Alert", the `_poofsOnCancel` property lets you configure whether there should be a poof animation when the Cancel button is clicked. Default value is `YES`. 31 | 32 | #### Show Alternate Action Menu 33 | 34 | If the notification type is set to "Alert", the `alternateActionButtonTitles` property lets you set an array of additional menu item titles to be shown in an action menu that can be accessed by hovering on the Action button and clicking on the arrow. It looks like this: 35 | 36 | ![Action items](https://raw.github.com/indragiek/NSUserNotificationPrivate/master/images/custom-items.png) 37 | 38 | Once a notification is handled, the index of the action can be retrieved using the `_alternateActionIndex` property. 39 | 40 | ### License 41 | 42 | There's hardly any code here, do whatever you want with it. -------------------------------------------------------------------------------- /images/custom-items.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/indragiek/NSUserNotificationPrivate/ad4fc22dd48495e4b5e8a6dc564113a8650338b9/images/custom-items.png -------------------------------------------------------------------------------- /images/example-ui.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/indragiek/NSUserNotificationPrivate/ad4fc22dd48495e4b5e8a6dc564113a8650338b9/images/example-ui.png -------------------------------------------------------------------------------- /images/itunes-notification.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/indragiek/NSUserNotificationPrivate/ad4fc22dd48495e4b5e8a6dc564113a8650338b9/images/itunes-notification.png --------------------------------------------------------------------------------