├── .gitignore ├── KTPomodoro WatchKit App ├── Base.lproj │ ├── Interface.storyboard │ └── KTWatchTaskCompletedNotificationStoryboard.storyboard ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── AppIcon-24@2x.png │ │ ├── AppIcon-27.5@2x.png │ │ ├── AppIcon-80@2x copy.png │ │ ├── AppIcon-88@2x.png │ │ └── Contents.json │ ├── LaunchImage.launchimage │ │ └── Contents.json │ ├── circles_0.imageset │ │ ├── Contents.json │ │ └── circles_0@2x.png │ ├── circles_1.imageset │ │ ├── Contents.json │ │ └── circles_1@2x.png │ ├── circles_10.imageset │ │ ├── Contents.json │ │ └── circles_10@2x.png │ ├── circles_11.imageset │ │ ├── Contents.json │ │ └── circles_11@2x.png │ ├── circles_12.imageset │ │ ├── Contents.json │ │ └── circles_12@2x.png │ ├── circles_2.imageset │ │ ├── Contents.json │ │ └── circles_2@2x.png │ ├── circles_3.imageset │ │ ├── Contents.json │ │ └── circles_3@2x.png │ ├── circles_4.imageset │ │ ├── Contents.json │ │ └── circles_4@2x.png │ ├── circles_5.imageset │ │ ├── Contents.json │ │ └── circles_5@2x.png │ ├── circles_6.imageset │ │ ├── Contents.json │ │ └── circles_6@2x.png │ ├── circles_7.imageset │ │ ├── Contents.json │ │ └── circles_7@2x.png │ ├── circles_8.imageset │ │ ├── Contents.json │ │ └── circles_8@2x.png │ ├── circles_9.imageset │ │ ├── Contents.json │ │ └── circles_9@2x.png │ ├── circles_background.imageset │ │ ├── Contents.json │ │ └── circles_background@2x.png │ ├── listview_background_red.imageset │ │ ├── Contents.json │ │ ├── listview_background_red.png │ │ └── listview_background_red@2x.png │ └── pomodoro_watch_activity_background.imageset │ │ ├── Contents.json │ │ └── pomodoro_watch_activity_background@2x.png └── Info.plist ├── KTPomodoro WatchKit Extension ├── Images.xcassets │ └── MyImage.imageset │ │ └── Contents.json ├── Info.plist ├── KTPomodoro WatchKit Extension.entitlements ├── KTWatchAddTaskRowInterfaceController.h ├── KTWatchAddTaskRowInterfaceController.m ├── KTWatchGlanceController.h ├── KTWatchGlanceController.m ├── KTWatchInterfaceAddTaskInterfaceController.h ├── KTWatchInterfaceAddTaskInterfaceController.m ├── KTWatchInterfaceController.h ├── KTWatchInterfaceController.m ├── KTWatchPomodoroCompletedNotificationController.h ├── KTWatchPomodoroCompletedNotificationController.m ├── KTWatchTaskCompletedNotificationController.h ├── KTWatchTaskCompletedNotificationController.m ├── KTWatchTasksListInterfaceController.h ├── KTWatchTasksListInterfaceController.m ├── KTWatchTasksRowInterfaceController.h ├── KTWatchTasksRowInterfaceController.m ├── PomodoroFinishedPayload.apns └── TaskCompletedPayload.apns ├── KTPomodoro.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ └── contents.xcworkspacedata └── xcuserdata │ └── ktang.xcuserdatad │ └── xcschemes │ ├── KTPomodoro.xcscheme │ └── xcschememanagement.plist ├── KTPomodoro ├── Base.lproj │ └── LaunchScreen.xib ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── tomato_app.imageset │ │ ├── Contents.json │ │ └── tomato_app@2x.png ├── Info.plist ├── KTAppDelegate.h ├── KTAppDelegate.m ├── KTPomodoro.entitlements ├── Model │ ├── KTActiveActivityState.h │ ├── KTActiveActivityState.m │ ├── KTCoreDataStack.h │ ├── KTCoreDataStack.m │ ├── KTPomodoroActivityModel.h │ ├── KTPomodoroActivityModel.m │ ├── KTPomodoroModel.xcdatamodeld │ │ └── KTPomodoroModel.xcdatamodel │ │ │ └── contents │ ├── KTPomodoroTaskConstants.h │ └── KTPomodoroTaskConstants.m ├── Resources │ ├── KTPomodoroTableViewCell.xib │ └── Shared │ │ └── Settings-Watch.bundle │ │ ├── Root.plist │ │ └── en.lproj │ │ └── Root.strings ├── Utils │ ├── KTActivityManager.h │ ├── KTActivityManager.m │ ├── KTSharedUserDefaults.h │ └── KTSharedUserDefaults.m ├── View Controller │ ├── KTPomodoroTableViewCell.h │ ├── KTPomodoroTableViewCell.m │ ├── KTPomodoroTableViewController.h │ └── KTPomodoroTableViewController.m └── main.m ├── KTPomodoroTests ├── Info.plist └── KTPomodoroTests.m ├── Mockup └── KTPomodoro - app.sketch └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | xcuserdata 3 | Logs/ 4 | /build/ 5 | instruments.out 6 | instrumentscli*.trace 7 | *.pbxuser 8 | *.mode2v3 9 | *.mode1v3 10 | xcuserdata 11 | *~ 12 | *.DS_Store 13 | *.swp 14 | *.out 15 | *.xccheckout 16 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Base.lproj/Interface.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 27 | 28 | 29 | 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 | 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 | 119 | 120 | 121 | 122 | 123 | 127 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 177 | 178 | 179 | 180 | 181 | 182 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 197 | 201 | 202 | 203 | 204 | 205 | 209 | 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 | 254 | 255 | 256 | 257 | 258 | 259 | 260 | 261 | 262 | 263 | 264 | 265 | 266 | 267 | 268 | 269 | 270 | 271 | 272 | 273 | 274 | 275 | 279 | 280 | 281 | 282 | 283 | 284 | 285 | 289 | 293 | 294 | 295 | 296 | 297 | 298 | 299 | 300 | 301 | 302 | 303 | 304 | 305 | 306 | 307 | 308 | 309 | 310 | 311 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Base.lproj/KTWatchTaskCompletedNotificationStoryboard.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 53 | 57 | 58 | 59 | 60 | 61 | 65 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/AppIcon.appiconset/AppIcon-24@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/AppIcon.appiconset/AppIcon-24@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/AppIcon.appiconset/AppIcon-27.5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/AppIcon.appiconset/AppIcon-27.5@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/AppIcon.appiconset/AppIcon-80@2x copy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/AppIcon.appiconset/AppIcon-80@2x copy.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/AppIcon.appiconset/AppIcon-88@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/AppIcon.appiconset/AppIcon-88@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "24x24", 5 | "idiom" : "watch", 6 | "scale" : "2x", 7 | "filename" : "AppIcon-24@2x.png", 8 | "role" : "notificationCenter", 9 | "subtype" : "38mm" 10 | }, 11 | { 12 | "size" : "27.5x27.5", 13 | "idiom" : "watch", 14 | "scale" : "2x", 15 | "filename" : "AppIcon-27.5@2x.png", 16 | "role" : "notificationCenter", 17 | "subtype" : "42mm" 18 | }, 19 | { 20 | "size" : "29x29", 21 | "idiom" : "watch", 22 | "role" : "companionSettings", 23 | "scale" : "2x" 24 | }, 25 | { 26 | "size" : "29x29", 27 | "idiom" : "watch", 28 | "role" : "companionSettings", 29 | "scale" : "3x" 30 | }, 31 | { 32 | "size" : "40x40", 33 | "idiom" : "watch", 34 | "scale" : "2x", 35 | "filename" : "AppIcon-80@2x copy.png", 36 | "role" : "appLauncher", 37 | "subtype" : "38mm" 38 | }, 39 | { 40 | "size" : "44x44", 41 | "idiom" : "watch", 42 | "scale" : "2x", 43 | "filename" : "AppIcon-88@2x.png", 44 | "role" : "appLauncher", 45 | "subtype" : "42mm" 46 | }, 47 | { 48 | "size" : "86x86", 49 | "idiom" : "watch", 50 | "scale" : "2x", 51 | "role" : "quickLook", 52 | "subtype" : "38mm" 53 | }, 54 | { 55 | "size" : "98x98", 56 | "idiom" : "watch", 57 | "scale" : "2x", 58 | "role" : "quickLook", 59 | "subtype" : "42mm" 60 | }, 61 | { 62 | "scale" : "2x", 63 | "idiom" : "watch", 64 | "unassigned" : true, 65 | "role" : "notificationCenter", 66 | "subtype" : "38mm" 67 | }, 68 | { 69 | "scale" : "2x", 70 | "idiom" : "watch", 71 | "unassigned" : true, 72 | "role" : "notificationCenter", 73 | "subtype" : "38mm" 74 | }, 75 | { 76 | "scale" : "2x", 77 | "idiom" : "watch", 78 | "unassigned" : true, 79 | "role" : "notificationCenter", 80 | "subtype" : "42mm" 81 | }, 82 | { 83 | "idiom" : "watch", 84 | "unassigned" : true, 85 | "role" : "companionSettings", 86 | "scale" : "3x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "watch", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "8.0", 8 | "subtype" : "38mm", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "orientation" : "portrait", 13 | "idiom" : "watch", 14 | "extent" : "full-screen", 15 | "minimum-system-version" : "8.0", 16 | "subtype" : "42mm", 17 | "scale" : "2x" 18 | } 19 | ], 20 | "info" : { 21 | "version" : 1, 22 | "author" : "xcode" 23 | } 24 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_0.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_0@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_0.imageset/circles_0@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_0.imageset/circles_0@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_1.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_1@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_1.imageset/circles_1@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_1.imageset/circles_1@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_10.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_10@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_10.imageset/circles_10@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_10.imageset/circles_10@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_11.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_11@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_11.imageset/circles_11@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_11.imageset/circles_11@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_12.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_12@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_12.imageset/circles_12@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_12.imageset/circles_12@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_2.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_2@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_2.imageset/circles_2@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_2.imageset/circles_2@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_3.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_3@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_3.imageset/circles_3@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_3.imageset/circles_3@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_4.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_4@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_4.imageset/circles_4@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_4.imageset/circles_4@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_5.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_5@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_5.imageset/circles_5@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_5.imageset/circles_5@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_6.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_6@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_6.imageset/circles_6@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_6.imageset/circles_6@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_7.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_7@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_7.imageset/circles_7@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_7.imageset/circles_7@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_8.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_8@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_8.imageset/circles_8@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_8.imageset/circles_8@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_9.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_9@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_9.imageset/circles_9@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_9.imageset/circles_9@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_background.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "circles_background@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/circles_background.imageset/circles_background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/circles_background.imageset/circles_background@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/listview_background_red.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x", 6 | "filename" : "listview_background_red.png" 7 | }, 8 | { 9 | "idiom" : "universal", 10 | "scale" : "2x", 11 | "filename" : "listview_background_red@2x.png" 12 | }, 13 | { 14 | "idiom" : "universal", 15 | "scale" : "3x" 16 | } 17 | ], 18 | "info" : { 19 | "version" : 1, 20 | "author" : "xcode" 21 | } 22 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/listview_background_red.imageset/listview_background_red.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/listview_background_red.imageset/listview_background_red.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/listview_background_red.imageset/listview_background_red@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/listview_background_red.imageset/listview_background_red@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/pomodoro_watch_activity_background.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "pomodoro_watch_activity_background@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Images.xcassets/pomodoro_watch_activity_background.imageset/pomodoro_watch_activity_background@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro WatchKit App/Images.xcassets/pomodoro_watch_activity_background.imageset/pomodoro_watch_activity_background@2x.png -------------------------------------------------------------------------------- /KTPomodoro WatchKit App/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | KTPomodoro 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | com.corgitoergosum.KTPomodoro.watchkitapp 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 | UISupportedInterfaceOrientations 26 | 27 | UIInterfaceOrientationPortrait 28 | UIInterfaceOrientationPortraitUpsideDown 29 | 30 | WKCompanionAppBundleIdentifier 31 | com.corgitoergosum.KTPomodoro 32 | WKWatchKitApp 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/Images.xcassets/MyImage.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "idiom" : "universal", 13 | "scale" : "3x" 14 | } 15 | ], 16 | "info" : { 17 | "version" : 1, 18 | "author" : "xcode" 19 | } 20 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | KTPomodoro WatchKit Extension 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | com.corgitoergosum.KTPomodoro.watchkitextension 13 | CFBundleInfoDictionaryVersion 14 | 6.0 15 | CFBundleName 16 | $(PRODUCT_NAME) 17 | CFBundlePackageType 18 | XPC! 19 | CFBundleShortVersionString 20 | 1.0 21 | CFBundleSignature 22 | ???? 23 | CFBundleVersion 24 | 1.0 25 | NSExtension 26 | 27 | NSExtensionAttributes 28 | 29 | WKAppBundleIdentifier 30 | com.corgitoergosum.KTPomodoro.watchkitapp 31 | 32 | NSExtensionPointIdentifier 33 | com.apple.watchkit 34 | 35 | RemoteInterfacePrincipalClass 36 | InterfaceController 37 | 38 | 39 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTPomodoro WatchKit Extension.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.corgitoergosum.KTPomodoro 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchAddTaskRowInterfaceController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchAddTaskRowInterfaceController.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/9/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTWatchAddTaskRowInterfaceController : NSObject 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchAddTaskRowInterfaceController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchAddTaskRowInterfaceController.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/9/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTWatchAddTaskRowInterfaceController.h" 10 | 11 | @implementation KTWatchAddTaskRowInterfaceController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchGlanceController.h: -------------------------------------------------------------------------------- 1 | // 2 | // GlanceController.h 3 | // KTPomodoro WatchKit Extension 4 | // 5 | // Created by Kenny Tang on 1/1/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface KTWatchGlanceController : WKInterfaceController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchGlanceController.m: -------------------------------------------------------------------------------- 1 | // 2 | // GlanceController.m 3 | // KTPomodoro WatchKit Extension 4 | // 5 | // Created by Kenny Tang on 1/1/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTWatchGlanceController.h" 10 | 11 | 12 | @interface KTWatchGlanceController() 13 | 14 | @end 15 | 16 | 17 | @implementation KTWatchGlanceController 18 | 19 | - (void)awakeWithContext:(id)context { 20 | [super awakeWithContext:context]; 21 | 22 | // Configure interface objects here. 23 | } 24 | 25 | - (void)willActivate { 26 | // This method is called when watch view controller is about to be visible to user 27 | [super willActivate]; 28 | } 29 | 30 | - (void)didDeactivate { 31 | // This method is called when watch view controller is no longer visible 32 | [super didDeactivate]; 33 | } 34 | 35 | @end 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchInterfaceAddTaskInterfaceController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchInterfaceAddTaskInterfaceController.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/9/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface KTWatchInterfaceAddTaskInterfaceController : WKInterfaceController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchInterfaceAddTaskInterfaceController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchInterfaceAddTaskInterfaceController.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/9/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTWatchInterfaceAddTaskInterfaceController.h" 10 | #import "KTCoreDataStack.h" 11 | 12 | @interface KTWatchInterfaceAddTaskInterfaceController() 13 | 14 | @property (nonatomic) NSString *taskName; 15 | @property (nonatomic) NSInteger expectedPomodoros; 16 | @property (weak, nonatomic) IBOutlet WKInterfaceLabel *expectedPomodorosLabel; 17 | 18 | @property (weak, nonatomic) IBOutlet WKInterfaceButton *confirmButton; 19 | @property (weak, nonatomic) IBOutlet WKInterfaceButton *taskNameButton; 20 | 21 | @end 22 | 23 | 24 | @implementation KTWatchInterfaceAddTaskInterfaceController 25 | 26 | - (void)awakeWithContext:(id)context { 27 | [super awakeWithContext:context]; 28 | 29 | // Configure interface objects here. 30 | } 31 | 32 | - (void)willActivate { 33 | // This method is called when watch view controller is about to be visible to user 34 | [super willActivate]; 35 | self.expectedPomodoros = 1; 36 | } 37 | 38 | - (void)didDeactivate { 39 | // This method is called when watch view controller is no longer visible 40 | [super didDeactivate]; 41 | } 42 | 43 | #pragma mark - Action handlers 44 | 45 | - (IBAction)enterTaskNameButtonTapped { 46 | 47 | [self presentTextInputControllerWithSuggestions:@[ 48 | @"Watch Cat videos", 49 | @"Exercise", 50 | @"Do some writing", 51 | @"Read a book", 52 | @"Work"] allowedInputMode:WKTextInputModeAllowAnimatedEmoji completion:^(NSArray *results) { 53 | NSLog(@"enterTaskNameButtonTapped results: %@", results); 54 | if ([results count]) { 55 | self.taskName = results[0]; 56 | if (self.taskName.length) { 57 | [self.taskNameButton setTitle:self.taskName]; 58 | [self.confirmButton setEnabled:YES]; 59 | [self.confirmButton setHidden:NO]; 60 | } 61 | } 62 | }]; 63 | } 64 | 65 | - (IBAction)pomodorosSliderValueChanged:(float)value { 66 | self.expectedPomodoros = (NSUInteger)floor(value); 67 | [self.expectedPomodorosLabel setText:[NSString stringWithFormat:@"%@", @(self.expectedPomodoros)]]; 68 | } 69 | 70 | 71 | - (IBAction)confirmButtonTapped { 72 | 73 | [[KTCoreDataStack sharedInstance] createNewTask:self.taskName taskDesc:@"" pomodoros:self.expectedPomodoros]; 74 | 75 | [[KTCoreDataStack sharedInstance] saveContext]; 76 | 77 | [self dismissController]; 78 | } 79 | 80 | @end 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchInterfaceController.h: -------------------------------------------------------------------------------- 1 | // 2 | // InterfaceController.h 3 | // KTPomodoro WatchKit Extension 4 | // 5 | // Created by Kenny Tang on 1/1/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface KTWatchInterfaceController : WKInterfaceController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchInterfaceController.m: -------------------------------------------------------------------------------- 1 | // 2 | // InterfaceController.m 3 | // KTPomodoro WatchKit Extension 4 | // 5 | // Created by Kenny Tang on 1/1/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTWatchInterfaceController.h" 10 | #import "KTActivityManager.h" 11 | #import "KTCoreDataStack.h" 12 | #import "KTPomodoroActivityModel.h" 13 | #import "KTPomodoroTaskConstants.h" 14 | #import "KTSharedUserDefaults.h" 15 | 16 | @interface KTWatchInterfaceController() 17 | 18 | @property (nonatomic) KTPomodoroActivityModel *activity; 19 | @property (weak, nonatomic) IBOutlet WKInterfaceLabel *taskNameLabel; 20 | @property (weak, nonatomic) IBOutlet WKInterfaceLabel *plannedPomoLabel; 21 | @property (weak, nonatomic) IBOutlet WKInterfaceLabel *remainingPomoLabel; 22 | 23 | @property (weak, nonatomic) IBOutlet WKInterfaceLabel *timeLabel; 24 | @property (weak, nonatomic) IBOutlet WKInterfaceGroup *timerRingInterfaceGroup; 25 | 26 | @property (nonatomic) NSString *currentBackgroundImageString; 27 | 28 | @end 29 | 30 | @implementation KTWatchInterfaceController 31 | 32 | 33 | 34 | - (void)awakeWithContext:(id)context { 35 | [super awakeWithContext:context]; 36 | 37 | KTPomodoroActivityModel *activity = (KTPomodoroActivityModel*)context; 38 | self.activity = activity; 39 | [self.taskNameLabel setText:activity.name]; 40 | [self.plannedPomoLabel setText:[activity.expected_pomo stringValue]]; 41 | self.currentBackgroundImageString = @""; 42 | [self.remainingPomoLabel setText:[activity.expected_pomo stringValue]]; 43 | 44 | [self registerUserDefaultChanges]; 45 | [self clearAllMenuItems]; 46 | 47 | KTActivityManager *activityManager = [KTActivityManager sharedInstance]; 48 | if (activity.status.integerValue == KTPomodoroActivityStatusInProgress){ 49 | 50 | if ([KTActivityManager sharedInstance].activity != self.activity) { 51 | 52 | [[KTActivityManager sharedInstance] startActivity:activity error:nil]; 53 | } 54 | 55 | // continue task 56 | activityManager.delegate = self; 57 | 58 | [self addMenuItemWithItemIcon:WKMenuItemIconBlock title:@"Interrupt" action:@selector(interruptTask:)]; 59 | [self addMenuItemWithItemIcon:WKMenuItemIconDecline title:@"Stop" action:@selector(stopTask:)]; 60 | 61 | } else { 62 | 63 | if (![activityManager hasOtherActiveActivityInSharedState:activity.activityID]) { 64 | [self addMenuItemWithItemIcon:WKMenuItemIconPlay title:@"Start" action:@selector(startTask:)]; 65 | [self addMenuItemWithItemIcon:WKMenuItemIconTrash title:@"Delete" action:@selector(deleteTask:)]; 66 | } 67 | } 68 | 69 | } 70 | 71 | 72 | - (void)didDeactivate { 73 | // This method is called when watch view controller is no longer visible 74 | [super didDeactivate]; 75 | [self unregisterUserDefaultChanges]; 76 | [[KTCoreDataStack sharedInstance] saveContext]; 77 | 78 | } 79 | 80 | #pragma mark - Private 81 | 82 | #pragma mark - awakeWithContext: helper methods 83 | 84 | - (void)registerUserDefaultChanges 85 | { 86 | [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(userDefaultsUpdated) name:NSUserDefaultsDidChangeNotification object:nil]; 87 | } 88 | 89 | #pragma mark - didDeactivate helper methods 90 | 91 | - (void)unregisterUserDefaultChanges 92 | { 93 | [[NSNotificationCenter defaultCenter] removeObserver:self name:NSUserDefaultsDidChangeNotification object:nil]; 94 | } 95 | 96 | #pragma mark - registerUserDefaultChanges helper methods 97 | 98 | - (void)userDefaultsUpdated 99 | { 100 | BOOL shouldAutoComplete = [KTSharedUserDefaults shouldAutoDeleteCompletedActivites]; 101 | NSUInteger breakDuration = [KTSharedUserDefaults breakDuration]; 102 | NSUInteger pomoDuration = [KTSharedUserDefaults pomoDuration]; 103 | NSLog(@"shouldAutoComplete: %i", shouldAutoComplete); 104 | NSLog(@"breakDuration: %@", @(breakDuration)); 105 | NSLog(@"pomoDuration: %@", @(pomoDuration)); 106 | } 107 | 108 | 109 | #pragma mark - Action Outlets 110 | 111 | - (void)interruptTask:(id)sender 112 | { 113 | [self stopTask:sender]; 114 | 115 | // increment interrupt 116 | NSInteger interruptions = [self.activity.interruptions integerValue]; 117 | self.activity.interruptions = @(++interruptions); 118 | 119 | } 120 | 121 | - (void)startTask:(id)sender 122 | { 123 | NSError *startTaskError; 124 | KTActivityManager *activityManager = [KTActivityManager sharedInstance]; 125 | activityManager.delegate = self; 126 | [activityManager startActivity:self.activity error:&startTaskError]; 127 | 128 | if (!startTaskError) { 129 | [self.timeLabel setText:[NSString stringWithFormat:@"%@:00", @([KTActivityManager pomodoroDurationMinutes])]]; 130 | 131 | [self clearAllMenuItems]; 132 | [self addMenuItemWithItemIcon:WKMenuItemIconBlock title:@"Interrupt" action:@selector(interruptTask:)]; 133 | [self addMenuItemWithItemIcon:WKMenuItemIconDecline title:@"Stop" action:@selector(stopTask:)]; 134 | } 135 | } 136 | 137 | - (void)stopTask:(id)sender 138 | { 139 | [[KTActivityManager sharedInstance] stopActivity]; 140 | [self resetMenuItemsTimeLabel]; 141 | [self resetBackgroundImage]; 142 | } 143 | 144 | - (void)taskCompleted 145 | { 146 | [self resetMenuItemsTimeLabel]; 147 | 148 | if ([self shouldAutoDeleteCompletedTasks]) { 149 | [self deleteTask:nil]; 150 | } 151 | 152 | } 153 | 154 | - (void)deleteTask:(id)sender 155 | { 156 | [self.timeLabel setText:@"00:00"]; 157 | [[KTActivityManager sharedInstance] stopActivity]; 158 | [[[KTCoreDataStack sharedInstance] managedObjectContext] deleteObject:self.activity]; 159 | [[KTCoreDataStack sharedInstance] saveContext]; 160 | [self popController]; 161 | } 162 | 163 | - (void)openApp:(id)sender 164 | { 165 | // NSDictionary *userInfo = @{@"taskID" : self.task.name}; 166 | // [WKInterfaceController openParentApplication:userInfo reply:^(NSDictionary *replyInfo, NSError *error) { 167 | // NSLog(@"error: %@", error); 168 | // }]; 169 | 170 | 171 | [self presentTextInputControllerWithSuggestions:nil allowedInputMode:WKTextInputModePlain completion:^(NSArray *results) { 172 | NSLog(@"results: %@", results); 173 | }]; 174 | } 175 | 176 | #pragma mark - taskCompleted helper methods 177 | 178 | - (void)resetBackgroundImage 179 | { 180 | [self.timerRingInterfaceGroup setBackgroundImageNamed:@"circles_background"]; 181 | } 182 | 183 | - (void)resetMenuItemsTimeLabel 184 | { 185 | [self clearAllMenuItems]; 186 | [self addMenuItemWithItemIcon:WKMenuItemIconPlay title:@"Start" action:@selector(startTask:)]; 187 | [self addMenuItemWithItemIcon:WKMenuItemIconTrash title:@"Delete" action:@selector(deleteTask:)]; 188 | [self.timeLabel setText:@"00:00"]; 189 | 190 | } 191 | 192 | - (BOOL)shouldAutoDeleteCompletedTasks 193 | { 194 | return [KTSharedUserDefaults shouldAutoDeleteCompletedActivites]; 195 | } 196 | 197 | 198 | #pragma mark - KTActivityManagerDelegate methods 199 | 200 | - (void)activityManager:(KTActivityManager *)manager activityPausedForBreak:(NSUInteger)elapsedTime 201 | { 202 | 203 | } 204 | 205 | - (void)activityManager:(KTActivityManager *)manager activityDidUpdate:(KTPomodoroActivityModel *)activity 206 | { 207 | 208 | [self updateTimerBackgroundImage:activity]; 209 | 210 | 211 | NSString *displayMinutesString = [self formatTimeIntToTwoDigitsString:[KTActivityManager pomoRemainingMinutes:activity.current_pomo_elapsed_time_int]]; 212 | 213 | NSString *displaySecsString = [self formatTimeIntToTwoDigitsString:[KTActivityManager pomoRemainingSecsInCurrentMinute:activity.current_pomo_elapsed_time_int]]; 214 | 215 | NSString *remainingTimeString = [NSString stringWithFormat:@"%@:%@", displayMinutesString, displaySecsString]; 216 | 217 | [self.timeLabel setText:remainingTimeString]; 218 | 219 | NSUInteger remainingPomo = [activity.expected_pomo integerValue] - [activity.actual_pomo integerValue]; 220 | 221 | [self.remainingPomoLabel setText:[@(remainingPomo) stringValue]]; 222 | 223 | if ([activity.status integerValue] == KTPomodoroActivityStatusCompleted) { 224 | [self.taskNameLabel setText:@"Yeah done!"]; 225 | [self taskCompleted]; 226 | } 227 | 228 | } 229 | 230 | #pragma mark - activityManager:activityDidUpdate: helper method 231 | 232 | - (NSString*)formatTimeIntToTwoDigitsString:(NSUInteger)time 233 | { 234 | NSString *displayString = (time>9)?[@(time) stringValue]:[NSString stringWithFormat:@"0%@", @(time)]; 235 | return displayString; 236 | } 237 | 238 | - (void)updateTimerBackgroundImage:(KTPomodoroActivityModel *)activity 239 | { 240 | NSUInteger elapsedSecs = activity.current_pomo_elapsed_time_int; 241 | NSUInteger elapsedSections = elapsedSecs/(([KTActivityManager pomodoroDurationMinutes]*60)/12); 242 | 243 | NSString *backgroundImageString = [NSString stringWithFormat:@"circles_%@", @(elapsedSections)]; 244 | NSLog(@"backgroundImageString: %@", backgroundImageString); 245 | if (![self.currentBackgroundImageString isEqualToString:backgroundImageString]) { 246 | self.currentBackgroundImageString = backgroundImageString; 247 | [self.timerRingInterfaceGroup setBackgroundImageNamed:backgroundImageString]; 248 | } 249 | } 250 | 251 | 252 | 253 | @end 254 | 255 | 256 | 257 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchPomodoroCompletedNotificationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchNotificationController.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/8/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface KTWatchPomodoroCompletedNotificationController : WKUserNotificationInterfaceController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchPomodoroCompletedNotificationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchNotificationController.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/8/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTWatchPomodoroCompletedNotificationController.h" 10 | 11 | 12 | @interface KTWatchPomodoroCompletedNotificationController() 13 | 14 | @property (nonatomic) IBOutlet WKInterfaceLabel *alertLabel; 15 | @property (nonatomic) IBOutlet WKInterfaceLabel *taskNameLabel; 16 | @property (nonatomic) IBOutlet WKInterfaceLabel *remainingPomodorosLabel; 17 | 18 | @end 19 | 20 | 21 | @implementation KTWatchPomodoroCompletedNotificationController 22 | 23 | - (instancetype)init { 24 | self = [super init]; 25 | if (self){ 26 | // Initialize variables here. 27 | // Configure interface objects here. 28 | 29 | } 30 | return self; 31 | } 32 | 33 | - (void)willActivate { 34 | // This method is called when watch view controller is about to be visible to user 35 | [super willActivate]; 36 | } 37 | 38 | - (void)didDeactivate { 39 | // This method is called when watch view controller is no longer visible 40 | [super didDeactivate]; 41 | } 42 | 43 | - (void)didReceiveLocalNotification:(UILocalNotification *)localNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler { 44 | 45 | NSLog(@"didReceiveLocalNotification"); 46 | 47 | 48 | // This method is called when a local notification needs to be presented. 49 | // Implement it if you use a dynamic notification interface. 50 | // Populate your dynamic notification inteface as quickly as possible. 51 | // 52 | // After populating your dynamic notification interface call the completion block. 53 | completionHandler(WKUserNotificationInterfaceTypeCustom); 54 | } 55 | 56 | - (void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler { 57 | 58 | NSLog(@"didReceiveRemoteNotification"); 59 | 60 | NSString *alertString = remoteNotification[@"aps"][@"alert"]; 61 | 62 | NSDictionary *payload = remoteNotification[@"payload"]; 63 | // NSString *taskID = payload[@"id"]; 64 | NSString *taskName = payload[@"name"]; 65 | NSNumber *remainingPomos = payload[@"pomos_left"]; 66 | [self.taskNameLabel setText:taskName]; 67 | [self.remainingPomodorosLabel setText:[remainingPomos stringValue]]; 68 | 69 | [self.alertLabel setText:alertString]; 70 | 71 | // This method is called when a remote notification needs to be presented. 72 | // Implement it if you use a dynamic notification interface. 73 | // Populate your dynamic notification inteface as quickly as possible. 74 | // 75 | // After populating your dynamic notification interface call the completion block. 76 | completionHandler(WKUserNotificationInterfaceTypeCustom); 77 | } 78 | 79 | @end 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchTaskCompletedNotificationController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchTaskCompletedNotificationController.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/9/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface KTWatchTaskCompletedNotificationController : WKUserNotificationInterfaceController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchTaskCompletedNotificationController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchTaskCompletedNotificationController.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/9/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTWatchTaskCompletedNotificationController.h" 10 | 11 | 12 | @interface KTWatchTaskCompletedNotificationController() 13 | 14 | @property (nonatomic) IBOutlet WKInterfaceLabel *alertLabel; 15 | @property (nonatomic) IBOutlet WKInterfaceLabel *plannedPomosLabel; 16 | @property (nonatomic) IBOutlet WKInterfaceLabel *actualPomosLabel; 17 | @property (nonatomic) IBOutlet WKInterfaceLabel *interruptionsLabel; 18 | 19 | @end 20 | 21 | 22 | @implementation KTWatchTaskCompletedNotificationController 23 | 24 | - (instancetype)init { 25 | self = [super init]; 26 | if (self){ 27 | // Initialize variables here. 28 | // Configure interface objects here. 29 | 30 | } 31 | return self; 32 | } 33 | 34 | - (void)willActivate { 35 | // This method is called when watch view controller is about to be visible to user 36 | [super willActivate]; 37 | } 38 | 39 | - (void)didDeactivate { 40 | // This method is called when watch view controller is no longer visible 41 | [super didDeactivate]; 42 | } 43 | 44 | - (void)didReceiveLocalNotification:(UILocalNotification *)localNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler { 45 | 46 | 47 | NSLog(@"didReceiveLocalNotification"); 48 | 49 | // This method is called when a local notification needs to be presented. 50 | // Implement it if you use a dynamic notification interface. 51 | // Populate your dynamic notification inteface as quickly as possible. 52 | // 53 | // After populating your dynamic notification interface call the completion block. 54 | completionHandler(WKUserNotificationInterfaceTypeCustom); 55 | } 56 | 57 | - (void)didReceiveRemoteNotification:(NSDictionary *)remoteNotification withCompletion:(void (^)(WKUserNotificationInterfaceType))completionHandler { 58 | 59 | NSLog(@"didReceiveRemoteNotification"); 60 | 61 | NSString *alertString = remoteNotification[@"aps"][@"alert"]; 62 | 63 | NSDictionary *payload = remoteNotification[@"payload"]; 64 | // NSString *taskID = payload[@"id"]; 65 | // NSString *taskName = payload[@"name"]; 66 | NSNumber *plannedPomos = payload[@"planned_pomos"]; 67 | NSNumber *actualPomos = payload[@"actual_pomos"]; 68 | NSNumber *interrupts = payload[@"interrupts"]; 69 | 70 | [self.plannedPomosLabel setText:[plannedPomos stringValue]]; 71 | [self.actualPomosLabel setText:[actualPomos stringValue]]; 72 | [self.interruptionsLabel setText:[interrupts stringValue]]; 73 | 74 | [self.alertLabel setText:alertString]; 75 | 76 | 77 | completionHandler(WKUserNotificationInterfaceTypeCustom); 78 | } 79 | 80 | @end 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchTasksListInterfaceController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchTasksListInterfaceController.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/1/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface KTWatchTasksListInterfaceController : WKInterfaceController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchTasksListInterfaceController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchTasksListInterfaceController.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/1/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTWatchTasksListInterfaceController.h" 10 | #import "KTCoreDataStack.h" 11 | #import "KTPomodoroActivityModel.h" 12 | #import "KTPomodoroTaskConstants.h" 13 | #import "KTWatchTasksRowInterfaceController.h" 14 | #import "KTWatchAddTaskRowInterfaceController.h" 15 | 16 | @interface KTWatchTasksListInterfaceController() 17 | 18 | @property (weak, nonatomic) IBOutlet WKInterfaceTable *table; 19 | @property (nonatomic) NSArray *allTasks; 20 | 21 | @end 22 | 23 | 24 | @implementation KTWatchTasksListInterfaceController 25 | 26 | - (void)awakeWithContext:(id)context { 27 | [super awakeWithContext:context]; 28 | 29 | } 30 | 31 | - (void)willActivate { 32 | // This method is called when watch view controller is about to be visible to user 33 | [super willActivate]; 34 | 35 | [self setUpTable]; 36 | } 37 | 38 | - (void)didDeactivate { 39 | // This method is called when watch view controller is no longer visible 40 | [super didDeactivate]; 41 | 42 | } 43 | 44 | #pragma mark - willActivate helper method 45 | 46 | - (void)setUpTable 47 | { 48 | NSArray *tasks = [[KTCoreDataStack sharedInstance] allTasks]; 49 | 50 | // reload table 51 | if ([tasks count] != [self.allTasks count]) { 52 | [self clearTableRows]; 53 | 54 | [self.table insertRowsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [tasks count])] withRowType:@"KTWatchTasksRowInterfaceController"]; 55 | __block CGFloat cellAlpha = 1.0f; 56 | [tasks enumerateObjectsUsingBlock:^(KTPomodoroActivityModel *task, NSUInteger idx, BOOL *stop) { 57 | KTWatchTasksRowInterfaceController *row = (KTWatchTasksRowInterfaceController*)[self.table rowControllerAtIndex:idx]; 58 | [row.taskNameLabel setText:task.name]; 59 | if (task.status.integerValue == KTPomodoroActivityStatusInProgress) { 60 | [row.taskStatusLabel setText:@"In Progress"]; 61 | } else { 62 | [row.taskStatusLabel setText:@""]; 63 | } 64 | [row.rowGroup setCornerRadius:0.0f]; 65 | [row.rowGroup setAlpha:cellAlpha]; 66 | if (cellAlpha > 0.2f) { 67 | cellAlpha -= 0.2; 68 | } 69 | if (idx > 0) { 70 | [row.taskStatusLabel setHidden:YES]; 71 | } 72 | }]; 73 | 74 | 75 | // add "add task" row at end 76 | [self.table insertRowsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange([tasks count], 1)] withRowType:@"KTWatchAddTaskRowInterfaceController"]; 77 | 78 | } 79 | 80 | [tasks enumerateObjectsUsingBlock:^(KTPomodoroActivityModel *task, NSUInteger idx, BOOL *stop) { 81 | KTWatchTasksRowInterfaceController *row = (KTWatchTasksRowInterfaceController*)[self.table rowControllerAtIndex:idx]; 82 | [row.taskNameLabel setText:task.name]; 83 | if (task.status.integerValue == KTPomodoroActivityStatusInProgress) { 84 | [row.taskStatusLabel setText:@"In Progress"]; 85 | } else { 86 | [row.taskStatusLabel setText:@""]; 87 | } 88 | if (idx > 0) { 89 | [row.taskStatusLabel setHidden:YES]; 90 | } 91 | }]; 92 | self.allTasks = tasks; 93 | } 94 | 95 | - (void)clearTableRows 96 | { 97 | [self.table removeRowsAtIndexes:[NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, [self.table numberOfRows])]]; 98 | } 99 | 100 | 101 | - (KTPomodoroActivityModel*)contextForSegueWithIdentifier:(NSString *)segueIdentifier inTable:(WKInterfaceTable *)table rowIndex:(NSInteger)rowIndex 102 | { 103 | if ([segueIdentifier isEqualToString:@"taskDetailsSegue"]) { 104 | return self.allTasks[rowIndex]; 105 | } else { 106 | return nil; 107 | } 108 | } 109 | 110 | #pragma mark - helper 111 | 112 | 113 | @end 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchTasksRowInterfaceController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchTasksRowInterfaceController.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/1/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface KTWatchTasksRowInterfaceController : NSObject 13 | 14 | @property (weak, nonatomic) IBOutlet WKInterfaceLabel *taskNameLabel; 15 | @property (weak, nonatomic) IBOutlet WKInterfaceLabel *taskStatusLabel; 16 | @property (weak, nonatomic) IBOutlet WKInterfaceGroup *rowGroup; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/KTWatchTasksRowInterfaceController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTWatchTasksRowInterfaceController.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/1/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTWatchTasksRowInterfaceController.h" 10 | #import 11 | 12 | @implementation KTWatchTasksRowInterfaceController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/PomodoroFinishedPayload.apns: -------------------------------------------------------------------------------- 1 | { 2 | "aps": { 3 | "alert":"Pomodoro #1 has finished. Time for a break!", 4 | "title":"Task #1", 5 | "category":"PomodoroFinishedCategory" 6 | }, 7 | "WatchKit Simulator Actions" : [ 8 | { 9 | "title" : "Don't need one", 10 | "identifier" : "PomodoroFinishedNotification" 11 | } 12 | ], 13 | "payload":{ 14 | "id":"task1", 15 | "name":"Task 1", 16 | "pomos_left":2 17 | } 18 | } -------------------------------------------------------------------------------- /KTPomodoro WatchKit Extension/TaskCompletedPayload.apns: -------------------------------------------------------------------------------- 1 | { 2 | "aps": { 3 | "alert": "Task #1 has finished.", 4 | "title": "Task #1", 5 | "category": "TaskCompletedCategory" 6 | }, 7 | "WatchKit Simulator Actions" : [ 8 | { 9 | "title" : "Next Task", 10 | "identifier" : "TaskCompletedNotification" 11 | } 12 | ], 13 | "payload":{ 14 | "id":"task1", 15 | "name":"Task 1", 16 | "pomos_left":0, 17 | "planned_pomos":1, 18 | "actual_pomos":2, 19 | "interrupts":0, 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /KTPomodoro.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 8E0F77441A55D0CF0008C4ED /* KTWatchInterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E0F77431A55D0CF0008C4ED /* KTWatchInterfaceController.m */; }; 11 | 8E0F77471A55D0CF0008C4ED /* KTWatchGlanceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E0F77461A55D0CF0008C4ED /* KTWatchGlanceController.m */; }; 12 | 8E0F77491A55D0CF0008C4ED /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8E0F77481A55D0CF0008C4ED /* Images.xcassets */; }; 13 | 8E0F774D1A55D0CF0008C4ED /* KTPomodoro WatchKit App.app in Resources */ = {isa = PBXBuildFile; fileRef = 8E0F774C1A55D0CF0008C4ED /* KTPomodoro WatchKit App.app */; }; 14 | 8E0F77551A55D0CF0008C4ED /* Interface.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8E0F77531A55D0CF0008C4ED /* Interface.storyboard */; }; 15 | 8E0F77571A55D0CF0008C4ED /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8E0F77561A55D0CF0008C4ED /* Images.xcassets */; }; 16 | 8E0F775A1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension.appex in Embed App Extensions */ = {isa = PBXBuildFile; fileRef = 8E0F773E1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; 17 | 8E0F77631A55D0FC0008C4ED /* KTCoreDataStack.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF55C5E1A54E29F002962DF /* KTCoreDataStack.m */; }; 18 | 8E0F77691A55D7CB0008C4ED /* KTPomodoroModel.xcdatamodeld in Resources */ = {isa = PBXBuildFile; fileRef = 8EF55C681A54EA82002962DF /* KTPomodoroModel.xcdatamodeld */; }; 19 | 8E0F776F1A55E0770008C4ED /* KTWatchTasksRowInterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E0F776E1A55E0770008C4ED /* KTWatchTasksRowInterfaceController.m */; }; 20 | 8E0F77721A55E09D0008C4ED /* KTWatchTasksListInterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E0F77711A55E09D0008C4ED /* KTWatchTasksListInterfaceController.m */; }; 21 | 8E2668011A5AF05800C36D0C /* KTPomodoroActivityModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E2668001A5AF05800C36D0C /* KTPomodoroActivityModel.m */; }; 22 | 8E2668021A5AF05800C36D0C /* KTPomodoroActivityModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E2668001A5AF05800C36D0C /* KTPomodoroActivityModel.m */; }; 23 | 8E362A431A8FE6D4006DD649 /* Settings-Watch.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 8EE78ABA1A8AE2E100F8A225 /* Settings-Watch.bundle */; }; 24 | 8E64C1061A5F4B2700A4D526 /* KTPomodoroTaskConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E64C1051A5F4B2700A4D526 /* KTPomodoroTaskConstants.m */; }; 25 | 8E64C1071A5F4B2700A4D526 /* KTPomodoroTaskConstants.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E64C1051A5F4B2700A4D526 /* KTPomodoroTaskConstants.m */; }; 26 | 8E64C1091A5F585100A4D526 /* PomodoroFinishedPayload.apns in Resources */ = {isa = PBXBuildFile; fileRef = 8E64C1081A5F585100A4D526 /* PomodoroFinishedPayload.apns */; }; 27 | 8E64C16A1A5F608800A4D526 /* KTWatchPomodoroCompletedNotificationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8E64C1691A5F608800A4D526 /* KTWatchPomodoroCompletedNotificationController.m */; }; 28 | 8EC91CB41A71911B007D0CD6 /* KTSharedUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EC91CB31A71911B007D0CD6 /* KTSharedUserDefaults.m */; }; 29 | 8EC91CB51A7191E2007D0CD6 /* KTSharedUserDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EC91CB31A71911B007D0CD6 /* KTSharedUserDefaults.m */; }; 30 | 8EC91CB81A719268007D0CD6 /* KTActiveActivityState.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EC91CB71A719268007D0CD6 /* KTActiveActivityState.m */; }; 31 | 8EC91CB91A719268007D0CD6 /* KTActiveActivityState.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EC91CB71A719268007D0CD6 /* KTActiveActivityState.m */; }; 32 | 8EC91CBC1A719806007D0CD6 /* KTActivityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EC91CBB1A719806007D0CD6 /* KTActivityManager.m */; }; 33 | 8EC91CBD1A719806007D0CD6 /* KTActivityManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EC91CBB1A719806007D0CD6 /* KTActivityManager.m */; }; 34 | 8EE78ABB1A8AE2E100F8A225 /* Settings-Watch.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 8EE78ABA1A8AE2E100F8A225 /* Settings-Watch.bundle */; }; 35 | 8EF55C2E1A54DFC2002962DF /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF55C2D1A54DFC2002962DF /* main.m */; }; 36 | 8EF55C311A54DFC2002962DF /* KTAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF55C301A54DFC2002962DF /* KTAppDelegate.m */; }; 37 | 8EF55C3C1A54DFC2002962DF /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 8EF55C3B1A54DFC2002962DF /* Images.xcassets */; }; 38 | 8EF55C3F1A54DFC2002962DF /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8EF55C3D1A54DFC2002962DF /* LaunchScreen.xib */; }; 39 | 8EF55C4B1A54DFC2002962DF /* KTPomodoroTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF55C4A1A54DFC2002962DF /* KTPomodoroTests.m */; }; 40 | 8EF55C5F1A54E29F002962DF /* KTCoreDataStack.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF55C5E1A54E29F002962DF /* KTCoreDataStack.m */; }; 41 | 8EF55C651A54E4AD002962DF /* KTPomodoroTableViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF55C641A54E4AD002962DF /* KTPomodoroTableViewController.m */; }; 42 | 8EF55C6A1A54EA82002962DF /* KTPomodoroModel.xcdatamodeld in Sources */ = {isa = PBXBuildFile; fileRef = 8EF55C681A54EA82002962DF /* KTPomodoroModel.xcdatamodeld */; }; 43 | 8EF55C6C1A54EBC4002962DF /* KTPomodoroTableViewCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8EF55C6B1A54EBC4002962DF /* KTPomodoroTableViewCell.xib */; }; 44 | 8EF55C6F1A54EC48002962DF /* KTPomodoroTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF55C6E1A54EC48002962DF /* KTPomodoroTableViewCell.m */; }; 45 | 8EF5AF2A1A6063E500A40CE8 /* KTWatchTaskCompletedNotificationController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF5AF291A6063E500A40CE8 /* KTWatchTaskCompletedNotificationController.m */; }; 46 | 8EF5AF2D1A60652D00A40CE8 /* KTWatchTaskCompletedNotificationStoryboard.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 8EF5AF2B1A60652D00A40CE8 /* KTWatchTaskCompletedNotificationStoryboard.storyboard */; }; 47 | 8EF5AF301A60916700A40CE8 /* KTWatchAddTaskRowInterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF5AF2F1A60916700A40CE8 /* KTWatchAddTaskRowInterfaceController.m */; }; 48 | 8EF5AF331A60955E00A40CE8 /* KTWatchInterfaceAddTaskInterfaceController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8EF5AF321A60955E00A40CE8 /* KTWatchInterfaceAddTaskInterfaceController.m */; }; 49 | /* End PBXBuildFile section */ 50 | 51 | /* Begin PBXContainerItemProxy section */ 52 | 8E0F774E1A55D0CF0008C4ED /* PBXContainerItemProxy */ = { 53 | isa = PBXContainerItemProxy; 54 | containerPortal = 8EF55C201A54DFC1002962DF /* Project object */; 55 | proxyType = 1; 56 | remoteGlobalIDString = 8E0F774B1A55D0CF0008C4ED; 57 | remoteInfo = "KTPomodoro WatchKit App"; 58 | }; 59 | 8E0F77581A55D0CF0008C4ED /* PBXContainerItemProxy */ = { 60 | isa = PBXContainerItemProxy; 61 | containerPortal = 8EF55C201A54DFC1002962DF /* Project object */; 62 | proxyType = 1; 63 | remoteGlobalIDString = 8E0F773D1A55D0CF0008C4ED; 64 | remoteInfo = "KTPomodoro WatchKit Extension"; 65 | }; 66 | 8EF55C451A54DFC2002962DF /* PBXContainerItemProxy */ = { 67 | isa = PBXContainerItemProxy; 68 | containerPortal = 8EF55C201A54DFC1002962DF /* Project object */; 69 | proxyType = 1; 70 | remoteGlobalIDString = 8EF55C271A54DFC1002962DF; 71 | remoteInfo = KTPomodoro; 72 | }; 73 | /* End PBXContainerItemProxy section */ 74 | 75 | /* Begin PBXCopyFilesBuildPhase section */ 76 | 8E0F77611A55D0CF0008C4ED /* Embed App Extensions */ = { 77 | isa = PBXCopyFilesBuildPhase; 78 | buildActionMask = 2147483647; 79 | dstPath = ""; 80 | dstSubfolderSpec = 13; 81 | files = ( 82 | 8E0F775A1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension.appex in Embed App Extensions */, 83 | ); 84 | name = "Embed App Extensions"; 85 | runOnlyForDeploymentPostprocessing = 0; 86 | }; 87 | /* End PBXCopyFilesBuildPhase section */ 88 | 89 | /* Begin PBXFileReference section */ 90 | 8E0F773E1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = "KTPomodoro WatchKit Extension.appex"; sourceTree = BUILT_PRODUCTS_DIR; }; 91 | 8E0F77411A55D0CF0008C4ED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 92 | 8E0F77421A55D0CF0008C4ED /* KTWatchInterfaceController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KTWatchInterfaceController.h; sourceTree = ""; }; 93 | 8E0F77431A55D0CF0008C4ED /* KTWatchInterfaceController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KTWatchInterfaceController.m; sourceTree = ""; }; 94 | 8E0F77451A55D0CF0008C4ED /* KTWatchGlanceController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KTWatchGlanceController.h; sourceTree = ""; }; 95 | 8E0F77461A55D0CF0008C4ED /* KTWatchGlanceController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KTWatchGlanceController.m; sourceTree = ""; }; 96 | 8E0F77481A55D0CF0008C4ED /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 97 | 8E0F774C1A55D0CF0008C4ED /* KTPomodoro WatchKit App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "KTPomodoro WatchKit App.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 98 | 8E0F77521A55D0CF0008C4ED /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 99 | 8E0F77541A55D0CF0008C4ED /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Interface.storyboard; sourceTree = ""; }; 100 | 8E0F77561A55D0CF0008C4ED /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 101 | 8E0F77681A55D6E40008C4ED /* KTPomodoro WatchKit Extension.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = "KTPomodoro WatchKit Extension.entitlements"; sourceTree = ""; }; 102 | 8E0F776D1A55E0770008C4ED /* KTWatchTasksRowInterfaceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KTWatchTasksRowInterfaceController.h; sourceTree = ""; }; 103 | 8E0F776E1A55E0770008C4ED /* KTWatchTasksRowInterfaceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KTWatchTasksRowInterfaceController.m; sourceTree = ""; }; 104 | 8E0F77701A55E09D0008C4ED /* KTWatchTasksListInterfaceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KTWatchTasksListInterfaceController.h; sourceTree = ""; }; 105 | 8E0F77711A55E09D0008C4ED /* KTWatchTasksListInterfaceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KTWatchTasksListInterfaceController.m; sourceTree = ""; }; 106 | 8E2667FF1A5AF05800C36D0C /* KTPomodoroActivityModel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KTPomodoroActivityModel.h; path = Model/KTPomodoroActivityModel.h; sourceTree = ""; }; 107 | 8E2668001A5AF05800C36D0C /* KTPomodoroActivityModel.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KTPomodoroActivityModel.m; path = Model/KTPomodoroActivityModel.m; sourceTree = ""; }; 108 | 8E64C1041A5F4B2700A4D526 /* KTPomodoroTaskConstants.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KTPomodoroTaskConstants.h; path = Model/KTPomodoroTaskConstants.h; sourceTree = ""; }; 109 | 8E64C1051A5F4B2700A4D526 /* KTPomodoroTaskConstants.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KTPomodoroTaskConstants.m; path = Model/KTPomodoroTaskConstants.m; sourceTree = ""; }; 110 | 8E64C1081A5F585100A4D526 /* PomodoroFinishedPayload.apns */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = PomodoroFinishedPayload.apns; sourceTree = ""; }; 111 | 8E64C1681A5F608800A4D526 /* KTWatchPomodoroCompletedNotificationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KTWatchPomodoroCompletedNotificationController.h; sourceTree = ""; }; 112 | 8E64C1691A5F608800A4D526 /* KTWatchPomodoroCompletedNotificationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KTWatchPomodoroCompletedNotificationController.m; sourceTree = ""; }; 113 | 8EC91CB21A71911B007D0CD6 /* KTSharedUserDefaults.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KTSharedUserDefaults.h; path = Utils/KTSharedUserDefaults.h; sourceTree = ""; }; 114 | 8EC91CB31A71911B007D0CD6 /* KTSharedUserDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KTSharedUserDefaults.m; path = Utils/KTSharedUserDefaults.m; sourceTree = ""; }; 115 | 8EC91CB61A719268007D0CD6 /* KTActiveActivityState.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KTActiveActivityState.h; path = Model/KTActiveActivityState.h; sourceTree = ""; }; 116 | 8EC91CB71A719268007D0CD6 /* KTActiveActivityState.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KTActiveActivityState.m; path = Model/KTActiveActivityState.m; sourceTree = ""; }; 117 | 8EC91CBA1A719806007D0CD6 /* KTActivityManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KTActivityManager.h; path = Utils/KTActivityManager.h; sourceTree = ""; }; 118 | 8EC91CBB1A719806007D0CD6 /* KTActivityManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KTActivityManager.m; path = Utils/KTActivityManager.m; sourceTree = ""; }; 119 | 8EE78ABA1A8AE2E100F8A225 /* Settings-Watch.bundle */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.plug-in"; name = "Settings-Watch.bundle"; path = "Resources/Shared/Settings-Watch.bundle"; sourceTree = ""; }; 120 | 8EF55C281A54DFC2002962DF /* KTPomodoro.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = KTPomodoro.app; sourceTree = BUILT_PRODUCTS_DIR; }; 121 | 8EF55C2C1A54DFC2002962DF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 122 | 8EF55C2D1A54DFC2002962DF /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 123 | 8EF55C2F1A54DFC2002962DF /* KTAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KTAppDelegate.h; sourceTree = ""; }; 124 | 8EF55C301A54DFC2002962DF /* KTAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KTAppDelegate.m; sourceTree = ""; }; 125 | 8EF55C3B1A54DFC2002962DF /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 126 | 8EF55C3E1A54DFC2002962DF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; 127 | 8EF55C441A54DFC2002962DF /* KTPomodoroTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KTPomodoroTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 128 | 8EF55C491A54DFC2002962DF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 129 | 8EF55C4A1A54DFC2002962DF /* KTPomodoroTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KTPomodoroTests.m; sourceTree = ""; }; 130 | 8EF55C5D1A54E29F002962DF /* KTCoreDataStack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KTCoreDataStack.h; path = Model/KTCoreDataStack.h; sourceTree = ""; }; 131 | 8EF55C5E1A54E29F002962DF /* KTCoreDataStack.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KTCoreDataStack.m; path = Model/KTCoreDataStack.m; sourceTree = ""; }; 132 | 8EF55C631A54E4AD002962DF /* KTPomodoroTableViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KTPomodoroTableViewController.h; path = "View Controller/KTPomodoroTableViewController.h"; sourceTree = ""; }; 133 | 8EF55C641A54E4AD002962DF /* KTPomodoroTableViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KTPomodoroTableViewController.m; path = "View Controller/KTPomodoroTableViewController.m"; sourceTree = ""; }; 134 | 8EF55C691A54EA82002962DF /* KTPomodoroModel.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = KTPomodoroModel.xcdatamodel; sourceTree = ""; }; 135 | 8EF55C6B1A54EBC4002962DF /* KTPomodoroTableViewCell.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = KTPomodoroTableViewCell.xib; path = Resources/KTPomodoroTableViewCell.xib; sourceTree = ""; }; 136 | 8EF55C6D1A54EC48002962DF /* KTPomodoroTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = KTPomodoroTableViewCell.h; path = "View Controller/KTPomodoroTableViewCell.h"; sourceTree = ""; }; 137 | 8EF55C6E1A54EC48002962DF /* KTPomodoroTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = KTPomodoroTableViewCell.m; path = "View Controller/KTPomodoroTableViewCell.m"; sourceTree = ""; }; 138 | 8EF55C701A54F59B002962DF /* KTPomodoro.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = KTPomodoro.entitlements; sourceTree = ""; }; 139 | 8EF5AF271A60631000A40CE8 /* TaskCompletedPayload.apns */ = {isa = PBXFileReference; lastKnownFileType = text; path = TaskCompletedPayload.apns; sourceTree = ""; }; 140 | 8EF5AF281A6063E500A40CE8 /* KTWatchTaskCompletedNotificationController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KTWatchTaskCompletedNotificationController.h; sourceTree = ""; }; 141 | 8EF5AF291A6063E500A40CE8 /* KTWatchTaskCompletedNotificationController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KTWatchTaskCompletedNotificationController.m; sourceTree = ""; }; 142 | 8EF5AF2C1A60652D00A40CE8 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/KTWatchTaskCompletedNotificationStoryboard.storyboard; sourceTree = ""; }; 143 | 8EF5AF2E1A60916700A40CE8 /* KTWatchAddTaskRowInterfaceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KTWatchAddTaskRowInterfaceController.h; sourceTree = ""; }; 144 | 8EF5AF2F1A60916700A40CE8 /* KTWatchAddTaskRowInterfaceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KTWatchAddTaskRowInterfaceController.m; sourceTree = ""; }; 145 | 8EF5AF311A60955E00A40CE8 /* KTWatchInterfaceAddTaskInterfaceController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KTWatchInterfaceAddTaskInterfaceController.h; sourceTree = ""; }; 146 | 8EF5AF321A60955E00A40CE8 /* KTWatchInterfaceAddTaskInterfaceController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KTWatchInterfaceAddTaskInterfaceController.m; sourceTree = ""; }; 147 | /* End PBXFileReference section */ 148 | 149 | /* Begin PBXFrameworksBuildPhase section */ 150 | 8E0F773B1A55D0CF0008C4ED /* Frameworks */ = { 151 | isa = PBXFrameworksBuildPhase; 152 | buildActionMask = 2147483647; 153 | files = ( 154 | ); 155 | runOnlyForDeploymentPostprocessing = 0; 156 | }; 157 | 8EF55C251A54DFC1002962DF /* Frameworks */ = { 158 | isa = PBXFrameworksBuildPhase; 159 | buildActionMask = 2147483647; 160 | files = ( 161 | ); 162 | runOnlyForDeploymentPostprocessing = 0; 163 | }; 164 | 8EF55C411A54DFC2002962DF /* Frameworks */ = { 165 | isa = PBXFrameworksBuildPhase; 166 | buildActionMask = 2147483647; 167 | files = ( 168 | ); 169 | runOnlyForDeploymentPostprocessing = 0; 170 | }; 171 | /* End PBXFrameworksBuildPhase section */ 172 | 173 | /* Begin PBXGroup section */ 174 | 8E0F77361A55CB0C0008C4ED /* Utils */ = { 175 | isa = PBXGroup; 176 | children = ( 177 | 8EC91CB21A71911B007D0CD6 /* KTSharedUserDefaults.h */, 178 | 8EC91CB31A71911B007D0CD6 /* KTSharedUserDefaults.m */, 179 | 8EC91CBA1A719806007D0CD6 /* KTActivityManager.h */, 180 | 8EC91CBB1A719806007D0CD6 /* KTActivityManager.m */, 181 | ); 182 | name = Utils; 183 | sourceTree = ""; 184 | }; 185 | 8E0F773F1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension */ = { 186 | isa = PBXGroup; 187 | children = ( 188 | 8E0F77681A55D6E40008C4ED /* KTPomodoro WatchKit Extension.entitlements */, 189 | 8E0F77421A55D0CF0008C4ED /* KTWatchInterfaceController.h */, 190 | 8E0F77431A55D0CF0008C4ED /* KTWatchInterfaceController.m */, 191 | 8E0F77701A55E09D0008C4ED /* KTWatchTasksListInterfaceController.h */, 192 | 8E0F77711A55E09D0008C4ED /* KTWatchTasksListInterfaceController.m */, 193 | 8E0F776D1A55E0770008C4ED /* KTWatchTasksRowInterfaceController.h */, 194 | 8E0F776E1A55E0770008C4ED /* KTWatchTasksRowInterfaceController.m */, 195 | 8EF5AF2E1A60916700A40CE8 /* KTWatchAddTaskRowInterfaceController.h */, 196 | 8EF5AF2F1A60916700A40CE8 /* KTWatchAddTaskRowInterfaceController.m */, 197 | 8EF5AF311A60955E00A40CE8 /* KTWatchInterfaceAddTaskInterfaceController.h */, 198 | 8EF5AF321A60955E00A40CE8 /* KTWatchInterfaceAddTaskInterfaceController.m */, 199 | 8E64C1681A5F608800A4D526 /* KTWatchPomodoroCompletedNotificationController.h */, 200 | 8E64C1691A5F608800A4D526 /* KTWatchPomodoroCompletedNotificationController.m */, 201 | 8EF5AF281A6063E500A40CE8 /* KTWatchTaskCompletedNotificationController.h */, 202 | 8EF5AF291A6063E500A40CE8 /* KTWatchTaskCompletedNotificationController.m */, 203 | 8E0F77451A55D0CF0008C4ED /* KTWatchGlanceController.h */, 204 | 8E0F77461A55D0CF0008C4ED /* KTWatchGlanceController.m */, 205 | 8E0F77481A55D0CF0008C4ED /* Images.xcassets */, 206 | 8E0F77401A55D0CF0008C4ED /* Supporting Files */, 207 | ); 208 | path = "KTPomodoro WatchKit Extension"; 209 | sourceTree = ""; 210 | }; 211 | 8E0F77401A55D0CF0008C4ED /* Supporting Files */ = { 212 | isa = PBXGroup; 213 | children = ( 214 | 8E0F77411A55D0CF0008C4ED /* Info.plist */, 215 | 8E64C1081A5F585100A4D526 /* PomodoroFinishedPayload.apns */, 216 | 8EF5AF271A60631000A40CE8 /* TaskCompletedPayload.apns */, 217 | ); 218 | name = "Supporting Files"; 219 | sourceTree = ""; 220 | }; 221 | 8E0F77501A55D0CF0008C4ED /* KTPomodoro WatchKit App */ = { 222 | isa = PBXGroup; 223 | children = ( 224 | 8E0F77531A55D0CF0008C4ED /* Interface.storyboard */, 225 | 8EF5AF2B1A60652D00A40CE8 /* KTWatchTaskCompletedNotificationStoryboard.storyboard */, 226 | 8E0F77561A55D0CF0008C4ED /* Images.xcassets */, 227 | 8E0F77511A55D0CF0008C4ED /* Supporting Files */, 228 | ); 229 | path = "KTPomodoro WatchKit App"; 230 | sourceTree = ""; 231 | }; 232 | 8E0F77511A55D0CF0008C4ED /* Supporting Files */ = { 233 | isa = PBXGroup; 234 | children = ( 235 | 8E0F77521A55D0CF0008C4ED /* Info.plist */, 236 | ); 237 | name = "Supporting Files"; 238 | sourceTree = ""; 239 | }; 240 | 8EE78AB91A8AE2B900F8A225 /* Shared */ = { 241 | isa = PBXGroup; 242 | children = ( 243 | 8EE78ABA1A8AE2E100F8A225 /* Settings-Watch.bundle */, 244 | ); 245 | name = Shared; 246 | sourceTree = ""; 247 | }; 248 | 8EF55C1F1A54DFC1002962DF = { 249 | isa = PBXGroup; 250 | children = ( 251 | 8EF55C2A1A54DFC2002962DF /* KTPomodoro */, 252 | 8EF55C471A54DFC2002962DF /* KTPomodoroTests */, 253 | 8E0F773F1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension */, 254 | 8E0F77501A55D0CF0008C4ED /* KTPomodoro WatchKit App */, 255 | 8EF55C291A54DFC2002962DF /* Products */, 256 | ); 257 | sourceTree = ""; 258 | }; 259 | 8EF55C291A54DFC2002962DF /* Products */ = { 260 | isa = PBXGroup; 261 | children = ( 262 | 8EF55C281A54DFC2002962DF /* KTPomodoro.app */, 263 | 8EF55C441A54DFC2002962DF /* KTPomodoroTests.xctest */, 264 | 8E0F773E1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension.appex */, 265 | 8E0F774C1A55D0CF0008C4ED /* KTPomodoro WatchKit App.app */, 266 | ); 267 | name = Products; 268 | sourceTree = ""; 269 | }; 270 | 8EF55C2A1A54DFC2002962DF /* KTPomodoro */ = { 271 | isa = PBXGroup; 272 | children = ( 273 | 8EF55C701A54F59B002962DF /* KTPomodoro.entitlements */, 274 | 8EF55C2F1A54DFC2002962DF /* KTAppDelegate.h */, 275 | 8EF55C301A54DFC2002962DF /* KTAppDelegate.m */, 276 | 8EF55C591A54E192002962DF /* Model */, 277 | 8E0F77361A55CB0C0008C4ED /* Utils */, 278 | 8EF55C551A54E061002962DF /* View Controllers */, 279 | 8EF55C541A54E006002962DF /* Resources */, 280 | 8EF55C2B1A54DFC2002962DF /* Supporting Files */, 281 | ); 282 | path = KTPomodoro; 283 | sourceTree = ""; 284 | }; 285 | 8EF55C2B1A54DFC2002962DF /* Supporting Files */ = { 286 | isa = PBXGroup; 287 | children = ( 288 | 8EF55C2C1A54DFC2002962DF /* Info.plist */, 289 | 8EF55C2D1A54DFC2002962DF /* main.m */, 290 | ); 291 | name = "Supporting Files"; 292 | sourceTree = ""; 293 | }; 294 | 8EF55C471A54DFC2002962DF /* KTPomodoroTests */ = { 295 | isa = PBXGroup; 296 | children = ( 297 | 8EF55C4A1A54DFC2002962DF /* KTPomodoroTests.m */, 298 | 8EF55C481A54DFC2002962DF /* Supporting Files */, 299 | ); 300 | path = KTPomodoroTests; 301 | sourceTree = ""; 302 | }; 303 | 8EF55C481A54DFC2002962DF /* Supporting Files */ = { 304 | isa = PBXGroup; 305 | children = ( 306 | 8EF55C491A54DFC2002962DF /* Info.plist */, 307 | ); 308 | name = "Supporting Files"; 309 | sourceTree = ""; 310 | }; 311 | 8EF55C541A54E006002962DF /* Resources */ = { 312 | isa = PBXGroup; 313 | children = ( 314 | 8EE78AB91A8AE2B900F8A225 /* Shared */, 315 | 8EF55C3B1A54DFC2002962DF /* Images.xcassets */, 316 | 8EF55C3D1A54DFC2002962DF /* LaunchScreen.xib */, 317 | 8EF55C681A54EA82002962DF /* KTPomodoroModel.xcdatamodeld */, 318 | 8EF55C6B1A54EBC4002962DF /* KTPomodoroTableViewCell.xib */, 319 | ); 320 | name = Resources; 321 | sourceTree = ""; 322 | }; 323 | 8EF55C551A54E061002962DF /* View Controllers */ = { 324 | isa = PBXGroup; 325 | children = ( 326 | 8EF55C631A54E4AD002962DF /* KTPomodoroTableViewController.h */, 327 | 8EF55C641A54E4AD002962DF /* KTPomodoroTableViewController.m */, 328 | 8EF55C6D1A54EC48002962DF /* KTPomodoroTableViewCell.h */, 329 | 8EF55C6E1A54EC48002962DF /* KTPomodoroTableViewCell.m */, 330 | ); 331 | name = "View Controllers"; 332 | sourceTree = ""; 333 | }; 334 | 8EF55C591A54E192002962DF /* Model */ = { 335 | isa = PBXGroup; 336 | children = ( 337 | 8EC91CB61A719268007D0CD6 /* KTActiveActivityState.h */, 338 | 8EC91CB71A719268007D0CD6 /* KTActiveActivityState.m */, 339 | 8E2667FF1A5AF05800C36D0C /* KTPomodoroActivityModel.h */, 340 | 8E2668001A5AF05800C36D0C /* KTPomodoroActivityModel.m */, 341 | 8EF55C5D1A54E29F002962DF /* KTCoreDataStack.h */, 342 | 8EF55C5E1A54E29F002962DF /* KTCoreDataStack.m */, 343 | 8E64C1041A5F4B2700A4D526 /* KTPomodoroTaskConstants.h */, 344 | 8E64C1051A5F4B2700A4D526 /* KTPomodoroTaskConstants.m */, 345 | ); 346 | name = Model; 347 | sourceTree = ""; 348 | }; 349 | /* End PBXGroup section */ 350 | 351 | /* Begin PBXNativeTarget section */ 352 | 8E0F773D1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension */ = { 353 | isa = PBXNativeTarget; 354 | buildConfigurationList = 8E0F775E1A55D0CF0008C4ED /* Build configuration list for PBXNativeTarget "KTPomodoro WatchKit Extension" */; 355 | buildPhases = ( 356 | 8E0F773A1A55D0CF0008C4ED /* Sources */, 357 | 8E0F773B1A55D0CF0008C4ED /* Frameworks */, 358 | 8E0F773C1A55D0CF0008C4ED /* Resources */, 359 | ); 360 | buildRules = ( 361 | ); 362 | dependencies = ( 363 | 8E0F774F1A55D0CF0008C4ED /* PBXTargetDependency */, 364 | ); 365 | name = "KTPomodoro WatchKit Extension"; 366 | productName = "KTPomodoro WatchKit Extension"; 367 | productReference = 8E0F773E1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension.appex */; 368 | productType = "com.apple.product-type.watchkit-extension"; 369 | }; 370 | 8E0F774B1A55D0CF0008C4ED /* KTPomodoro WatchKit App */ = { 371 | isa = PBXNativeTarget; 372 | buildConfigurationList = 8E0F775B1A55D0CF0008C4ED /* Build configuration list for PBXNativeTarget "KTPomodoro WatchKit App" */; 373 | buildPhases = ( 374 | 8E0F774A1A55D0CF0008C4ED /* Resources */, 375 | ); 376 | buildRules = ( 377 | ); 378 | dependencies = ( 379 | ); 380 | name = "KTPomodoro WatchKit App"; 381 | productName = "KTPomodoro WatchKit App"; 382 | productReference = 8E0F774C1A55D0CF0008C4ED /* KTPomodoro WatchKit App.app */; 383 | productType = "com.apple.product-type.application.watchapp"; 384 | }; 385 | 8EF55C271A54DFC1002962DF /* KTPomodoro */ = { 386 | isa = PBXNativeTarget; 387 | buildConfigurationList = 8EF55C4E1A54DFC2002962DF /* Build configuration list for PBXNativeTarget "KTPomodoro" */; 388 | buildPhases = ( 389 | 8EF55C241A54DFC1002962DF /* Sources */, 390 | 8EF55C251A54DFC1002962DF /* Frameworks */, 391 | 8EF55C261A54DFC1002962DF /* Resources */, 392 | 8E0F77611A55D0CF0008C4ED /* Embed App Extensions */, 393 | ); 394 | buildRules = ( 395 | ); 396 | dependencies = ( 397 | 8E0F77591A55D0CF0008C4ED /* PBXTargetDependency */, 398 | ); 399 | name = KTPomodoro; 400 | productName = KTPomodoro; 401 | productReference = 8EF55C281A54DFC2002962DF /* KTPomodoro.app */; 402 | productType = "com.apple.product-type.application"; 403 | }; 404 | 8EF55C431A54DFC2002962DF /* KTPomodoroTests */ = { 405 | isa = PBXNativeTarget; 406 | buildConfigurationList = 8EF55C511A54DFC2002962DF /* Build configuration list for PBXNativeTarget "KTPomodoroTests" */; 407 | buildPhases = ( 408 | 8EF55C401A54DFC2002962DF /* Sources */, 409 | 8EF55C411A54DFC2002962DF /* Frameworks */, 410 | 8EF55C421A54DFC2002962DF /* Resources */, 411 | ); 412 | buildRules = ( 413 | ); 414 | dependencies = ( 415 | 8EF55C461A54DFC2002962DF /* PBXTargetDependency */, 416 | ); 417 | name = KTPomodoroTests; 418 | productName = KTPomodoroTests; 419 | productReference = 8EF55C441A54DFC2002962DF /* KTPomodoroTests.xctest */; 420 | productType = "com.apple.product-type.bundle.unit-test"; 421 | }; 422 | /* End PBXNativeTarget section */ 423 | 424 | /* Begin PBXProject section */ 425 | 8EF55C201A54DFC1002962DF /* Project object */ = { 426 | isa = PBXProject; 427 | attributes = { 428 | CLASSPREFIX = KT; 429 | LastUpgradeCheck = 0620; 430 | ORGANIZATIONNAME = "Kenny Tang"; 431 | TargetAttributes = { 432 | 8E0F773D1A55D0CF0008C4ED = { 433 | CreatedOnToolsVersion = 6.2; 434 | DevelopmentTeam = Y54H2D8RT6; 435 | SystemCapabilities = { 436 | com.apple.ApplicationGroups.iOS = { 437 | enabled = 1; 438 | }; 439 | }; 440 | }; 441 | 8E0F774B1A55D0CF0008C4ED = { 442 | CreatedOnToolsVersion = 6.2; 443 | }; 444 | 8EF55C271A54DFC1002962DF = { 445 | CreatedOnToolsVersion = 6.2; 446 | DevelopmentTeam = Y54H2D8RT6; 447 | SystemCapabilities = { 448 | com.apple.ApplicationGroups.iOS = { 449 | enabled = 1; 450 | }; 451 | }; 452 | }; 453 | 8EF55C431A54DFC2002962DF = { 454 | CreatedOnToolsVersion = 6.2; 455 | TestTargetID = 8EF55C271A54DFC1002962DF; 456 | }; 457 | }; 458 | }; 459 | buildConfigurationList = 8EF55C231A54DFC1002962DF /* Build configuration list for PBXProject "KTPomodoro" */; 460 | compatibilityVersion = "Xcode 3.2"; 461 | developmentRegion = English; 462 | hasScannedForEncodings = 0; 463 | knownRegions = ( 464 | en, 465 | Base, 466 | ); 467 | mainGroup = 8EF55C1F1A54DFC1002962DF; 468 | productRefGroup = 8EF55C291A54DFC2002962DF /* Products */; 469 | projectDirPath = ""; 470 | projectRoot = ""; 471 | targets = ( 472 | 8EF55C271A54DFC1002962DF /* KTPomodoro */, 473 | 8EF55C431A54DFC2002962DF /* KTPomodoroTests */, 474 | 8E0F773D1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension */, 475 | 8E0F774B1A55D0CF0008C4ED /* KTPomodoro WatchKit App */, 476 | ); 477 | }; 478 | /* End PBXProject section */ 479 | 480 | /* Begin PBXResourcesBuildPhase section */ 481 | 8E0F773C1A55D0CF0008C4ED /* Resources */ = { 482 | isa = PBXResourcesBuildPhase; 483 | buildActionMask = 2147483647; 484 | files = ( 485 | 8E0F774D1A55D0CF0008C4ED /* KTPomodoro WatchKit App.app in Resources */, 486 | 8E362A431A8FE6D4006DD649 /* Settings-Watch.bundle in Resources */, 487 | 8E64C1091A5F585100A4D526 /* PomodoroFinishedPayload.apns in Resources */, 488 | 8E0F77691A55D7CB0008C4ED /* KTPomodoroModel.xcdatamodeld in Resources */, 489 | 8E0F77491A55D0CF0008C4ED /* Images.xcassets in Resources */, 490 | ); 491 | runOnlyForDeploymentPostprocessing = 0; 492 | }; 493 | 8E0F774A1A55D0CF0008C4ED /* Resources */ = { 494 | isa = PBXResourcesBuildPhase; 495 | buildActionMask = 2147483647; 496 | files = ( 497 | 8EF5AF2D1A60652D00A40CE8 /* KTWatchTaskCompletedNotificationStoryboard.storyboard in Resources */, 498 | 8E0F77551A55D0CF0008C4ED /* Interface.storyboard in Resources */, 499 | 8E0F77571A55D0CF0008C4ED /* Images.xcassets in Resources */, 500 | ); 501 | runOnlyForDeploymentPostprocessing = 0; 502 | }; 503 | 8EF55C261A54DFC1002962DF /* Resources */ = { 504 | isa = PBXResourcesBuildPhase; 505 | buildActionMask = 2147483647; 506 | files = ( 507 | 8EF55C6C1A54EBC4002962DF /* KTPomodoroTableViewCell.xib in Resources */, 508 | 8EF55C3F1A54DFC2002962DF /* LaunchScreen.xib in Resources */, 509 | 8EE78ABB1A8AE2E100F8A225 /* Settings-Watch.bundle in Resources */, 510 | 8EF55C3C1A54DFC2002962DF /* Images.xcassets in Resources */, 511 | ); 512 | runOnlyForDeploymentPostprocessing = 0; 513 | }; 514 | 8EF55C421A54DFC2002962DF /* Resources */ = { 515 | isa = PBXResourcesBuildPhase; 516 | buildActionMask = 2147483647; 517 | files = ( 518 | ); 519 | runOnlyForDeploymentPostprocessing = 0; 520 | }; 521 | /* End PBXResourcesBuildPhase section */ 522 | 523 | /* Begin PBXSourcesBuildPhase section */ 524 | 8E0F773A1A55D0CF0008C4ED /* Sources */ = { 525 | isa = PBXSourcesBuildPhase; 526 | buildActionMask = 2147483647; 527 | files = ( 528 | 8E0F77721A55E09D0008C4ED /* KTWatchTasksListInterfaceController.m in Sources */, 529 | 8EC91CB51A7191E2007D0CD6 /* KTSharedUserDefaults.m in Sources */, 530 | 8E64C16A1A5F608800A4D526 /* KTWatchPomodoroCompletedNotificationController.m in Sources */, 531 | 8EC91CBD1A719806007D0CD6 /* KTActivityManager.m in Sources */, 532 | 8E0F77631A55D0FC0008C4ED /* KTCoreDataStack.m in Sources */, 533 | 8EF5AF331A60955E00A40CE8 /* KTWatchInterfaceAddTaskInterfaceController.m in Sources */, 534 | 8EC91CB91A719268007D0CD6 /* KTActiveActivityState.m in Sources */, 535 | 8E64C1071A5F4B2700A4D526 /* KTPomodoroTaskConstants.m in Sources */, 536 | 8EF5AF2A1A6063E500A40CE8 /* KTWatchTaskCompletedNotificationController.m in Sources */, 537 | 8E0F776F1A55E0770008C4ED /* KTWatchTasksRowInterfaceController.m in Sources */, 538 | 8E0F77441A55D0CF0008C4ED /* KTWatchInterfaceController.m in Sources */, 539 | 8EF5AF301A60916700A40CE8 /* KTWatchAddTaskRowInterfaceController.m in Sources */, 540 | 8E0F77471A55D0CF0008C4ED /* KTWatchGlanceController.m in Sources */, 541 | 8E2668021A5AF05800C36D0C /* KTPomodoroActivityModel.m in Sources */, 542 | ); 543 | runOnlyForDeploymentPostprocessing = 0; 544 | }; 545 | 8EF55C241A54DFC1002962DF /* Sources */ = { 546 | isa = PBXSourcesBuildPhase; 547 | buildActionMask = 2147483647; 548 | files = ( 549 | 8EC91CB41A71911B007D0CD6 /* KTSharedUserDefaults.m in Sources */, 550 | 8EF55C311A54DFC2002962DF /* KTAppDelegate.m in Sources */, 551 | 8EF55C651A54E4AD002962DF /* KTPomodoroTableViewController.m in Sources */, 552 | 8EF55C2E1A54DFC2002962DF /* main.m in Sources */, 553 | 8EF55C5F1A54E29F002962DF /* KTCoreDataStack.m in Sources */, 554 | 8E2668011A5AF05800C36D0C /* KTPomodoroActivityModel.m in Sources */, 555 | 8EF55C6F1A54EC48002962DF /* KTPomodoroTableViewCell.m in Sources */, 556 | 8EC91CB81A719268007D0CD6 /* KTActiveActivityState.m in Sources */, 557 | 8EC91CBC1A719806007D0CD6 /* KTActivityManager.m in Sources */, 558 | 8E64C1061A5F4B2700A4D526 /* KTPomodoroTaskConstants.m in Sources */, 559 | 8EF55C6A1A54EA82002962DF /* KTPomodoroModel.xcdatamodeld in Sources */, 560 | ); 561 | runOnlyForDeploymentPostprocessing = 0; 562 | }; 563 | 8EF55C401A54DFC2002962DF /* Sources */ = { 564 | isa = PBXSourcesBuildPhase; 565 | buildActionMask = 2147483647; 566 | files = ( 567 | 8EF55C4B1A54DFC2002962DF /* KTPomodoroTests.m in Sources */, 568 | ); 569 | runOnlyForDeploymentPostprocessing = 0; 570 | }; 571 | /* End PBXSourcesBuildPhase section */ 572 | 573 | /* Begin PBXTargetDependency section */ 574 | 8E0F774F1A55D0CF0008C4ED /* PBXTargetDependency */ = { 575 | isa = PBXTargetDependency; 576 | target = 8E0F774B1A55D0CF0008C4ED /* KTPomodoro WatchKit App */; 577 | targetProxy = 8E0F774E1A55D0CF0008C4ED /* PBXContainerItemProxy */; 578 | }; 579 | 8E0F77591A55D0CF0008C4ED /* PBXTargetDependency */ = { 580 | isa = PBXTargetDependency; 581 | target = 8E0F773D1A55D0CF0008C4ED /* KTPomodoro WatchKit Extension */; 582 | targetProxy = 8E0F77581A55D0CF0008C4ED /* PBXContainerItemProxy */; 583 | }; 584 | 8EF55C461A54DFC2002962DF /* PBXTargetDependency */ = { 585 | isa = PBXTargetDependency; 586 | target = 8EF55C271A54DFC1002962DF /* KTPomodoro */; 587 | targetProxy = 8EF55C451A54DFC2002962DF /* PBXContainerItemProxy */; 588 | }; 589 | /* End PBXTargetDependency section */ 590 | 591 | /* Begin PBXVariantGroup section */ 592 | 8E0F77531A55D0CF0008C4ED /* Interface.storyboard */ = { 593 | isa = PBXVariantGroup; 594 | children = ( 595 | 8E0F77541A55D0CF0008C4ED /* Base */, 596 | ); 597 | name = Interface.storyboard; 598 | sourceTree = ""; 599 | }; 600 | 8EF55C3D1A54DFC2002962DF /* LaunchScreen.xib */ = { 601 | isa = PBXVariantGroup; 602 | children = ( 603 | 8EF55C3E1A54DFC2002962DF /* Base */, 604 | ); 605 | name = LaunchScreen.xib; 606 | sourceTree = ""; 607 | }; 608 | 8EF5AF2B1A60652D00A40CE8 /* KTWatchTaskCompletedNotificationStoryboard.storyboard */ = { 609 | isa = PBXVariantGroup; 610 | children = ( 611 | 8EF5AF2C1A60652D00A40CE8 /* Base */, 612 | ); 613 | name = KTWatchTaskCompletedNotificationStoryboard.storyboard; 614 | sourceTree = ""; 615 | }; 616 | /* End PBXVariantGroup section */ 617 | 618 | /* Begin XCBuildConfiguration section */ 619 | 8E0F775C1A55D0CF0008C4ED /* Debug */ = { 620 | isa = XCBuildConfiguration; 621 | buildSettings = { 622 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 623 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 624 | GCC_PREPROCESSOR_DEFINITIONS = ( 625 | "DEBUG=1", 626 | "$(inherited)", 627 | ); 628 | IBSC_MODULE = KTPomodoro_WatchKit_Extension; 629 | INFOPLIST_FILE = "KTPomodoro WatchKit App/Info.plist"; 630 | PRODUCT_NAME = "$(TARGET_NAME)"; 631 | SKIP_INSTALL = YES; 632 | TARGETED_DEVICE_FAMILY = 4; 633 | "TARGETED_DEVICE_FAMILY[sdk=iphonesimulator*]" = "1,4"; 634 | }; 635 | name = Debug; 636 | }; 637 | 8E0F775D1A55D0CF0008C4ED /* Release */ = { 638 | isa = XCBuildConfiguration; 639 | buildSettings = { 640 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 641 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 642 | IBSC_MODULE = KTPomodoro_WatchKit_Extension; 643 | INFOPLIST_FILE = "KTPomodoro WatchKit App/Info.plist"; 644 | PRODUCT_NAME = "$(TARGET_NAME)"; 645 | SKIP_INSTALL = YES; 646 | TARGETED_DEVICE_FAMILY = 4; 647 | "TARGETED_DEVICE_FAMILY[sdk=iphonesimulator*]" = "1,4"; 648 | }; 649 | name = Release; 650 | }; 651 | 8E0F775F1A55D0CF0008C4ED /* Debug */ = { 652 | isa = XCBuildConfiguration; 653 | buildSettings = { 654 | CODE_SIGN_ENTITLEMENTS = "KTPomodoro WatchKit Extension/KTPomodoro WatchKit Extension.entitlements"; 655 | CODE_SIGN_IDENTITY = "iPhone Developer: Kenny Tang (3ZSQ9FX37R)"; 656 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 657 | GCC_PREPROCESSOR_DEFINITIONS = ( 658 | "DEBUG=1", 659 | "$(inherited)", 660 | ); 661 | INFOPLIST_FILE = "KTPomodoro WatchKit Extension/Info.plist"; 662 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 663 | PRODUCT_NAME = "${TARGET_NAME}"; 664 | PROVISIONING_PROFILE = "98320b9c-a4f5-426d-87a1-5de36cea06e8"; 665 | SKIP_INSTALL = YES; 666 | }; 667 | name = Debug; 668 | }; 669 | 8E0F77601A55D0CF0008C4ED /* Release */ = { 670 | isa = XCBuildConfiguration; 671 | buildSettings = { 672 | CODE_SIGN_ENTITLEMENTS = "KTPomodoro WatchKit Extension/KTPomodoro WatchKit Extension.entitlements"; 673 | CODE_SIGN_IDENTITY = "iPhone Developer: Kenny Tang (3ZSQ9FX37R)"; 674 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 675 | INFOPLIST_FILE = "KTPomodoro WatchKit Extension/Info.plist"; 676 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @executable_path/../../Frameworks"; 677 | PRODUCT_NAME = "${TARGET_NAME}"; 678 | PROVISIONING_PROFILE = "98320b9c-a4f5-426d-87a1-5de36cea06e8"; 679 | SKIP_INSTALL = YES; 680 | }; 681 | name = Release; 682 | }; 683 | 8EF55C4C1A54DFC2002962DF /* Debug */ = { 684 | isa = XCBuildConfiguration; 685 | buildSettings = { 686 | ALWAYS_SEARCH_USER_PATHS = NO; 687 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 688 | CLANG_CXX_LIBRARY = "libc++"; 689 | CLANG_ENABLE_MODULES = YES; 690 | CLANG_ENABLE_OBJC_ARC = YES; 691 | CLANG_WARN_BOOL_CONVERSION = YES; 692 | CLANG_WARN_CONSTANT_CONVERSION = YES; 693 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 694 | CLANG_WARN_EMPTY_BODY = YES; 695 | CLANG_WARN_ENUM_CONVERSION = YES; 696 | CLANG_WARN_INT_CONVERSION = YES; 697 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 698 | CLANG_WARN_UNREACHABLE_CODE = YES; 699 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 700 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 701 | COPY_PHASE_STRIP = NO; 702 | ENABLE_STRICT_OBJC_MSGSEND = YES; 703 | GCC_C_LANGUAGE_STANDARD = gnu99; 704 | GCC_DYNAMIC_NO_PIC = NO; 705 | GCC_OPTIMIZATION_LEVEL = 0; 706 | GCC_PREPROCESSOR_DEFINITIONS = ( 707 | "DEBUG=1", 708 | "$(inherited)", 709 | ); 710 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 711 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 712 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 713 | GCC_WARN_UNDECLARED_SELECTOR = YES; 714 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 715 | GCC_WARN_UNUSED_FUNCTION = YES; 716 | GCC_WARN_UNUSED_VARIABLE = YES; 717 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 718 | MTL_ENABLE_DEBUG_INFO = YES; 719 | ONLY_ACTIVE_ARCH = YES; 720 | SDKROOT = iphoneos; 721 | }; 722 | name = Debug; 723 | }; 724 | 8EF55C4D1A54DFC2002962DF /* Release */ = { 725 | isa = XCBuildConfiguration; 726 | buildSettings = { 727 | ALWAYS_SEARCH_USER_PATHS = NO; 728 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 729 | CLANG_CXX_LIBRARY = "libc++"; 730 | CLANG_ENABLE_MODULES = YES; 731 | CLANG_ENABLE_OBJC_ARC = YES; 732 | CLANG_WARN_BOOL_CONVERSION = YES; 733 | CLANG_WARN_CONSTANT_CONVERSION = YES; 734 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 735 | CLANG_WARN_EMPTY_BODY = YES; 736 | CLANG_WARN_ENUM_CONVERSION = YES; 737 | CLANG_WARN_INT_CONVERSION = YES; 738 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 739 | CLANG_WARN_UNREACHABLE_CODE = YES; 740 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 741 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 742 | COPY_PHASE_STRIP = NO; 743 | ENABLE_NS_ASSERTIONS = NO; 744 | ENABLE_STRICT_OBJC_MSGSEND = YES; 745 | GCC_C_LANGUAGE_STANDARD = gnu99; 746 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 747 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 748 | GCC_WARN_UNDECLARED_SELECTOR = YES; 749 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 750 | GCC_WARN_UNUSED_FUNCTION = YES; 751 | GCC_WARN_UNUSED_VARIABLE = YES; 752 | IPHONEOS_DEPLOYMENT_TARGET = 8.2; 753 | MTL_ENABLE_DEBUG_INFO = NO; 754 | SDKROOT = iphoneos; 755 | VALIDATE_PRODUCT = YES; 756 | }; 757 | name = Release; 758 | }; 759 | 8EF55C4F1A54DFC2002962DF /* Debug */ = { 760 | isa = XCBuildConfiguration; 761 | buildSettings = { 762 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 763 | CODE_SIGN_ENTITLEMENTS = KTPomodoro/KTPomodoro.entitlements; 764 | CODE_SIGN_IDENTITY = "iPhone Developer: Kenny Tang (3ZSQ9FX37R)"; 765 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 766 | INFOPLIST_FILE = KTPomodoro/Info.plist; 767 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 768 | PRODUCT_NAME = "$(TARGET_NAME)"; 769 | PROVISIONING_PROFILE = "ce7bb023-8f2a-48f2-9f84-732bfc519fd0"; 770 | }; 771 | name = Debug; 772 | }; 773 | 8EF55C501A54DFC2002962DF /* Release */ = { 774 | isa = XCBuildConfiguration; 775 | buildSettings = { 776 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 777 | CODE_SIGN_ENTITLEMENTS = KTPomodoro/KTPomodoro.entitlements; 778 | CODE_SIGN_IDENTITY = "iPhone Developer: Kenny Tang (3ZSQ9FX37R)"; 779 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 780 | INFOPLIST_FILE = KTPomodoro/Info.plist; 781 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 782 | PRODUCT_NAME = "$(TARGET_NAME)"; 783 | PROVISIONING_PROFILE = "ce7bb023-8f2a-48f2-9f84-732bfc519fd0"; 784 | }; 785 | name = Release; 786 | }; 787 | 8EF55C521A54DFC2002962DF /* Debug */ = { 788 | isa = XCBuildConfiguration; 789 | buildSettings = { 790 | BUNDLE_LOADER = "$(TEST_HOST)"; 791 | FRAMEWORK_SEARCH_PATHS = ( 792 | "$(SDKROOT)/Developer/Library/Frameworks", 793 | "$(inherited)", 794 | ); 795 | GCC_PREPROCESSOR_DEFINITIONS = ( 796 | "DEBUG=1", 797 | "$(inherited)", 798 | ); 799 | INFOPLIST_FILE = KTPomodoroTests/Info.plist; 800 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 801 | PRODUCT_NAME = "$(TARGET_NAME)"; 802 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KTPomodoro.app/KTPomodoro"; 803 | }; 804 | name = Debug; 805 | }; 806 | 8EF55C531A54DFC2002962DF /* Release */ = { 807 | isa = XCBuildConfiguration; 808 | buildSettings = { 809 | BUNDLE_LOADER = "$(TEST_HOST)"; 810 | FRAMEWORK_SEARCH_PATHS = ( 811 | "$(SDKROOT)/Developer/Library/Frameworks", 812 | "$(inherited)", 813 | ); 814 | INFOPLIST_FILE = KTPomodoroTests/Info.plist; 815 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 816 | PRODUCT_NAME = "$(TARGET_NAME)"; 817 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/KTPomodoro.app/KTPomodoro"; 818 | }; 819 | name = Release; 820 | }; 821 | /* End XCBuildConfiguration section */ 822 | 823 | /* Begin XCConfigurationList section */ 824 | 8E0F775B1A55D0CF0008C4ED /* Build configuration list for PBXNativeTarget "KTPomodoro WatchKit App" */ = { 825 | isa = XCConfigurationList; 826 | buildConfigurations = ( 827 | 8E0F775C1A55D0CF0008C4ED /* Debug */, 828 | 8E0F775D1A55D0CF0008C4ED /* Release */, 829 | ); 830 | defaultConfigurationIsVisible = 0; 831 | defaultConfigurationName = Release; 832 | }; 833 | 8E0F775E1A55D0CF0008C4ED /* Build configuration list for PBXNativeTarget "KTPomodoro WatchKit Extension" */ = { 834 | isa = XCConfigurationList; 835 | buildConfigurations = ( 836 | 8E0F775F1A55D0CF0008C4ED /* Debug */, 837 | 8E0F77601A55D0CF0008C4ED /* Release */, 838 | ); 839 | defaultConfigurationIsVisible = 0; 840 | defaultConfigurationName = Release; 841 | }; 842 | 8EF55C231A54DFC1002962DF /* Build configuration list for PBXProject "KTPomodoro" */ = { 843 | isa = XCConfigurationList; 844 | buildConfigurations = ( 845 | 8EF55C4C1A54DFC2002962DF /* Debug */, 846 | 8EF55C4D1A54DFC2002962DF /* Release */, 847 | ); 848 | defaultConfigurationIsVisible = 0; 849 | defaultConfigurationName = Release; 850 | }; 851 | 8EF55C4E1A54DFC2002962DF /* Build configuration list for PBXNativeTarget "KTPomodoro" */ = { 852 | isa = XCConfigurationList; 853 | buildConfigurations = ( 854 | 8EF55C4F1A54DFC2002962DF /* Debug */, 855 | 8EF55C501A54DFC2002962DF /* Release */, 856 | ); 857 | defaultConfigurationIsVisible = 0; 858 | defaultConfigurationName = Release; 859 | }; 860 | 8EF55C511A54DFC2002962DF /* Build configuration list for PBXNativeTarget "KTPomodoroTests" */ = { 861 | isa = XCConfigurationList; 862 | buildConfigurations = ( 863 | 8EF55C521A54DFC2002962DF /* Debug */, 864 | 8EF55C531A54DFC2002962DF /* Release */, 865 | ); 866 | defaultConfigurationIsVisible = 0; 867 | defaultConfigurationName = Release; 868 | }; 869 | /* End XCConfigurationList section */ 870 | 871 | /* Begin XCVersionGroup section */ 872 | 8EF55C681A54EA82002962DF /* KTPomodoroModel.xcdatamodeld */ = { 873 | isa = XCVersionGroup; 874 | children = ( 875 | 8EF55C691A54EA82002962DF /* KTPomodoroModel.xcdatamodel */, 876 | ); 877 | currentVersion = 8EF55C691A54EA82002962DF /* KTPomodoroModel.xcdatamodel */; 878 | name = KTPomodoroModel.xcdatamodeld; 879 | path = Model/KTPomodoroModel.xcdatamodeld; 880 | sourceTree = ""; 881 | versionGroupType = wrapper.xcdatamodel; 882 | }; 883 | /* End XCVersionGroup section */ 884 | }; 885 | rootObject = 8EF55C201A54DFC1002962DF /* Project object */; 886 | } 887 | -------------------------------------------------------------------------------- /KTPomodoro.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /KTPomodoro.xcodeproj/xcuserdata/ktang.xcuserdatad/xcschemes/KTPomodoro.xcscheme: -------------------------------------------------------------------------------- 1 | 2 | 5 | 8 | 9 | 15 | 21 | 22 | 23 | 29 | 35 | 36 | 37 | 38 | 39 | 44 | 45 | 47 | 53 | 54 | 55 | 56 | 57 | 63 | 64 | 65 | 66 | 75 | 77 | 83 | 84 | 85 | 86 | 87 | 88 | 94 | 96 | 102 | 103 | 104 | 105 | 107 | 108 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /KTPomodoro.xcodeproj/xcuserdata/ktang.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | KTPomodoro WatchKit - Pomo Finished Notifications.xcscheme 8 | 9 | orderHint 10 | 2 11 | 12 | KTPomodoro WatchKit - Task Finished Notifications.xcscheme 13 | 14 | orderHint 15 | 3 16 | 17 | KTPomodoro WatchKit App.xcscheme 18 | 19 | orderHint 20 | 1 21 | 22 | KTPomodoro.xcscheme 23 | 24 | orderHint 25 | 0 26 | 27 | 28 | SuppressBuildableAutocreation 29 | 30 | 8E0F773D1A55D0CF0008C4ED 31 | 32 | primary 33 | 34 | 35 | 8E0F774B1A55D0CF0008C4ED 36 | 37 | primary 38 | 39 | 40 | 8EF55C271A54DFC1002962DF 41 | 42 | primary 43 | 44 | 45 | 8EF55C431A54DFC2002962DF 46 | 47 | primary 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /KTPomodoro/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 20 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /KTPomodoro/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "40x40", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "60x60", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "60x60", 31 | "scale" : "3x" 32 | } 33 | ], 34 | "info" : { 35 | "version" : 1, 36 | "author" : "xcode" 37 | } 38 | } -------------------------------------------------------------------------------- /KTPomodoro/Images.xcassets/tomato_app.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "tomato_app@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /KTPomodoro/Images.xcassets/tomato_app.imageset/tomato_app@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro/Images.xcassets/tomato_app.imageset/tomato_app@2x.png -------------------------------------------------------------------------------- /KTPomodoro/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Bundle Display Name 6 | Cherry 7 | CFBundleDevelopmentRegion 8 | en 9 | CFBundleExecutable 10 | $(EXECUTABLE_NAME) 11 | CFBundleIdentifier 12 | com.corgitoergosum.$(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 | LSRequiresIPhoneOS 26 | 27 | UILaunchStoryboardName 28 | LaunchScreen 29 | UIRequiredDeviceCapabilities 30 | 31 | armv7 32 | 33 | UIStatusBarStyle 34 | UIStatusBarStyleLightContent 35 | UISupportedInterfaceOrientations 36 | 37 | UIInterfaceOrientationPortrait 38 | 39 | UIViewControllerBasedStatusBarAppearance 40 | 41 | 42 | 43 | -------------------------------------------------------------------------------- /KTPomodoro/KTAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTAppDelegate.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | 16 | @end 17 | 18 | -------------------------------------------------------------------------------- /KTPomodoro/KTAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTAppDelegate.h" 10 | #import "KTCoreDataStack.h" 11 | #import "KTPomodoroTableViewController.h" 12 | 13 | @interface KTAppDelegate () 14 | @end 15 | 16 | @implementation KTAppDelegate 17 | 18 | 19 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 20 | // Override point for customization after application launch. 21 | 22 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 23 | 24 | UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:[KTPomodoroTableViewController new]]; 25 | navigationController.navigationBar.barTintColor = [UIColor redColor]; 26 | [UIApplication sharedApplication].statusBarStyle = UIStatusBarStyleLightContent; 27 | [[UINavigationBar appearance] setTitleTextAttributes:@{ 28 | NSForegroundColorAttributeName:[UIColor whiteColor], 29 | NSFontAttributeName:[UIFont fontWithName:@"HelveticaNeue" size:20.0f] 30 | }]; 31 | self.window.rootViewController = navigationController; 32 | 33 | [self.window makeKeyAndVisible]; 34 | 35 | return YES; 36 | } 37 | 38 | - (void)application:(UIApplication *)application handleWatchKitExtensionRequest:(NSDictionary *)userInfo reply:(void (^)(NSDictionary *))reply 39 | { 40 | NSLog(@"userInfo: %@", userInfo); 41 | reply(@{}); 42 | } 43 | 44 | 45 | - (void)applicationWillResignActive:(UIApplication *)application { 46 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 47 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 48 | } 49 | 50 | - (void)applicationDidEnterBackground:(UIApplication *)application { 51 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 52 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 53 | } 54 | 55 | - (void)applicationWillEnterForeground:(UIApplication *)application { 56 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 57 | } 58 | 59 | - (void)applicationDidBecomeActive:(UIApplication *)application { 60 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 61 | } 62 | 63 | - (void)applicationWillTerminate:(UIApplication *)application { 64 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 65 | // Saves changes in the application's managed object context before the application terminates. 66 | [[KTCoreDataStack sharedInstance] saveContext]; 67 | } 68 | 69 | @end 70 | -------------------------------------------------------------------------------- /KTPomodoro/KTPomodoro.entitlements: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | com.apple.security.application-groups 6 | 7 | group.com.corgitoergosum.KTPomodoro 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /KTPomodoro/Model/KTActiveActivityState.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTActiveActivityState.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/22/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTActiveActivityState : NSObject 12 | 13 | @property (nonatomic) NSString *activityID; 14 | @property (nonatomic) NSNumber *status; 15 | @property (nonatomic) NSNumber *currentPomo; 16 | @property (nonatomic) NSNumber *elapsedSecs; 17 | 18 | 19 | @end 20 | -------------------------------------------------------------------------------- /KTPomodoro/Model/KTActiveActivityState.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTActiveActivityState.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/22/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTActiveActivityState.h" 10 | 11 | @implementation KTActiveActivityState 12 | 13 | - (void)encodeWithCoder:(NSCoder *)encoder { 14 | [encoder encodeObject:self.activityID forKey:@"activityID"]; 15 | [encoder encodeObject:self.status forKey:@"status"]; 16 | [encoder encodeObject:self.currentPomo forKey:@"currentPomo"]; 17 | [encoder encodeObject:self.elapsedSecs forKey:@"elapsedSecs"]; 18 | } 19 | 20 | - (id)initWithCoder:(NSCoder *)decoder { 21 | if((self = [super init])) { 22 | self.activityID = [decoder decodeObjectForKey:@"activityID"]; 23 | self.status = [decoder decodeObjectForKey:@"status"]; 24 | self.currentPomo = [decoder decodeObjectForKey:@"currentPomo"]; 25 | self.elapsedSecs = [decoder decodeObjectForKey:@"elapsedSecs"]; 26 | } 27 | return self; 28 | } 29 | 30 | @end 31 | -------------------------------------------------------------------------------- /KTPomodoro/Model/KTCoreDataStack.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTCoreDataStack.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "KTPomodoroActivityModel.h" 12 | 13 | @interface KTCoreDataStack : NSObject 14 | 15 | + (KTCoreDataStack*)sharedInstance; 16 | 17 | - (NSArray*)allTasks; 18 | 19 | @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; 20 | @property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel; 21 | @property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator; 22 | 23 | - (KTPomodoroActivityModel*)createNewTask:(NSString*)taskName taskDesc:(NSString*)description pomodoros:(NSUInteger)pomodoros; 24 | 25 | - (void)saveContext; 26 | - (NSURL *)applicationDocumentsDirectory; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /KTPomodoro/Model/KTCoreDataStack.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTCoreDataStack.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTCoreDataStack.h" 10 | #import "KTPomodoroTaskConstants.h" 11 | 12 | // This turns storing CoreData persistance store in app container on and off. 13 | #define kKTCoreDataStackShouldUseAppContainer 0 14 | 15 | 16 | @implementation KTCoreDataStack 17 | 18 | + (KTCoreDataStack*)sharedInstance 19 | { 20 | static KTCoreDataStack* _instance; 21 | static dispatch_once_t onceToken; 22 | dispatch_once(&onceToken, ^{ 23 | _instance = [KTCoreDataStack new]; 24 | [_instance seedData]; 25 | 26 | }); 27 | return _instance; 28 | } 29 | 30 | #pragma mark - Helpers 31 | 32 | - (KTPomodoroActivityModel*)createNewTask:(NSString*)taskName taskDesc:(NSString*)description pomodoros:(NSUInteger)pomodoros 33 | { 34 | NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"KTPomodoroActivityModel" inManagedObjectContext:self.managedObjectContext]; 35 | 36 | KTPomodoroActivityModel *newTask1 = (KTPomodoroActivityModel*)[[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:self.managedObjectContext]; 37 | newTask1.name = taskName; 38 | newTask1.desc = description; 39 | newTask1.status = @(KTPomodoroActivityStatusStopped); 40 | newTask1.expected_pomo = @(pomodoros); 41 | newTask1.actual_pomo = @(0); 42 | newTask1.created_time = [NSDate new]; 43 | newTask1.activityID = [[NSUUID UUID] UUIDString]; 44 | 45 | return newTask1; 46 | } 47 | 48 | - (void)seedData 49 | { 50 | if (![[self allTasks] count]) { 51 | 52 | // Create Managed Object 53 | NSEntityDescription *entityDescription = [NSEntityDescription entityForName:@"KTPomodoroActivityModel" inManagedObjectContext:self.managedObjectContext]; 54 | 55 | KTPomodoroActivityModel *newTask1 = (KTPomodoroActivityModel*)[[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:self.managedObjectContext]; 56 | newTask1.activityID = [[NSUUID UUID] UUIDString]; 57 | newTask1.name = @"Task 1"; 58 | newTask1.desc = @"Task desc"; 59 | newTask1.status = @(KTPomodoroActivityStatusStopped); 60 | newTask1.expected_pomo = @(1); 61 | newTask1.actual_pomo = @(0); 62 | newTask1.created_time = [NSDate new]; 63 | 64 | KTPomodoroActivityModel *newTask2 = (KTPomodoroActivityModel*)[[NSManagedObject alloc] initWithEntity:entityDescription insertIntoManagedObjectContext:self.managedObjectContext]; 65 | newTask2.activityID = [[NSUUID UUID] UUIDString]; 66 | newTask2.name = @"Task 2"; 67 | newTask2.desc = @"Task desc"; 68 | newTask2.status = @(KTPomodoroActivityStatusStopped); 69 | newTask2.expected_pomo = @(1); 70 | newTask2.actual_pomo = @(0); 71 | newTask2.created_time = [NSDate new]; 72 | 73 | } 74 | } 75 | 76 | - (NSArray*)allTasks 77 | { 78 | NSFetchRequest* request = [NSFetchRequest fetchRequestWithEntityName:@"KTPomodoroActivityModel"]; 79 | 80 | NSSortDescriptor *createdTimeDescriptor = [[NSSortDescriptor alloc] initWithKey:@"created_time" ascending:NO]; 81 | NSSortDescriptor *inProgressStatusDescriptor = [[NSSortDescriptor alloc] initWithKey:@"status" ascending:YES]; 82 | 83 | request.sortDescriptors = @[inProgressStatusDescriptor, createdTimeDescriptor]; 84 | 85 | NSArray* objects = [self.managedObjectContext executeFetchRequest:request error:NULL]; 86 | return objects; 87 | } 88 | 89 | 90 | #pragma mark - Core Data stack 91 | 92 | @synthesize managedObjectContext = _managedObjectContext; 93 | @synthesize managedObjectModel = _managedObjectModel; 94 | @synthesize persistentStoreCoordinator = _persistentStoreCoordinator; 95 | 96 | - (NSURL *)applicationDocumentsDirectory { 97 | // The directory the application uses to store the Core Data store file. This code uses a directory named "com.corgitoergosum.KTPomodoro" in the application's documents directory. 98 | return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject]; 99 | } 100 | 101 | - (NSManagedObjectModel *)managedObjectModel { 102 | // The managed object model for the application. It is a fatal error for the application not to be able to find and load its model. 103 | if (_managedObjectModel != nil) { 104 | return _managedObjectModel; 105 | } 106 | NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"KTPomodoroModel" withExtension:@"momd"]; 107 | _managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL]; 108 | return _managedObjectModel; 109 | } 110 | 111 | - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { 112 | // The persistent store coordinator for the application. This implementation creates and return a coordinator, having added the store for the application to it. 113 | if (_persistentStoreCoordinator != nil) { 114 | return _persistentStoreCoordinator; 115 | } 116 | 117 | // Create the coordinator and store 118 | 119 | _persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; 120 | NSURL *storeURL = nil; 121 | 122 | #if kKTCoreDataStackShouldUseAppContainer 123 | NSString *appGroupID = @"group.com.corgitoergosum.KTPomodoro"; 124 | NSFileManager *fileManager = [NSFileManager defaultManager]; 125 | NSURL *appGroupURL = [fileManager containerURLForSecurityApplicationGroupIdentifier:appGroupID]; 126 | storeURL = [appGroupURL URLByAppendingPathComponent:@"KTPomodoro.sqlite"]; 127 | 128 | #else 129 | storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"KTPomodoro.sqlite"]; 130 | #endif 131 | 132 | NSError *error = nil; 133 | NSString *failureReason = @"There was an error creating or loading the application's saved data."; 134 | if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) { 135 | // Report any error we got. 136 | NSMutableDictionary *dict = [NSMutableDictionary dictionary]; 137 | dict[NSLocalizedDescriptionKey] = @"Failed to initialize the application's saved data"; 138 | dict[NSLocalizedFailureReasonErrorKey] = failureReason; 139 | dict[NSUnderlyingErrorKey] = error; 140 | error = [NSError errorWithDomain:@"YOUR_ERROR_DOMAIN" code:9999 userInfo:dict]; 141 | // Replace this with code to handle the error appropriately. 142 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 143 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 144 | abort(); 145 | } 146 | 147 | return _persistentStoreCoordinator; 148 | } 149 | 150 | 151 | - (NSManagedObjectContext *)managedObjectContext { 152 | // Returns the managed object context for the application (which is already bound to the persistent store coordinator for the application.) 153 | if (_managedObjectContext != nil) { 154 | return _managedObjectContext; 155 | } 156 | 157 | NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator]; 158 | if (!coordinator) { 159 | return nil; 160 | } 161 | _managedObjectContext = [[NSManagedObjectContext alloc] init]; 162 | [_managedObjectContext setPersistentStoreCoordinator:coordinator]; 163 | return _managedObjectContext; 164 | } 165 | 166 | #pragma mark - Core Data Saving support 167 | 168 | - (void)saveContext { 169 | NSManagedObjectContext *managedObjectContext = self.managedObjectContext; 170 | if (managedObjectContext != nil) { 171 | NSError *error = nil; 172 | if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) { 173 | // Replace this implementation with code to handle the error appropriately. 174 | // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development. 175 | NSLog(@"Unresolved error %@, %@", error, [error userInfo]); 176 | abort(); 177 | } 178 | } 179 | } 180 | 181 | @end 182 | -------------------------------------------------------------------------------- /KTPomodoro/Model/KTPomodoroActivityModel.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTPomodoroTask.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/5/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | 13 | @interface KTPomodoroActivityModel : NSManagedObject 14 | 15 | @property (nonatomic, retain) NSString * activityID; 16 | @property (nonatomic, retain) NSNumber * actual_pomo; 17 | @property (nonatomic, retain) NSString * desc; 18 | @property (nonatomic, retain) NSNumber * expected_pomo; 19 | @property (nonatomic, retain) NSString * name; 20 | @property (nonatomic, retain) NSNumber * status; 21 | @property (nonatomic, retain) NSNumber * interruptions; 22 | @property (nonatomic, retain) NSDate * created_time; 23 | 24 | @property (nonatomic, retain) NSNumber * current_pomo; 25 | @property (nonatomic, retain) NSNumber * current_pomo_elapsed_time; 26 | @property (nonatomic, readonly) NSUInteger current_pomo_elapsed_time_int; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /KTPomodoro/Model/KTPomodoroActivityModel.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTPomodoroTask.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/5/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTPomodoroActivityModel.h" 10 | 11 | @implementation KTPomodoroActivityModel 12 | 13 | @dynamic activityID; 14 | @dynamic actual_pomo; 15 | @dynamic desc; 16 | @dynamic expected_pomo; 17 | @dynamic name; 18 | @dynamic status; 19 | @dynamic interruptions; 20 | @dynamic created_time; 21 | @dynamic current_pomo; 22 | @dynamic current_pomo_elapsed_time; 23 | 24 | - (NSUInteger)current_pomo_elapsed_time_int 25 | { 26 | return [self.current_pomo_elapsed_time integerValue]; 27 | } 28 | @end 29 | -------------------------------------------------------------------------------- /KTPomodoro/Model/KTPomodoroModel.xcdatamodeld/KTPomodoroModel.xcdatamodel/contents: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /KTPomodoro/Model/KTPomodoroTaskConstants.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTPomodoroTaskConstants.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/8/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | 13 | @interface KTPomodoroTaskConstants : NSObject 14 | 15 | typedef NS_ENUM (NSUInteger, KTPomodoroActivityStatus) { 16 | KTPomodoroActivityStatusInProgress = 0, 17 | KTPomodoroActivityStatusStopped, 18 | KTPomodoroActivityStatusCompleted, 19 | KTPomodoroActivityStatusUnknown 20 | }; 21 | 22 | typedef NS_ENUM (NSUInteger, KTPomodoroStartActivityError) { 23 | KTPomodoroStartActivityOtherActivityActiveError = 0, 24 | }; 25 | 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /KTPomodoro/Model/KTPomodoroTaskConstants.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTPomodoroTaskConstants.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/8/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTPomodoroTaskConstants.h" 10 | 11 | @implementation KTPomodoroTaskConstants 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KTPomodoro/Resources/KTPomodoroTableViewCell.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 24 | 30 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /KTPomodoro/Resources/Shared/Settings-Watch.bundle/Root.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | StringsTable 6 | Root 7 | PreferenceSpecifiers 8 | 9 | 10 | Type 11 | PSToggleSwitchSpecifier 12 | Title 13 | Delete completed activities 14 | Key 15 | delete_completed_activities 16 | DefaultValue 17 | 18 | 19 | 20 | Type 21 | PSTextFieldSpecifier 22 | Title 23 | Break Length 24 | Key 25 | break_length 26 | DefaultValue 27 | 5 28 | KeyboardType 29 | NumberPad 30 | 31 | 32 | Type 33 | PSTextFieldSpecifier 34 | Title 35 | Pomo Length 36 | Key 37 | pomo_length 38 | DefaultValue 39 | 25 40 | KeyboardType 41 | NumberPad 42 | 43 | 44 | ApplicationGroupContainerIdentifier 45 | group.com.corgitoergosum.KTPomodoro 46 | 47 | 48 | -------------------------------------------------------------------------------- /KTPomodoro/Resources/Shared/Settings-Watch.bundle/en.lproj/Root.strings: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/KTPomodoro/Resources/Shared/Settings-Watch.bundle/en.lproj/Root.strings -------------------------------------------------------------------------------- /KTPomodoro/Utils/KTActivityManager.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTActivityManager.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/22/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KTPomodoroActivityModel.h" 11 | 12 | @protocol KTActivityManagerDelegate; 13 | 14 | 15 | @interface KTActivityManager : NSObject 16 | 17 | @property (nonatomic, weak) id delegate; 18 | @property (nonatomic, readonly) KTPomodoroActivityModel *activity; 19 | 20 | + (instancetype)sharedInstance; 21 | 22 | + (NSUInteger)pomodoroDurationMinutes; 23 | 24 | + (NSUInteger)breakDurationMinutes; 25 | 26 | + (NSUInteger)pomoRemainingMinutes:(NSUInteger)totalRemainingSecs; 27 | 28 | + (NSUInteger)pomoRemainingSecsInCurrentMinute:(NSUInteger)totalRemainingSecs; 29 | 30 | 31 | - (void)startActivity:(KTPomodoroActivityModel*)activity error:(NSError**)error; 32 | 33 | - (void)stopActivity; 34 | 35 | - (void)stopActivityOnInterruption; 36 | 37 | - (BOOL)hasOtherActiveActivityInSharedState:(NSString*)activityID; 38 | 39 | @end 40 | 41 | 42 | @protocol KTActivityManagerDelegate 43 | 44 | - (void)activityManager:(KTActivityManager*)manager activityDidUpdate:(KTPomodoroActivityModel*)activity; 45 | 46 | - (void)activityManager:(KTActivityManager*)manager activityPausedForBreak:(NSUInteger)elapsedTime; 47 | 48 | @end -------------------------------------------------------------------------------- /KTPomodoro/Utils/KTActivityManager.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTActivityManager.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/22/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTActivityManager.h" 10 | #import "KTActiveActivityState.h" 11 | #import "KTCoreDataStack.h" 12 | #import "KTPomodoroTaskConstants.h" 13 | #import "KTSharedUserDefaults.h" 14 | 15 | 16 | @interface KTActivityManager() 17 | 18 | @property (atomic) KTPomodoroActivityModel *activity; 19 | @property (nonatomic) NSTimer *activityTimer; 20 | @property (nonatomic) NSTimer *breakTimer; 21 | @property (nonatomic) NSUInteger currentPomo; 22 | 23 | @property (nonatomic) NSUInteger breakElapsed; 24 | 25 | @end 26 | 27 | @implementation KTActivityManager 28 | 29 | #pragma mark - Public 30 | 31 | + (instancetype)sharedInstance { 32 | static KTActivityManager *_instance; 33 | static dispatch_once_t onceToken; 34 | dispatch_once(&onceToken, ^{ 35 | _instance = [KTActivityManager new]; 36 | }); 37 | return _instance; 38 | } 39 | 40 | + (NSUInteger)pomodoroDurationMinutes 41 | { 42 | return [KTSharedUserDefaults pomoDuration]; 43 | } 44 | 45 | + (NSUInteger)breakDurationMinutes 46 | { 47 | return [KTSharedUserDefaults breakDuration]; 48 | } 49 | 50 | - (void)startActivity:(KTPomodoroActivityModel*)activity error:(NSError**)error 51 | { 52 | if ([self hasOtherActiveActivityInSharedState:activity.activityID]){ 53 | // log error 54 | // inform delegate 55 | *error = [NSError errorWithDomain:@"com.corgitoergosum.net" code:KTPomodoroStartActivityOtherActivityActiveError userInfo:nil]; 56 | 57 | return; 58 | } 59 | if (!activity) { 60 | return; 61 | } 62 | 63 | self.activity = activity; 64 | self.activity.current_pomo_elapsed_time = @(0); 65 | self.activity.status = @(KTPomodoroActivityStatusInProgress); 66 | self.currentPomo = 0; 67 | self.breakElapsed = 0; 68 | 69 | [self updateSharedActiveActivityState:activity.activityID 70 | currentPomo:self.currentPomo 71 | status:activity.status]; 72 | 73 | [self invalidateTimers]; 74 | 75 | [self scheduleTimerInRunLoop:self.activityTimer]; 76 | 77 | } 78 | 79 | - (void)stopActivityOnInterruption 80 | { 81 | self.activity.status = @(KTPomodoroActivityStatusStopped); 82 | [self updateSharedActiveActivityState:self.activity.activityID 83 | currentPomo:self.currentPomo 84 | status:self.activity.status]; 85 | 86 | 87 | // save to disk 88 | [[KTCoreDataStack sharedInstance] saveContext]; 89 | 90 | // house keeping 91 | [self resetManagerInternalState]; 92 | 93 | } 94 | 95 | - (void)stopActivity 96 | { 97 | self.activity.status = @(KTPomodoroActivityStatusStopped); 98 | [self updateSharedActiveActivityState:self.activity.activityID 99 | currentPomo:self.currentPomo 100 | status:self.activity.status]; 101 | 102 | // save to disk 103 | [[KTCoreDataStack sharedInstance] saveContext]; 104 | 105 | // house keeping 106 | [self resetManagerInternalState]; 107 | 108 | } 109 | 110 | + (NSUInteger)pomoRemainingMinutes:(NSUInteger)totalRemainingSecs 111 | { 112 | NSInteger pomodoroSecs = [KTSharedUserDefaults pomoDuration]*60 - totalRemainingSecs; 113 | 114 | NSUInteger displayMinutes = (NSUInteger)floor(pomodoroSecs/60.0f); 115 | 116 | return displayMinutes; 117 | 118 | } 119 | 120 | + (NSUInteger)pomoRemainingSecsInCurrentMinute:(NSUInteger)totalRemainingSecs 121 | { 122 | NSInteger pomodoroSecs = [KTSharedUserDefaults pomoDuration]*60 - totalRemainingSecs; 123 | 124 | NSUInteger displaySecs = (NSUInteger)pomodoroSecs%60; 125 | return displaySecs; 126 | 127 | } 128 | 129 | #pragma mark - Private 130 | 131 | 132 | #pragma mark - Lazy Loading 133 | 134 | - (NSTimer*)activityTimer 135 | { 136 | if (!_activityTimer) { 137 | _activityTimer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(activityTimerFired:) userInfo:nil repeats:YES]; 138 | } 139 | return _activityTimer; 140 | } 141 | 142 | - (NSTimer*)breakTimer 143 | { 144 | if (!_breakTimer) { 145 | _breakTimer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(breakTimerFired:) userInfo:nil repeats:YES]; 146 | } 147 | return _breakTimer; 148 | } 149 | 150 | 151 | #pragma mark - startActivity: helper methods 152 | 153 | - (BOOL)hasOtherActiveActivityInSharedState:(NSString*)activityID 154 | { 155 | id encodedActivity = [[KTSharedUserDefaults sharedUserDefaults] objectForKey:@"ActiveActivity"]; 156 | KTActiveActivityState *activity = (KTActiveActivityState*)[NSKeyedUnarchiver unarchiveObjectWithData:encodedActivity]; 157 | if (!activityID || !activity) { 158 | return NO; 159 | } 160 | return [activity.activityID isEqualToString:activityID] ? NO : YES; 161 | } 162 | 163 | - (void)updateSharedActiveActivityState:(NSString*)activityID currentPomo:(NSUInteger)currentPomo status:(NSNumber*)status 164 | { 165 | KTActiveActivityState *activity = nil; 166 | 167 | id encodedActivity = [[KTSharedUserDefaults sharedUserDefaults] objectForKey:@"ActiveActivity"]; 168 | NSObject *decodedActivity = [NSKeyedUnarchiver unarchiveObjectWithData:encodedActivity]; 169 | 170 | activity = (KTActiveActivityState*)decodedActivity; 171 | 172 | if (!([activity isKindOfClass:[KTActiveActivityState class]]) || 173 | !([activity.activityID isEqualToString:activityID])){ 174 | activity = [KTActiveActivityState new]; 175 | activity.activityID = activityID; 176 | } 177 | activity.currentPomo = @(currentPomo); 178 | activity.status = status; 179 | 180 | if (status.integerValue == KTPomodoroActivityStatusStopped) { 181 | [[KTSharedUserDefaults sharedUserDefaults] removeObjectForKey:@"ActiveActivity"]; 182 | 183 | } else { 184 | encodedActivity = [NSKeyedArchiver archivedDataWithRootObject:activity]; 185 | [[KTSharedUserDefaults sharedUserDefaults] setObject:encodedActivity forKey:@"ActiveActivity"]; 186 | } 187 | } 188 | 189 | - (void)invalidateTimers 190 | { 191 | [self.activityTimer invalidate]; 192 | [self.breakTimer invalidate]; 193 | _activityTimer = nil; 194 | _breakTimer = nil; 195 | } 196 | 197 | - (void)scheduleTimerInRunLoop:(NSTimer*)timer 198 | { 199 | [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode]; 200 | } 201 | 202 | #pragma mark - timer helper methods 203 | 204 | - (void)activityTimerFired:(id)sender 205 | { 206 | NSUInteger currentPomoElapsed = self.activity.current_pomo_elapsed_time_int+1; 207 | self.activity.current_pomo_elapsed_time = @(currentPomoElapsed); 208 | 209 | [self.delegate activityManager:self activityDidUpdate:self.activity]; 210 | 211 | if (currentPomoElapsed == [KTActivityManager pomodoroDurationMinutes]*60) { 212 | 213 | // reached end of pomo, either: 214 | self.currentPomo++; 215 | 216 | if ([self activityHasMorePomo:self.activity]) { 217 | [self pauseActivityStartBreak]; 218 | 219 | } else { 220 | // complete task if this is last pomo 221 | [self completeActivityOnLastPomo]; 222 | } 223 | } 224 | } 225 | 226 | - (void)breakTimerFired:(id)sender 227 | { 228 | self.breakElapsed++; 229 | if (self.breakElapsed < [KTActivityManager breakDurationMinutes]*60) { 230 | // continue break 231 | [self.delegate activityManager:self activityPausedForBreak:self.breakElapsed]; 232 | } else { 233 | // end of break. stop break timer. clear state. 234 | [self invalidateTimers]; 235 | self.breakElapsed = 0; 236 | 237 | // start next pomo 238 | [self startNextPomo]; 239 | } 240 | } 241 | 242 | #pragma mark - breakTimerFired: helper methods 243 | 244 | - (void)startNextPomo 245 | { 246 | self.currentPomo++; 247 | self.activity.current_pomo_elapsed_time = @(0); 248 | [self scheduleTimerInRunLoop:self.activityTimer]; 249 | 250 | } 251 | 252 | #pragma mark - activityTimerFired: helper methods 253 | 254 | - (BOOL)activityHasMorePomo:(KTPomodoroActivityModel*)activity 255 | { 256 | return [activity.expected_pomo integerValue]-1 > self.currentPomo; 257 | } 258 | 259 | - (void)completeActivityOnLastPomo 260 | { 261 | self.activity.status = @(KTPomodoroActivityStatusCompleted); 262 | self.activity.actual_pomo = @(self.currentPomo); 263 | 264 | // save to disk 265 | [[KTCoreDataStack sharedInstance] saveContext]; 266 | 267 | // inform delegate 268 | [self.delegate activityManager:self activityDidUpdate:self.activity]; 269 | 270 | 271 | // house keeping 272 | [self resetManagerInternalState]; 273 | 274 | } 275 | 276 | - (void)pauseActivityStartBreak 277 | { 278 | [self stopActivityTimer]; 279 | [self startBreakTimer]; 280 | } 281 | 282 | #pragma mark - pauseActivityStartBreak helper method 283 | 284 | - (void)stopActivityTimer 285 | { 286 | [self.activityTimer invalidate]; 287 | _activityTimer = nil; 288 | } 289 | 290 | - (void)startBreakTimer 291 | { 292 | [self.breakTimer invalidate]; 293 | _breakTimer = nil; 294 | [self scheduleTimerInRunLoop:self.breakTimer]; 295 | } 296 | 297 | #pragma mark - completeActivityOnLastPomo and helper method 298 | 299 | - (void)resetManagerInternalState 300 | { 301 | // clear internal state 302 | _activity = nil; 303 | [self invalidateTimers]; 304 | self.currentPomo = 0; 305 | self.breakElapsed = 0; 306 | 307 | } 308 | 309 | 310 | 311 | 312 | 313 | 314 | 315 | 316 | @end 317 | -------------------------------------------------------------------------------- /KTPomodoro/Utils/KTSharedUserDefaults.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTSharedUserDefaults.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/22/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | 12 | @interface KTSharedUserDefaults : NSObject 13 | 14 | + (NSUserDefaults*)sharedUserDefaults; 15 | 16 | + (BOOL)shouldAutoDeleteCompletedActivites; 17 | 18 | + (NSUInteger)pomoDuration; 19 | 20 | + (NSUInteger)breakDuration; 21 | 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /KTPomodoro/Utils/KTSharedUserDefaults.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTSharedUserDefaults.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 1/22/15. 6 | // Copyright (c) 2015 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTSharedUserDefaults.h" 10 | 11 | // This turns storing UserDefaults storing in app container on and off. 12 | #define kKTSharedUserDefaultsShouldUseAppContainer 0 13 | 14 | 15 | static NSString *kKTSharedUserDefaultsShouldAutoDeleteCompletedActivities = @"delete_completed_activities"; 16 | static NSString *kKTSharedUserDefaultsPomoDuration = @"pomo_length"; 17 | static NSString *kKTSharedUserDefaultsBreakDuration = @"break_length"; 18 | 19 | @implementation KTSharedUserDefaults 20 | 21 | + (NSUserDefaults*)sharedUserDefaults 22 | { 23 | static NSUserDefaults *sharedDefaults; 24 | static dispatch_once_t onceToken; 25 | dispatch_once(&onceToken, ^{ 26 | #ifdef kKTSharedUserDefaultsShouldUseAppContainer 27 | sharedDefaults = [[NSUserDefaults alloc] initWithSuiteName:@"group.com.corgitoergosum.KTPomodoro"]; 28 | #else 29 | sharedDefaults = [NSUserDefaults standardUserDefaults]; 30 | #endif 31 | }); 32 | return sharedDefaults; 33 | } 34 | 35 | + (NSUInteger)pomoDuration 36 | { 37 | return ([[KTSharedUserDefaults sharedUserDefaults] integerForKey:kKTSharedUserDefaultsPomoDuration]>0?[[KTSharedUserDefaults sharedUserDefaults] integerForKey:kKTSharedUserDefaultsPomoDuration]:25); 38 | 39 | } 40 | 41 | + (NSUInteger)breakDuration 42 | { 43 | return ([[KTSharedUserDefaults sharedUserDefaults] integerForKey:kKTSharedUserDefaultsBreakDuration]>0?[[KTSharedUserDefaults sharedUserDefaults] integerForKey:kKTSharedUserDefaultsBreakDuration]:5); 44 | } 45 | 46 | 47 | + (BOOL)shouldAutoDeleteCompletedActivites 48 | { 49 | return ([[KTSharedUserDefaults sharedUserDefaults] boolForKey:kKTSharedUserDefaultsShouldAutoDeleteCompletedActivities]?[[KTSharedUserDefaults sharedUserDefaults] boolForKey:kKTSharedUserDefaultsShouldAutoDeleteCompletedActivities]:YES); 50 | } 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /KTPomodoro/View Controller/KTPomodoroTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTPomodoroTableViewCell.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTPomodoroTableViewCell : UITableViewCell 12 | 13 | @property (weak, nonatomic) IBOutlet UILabel *taskNameLabel; 14 | @property (weak, nonatomic) IBOutlet UILabel *descLabel; 15 | @property (weak, nonatomic) IBOutlet UILabel *statusLabel; 16 | @property (weak, nonatomic) IBOutlet UILabel *timeLabel; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /KTPomodoro/View Controller/KTPomodoroTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTPomodoroTableViewCell.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTPomodoroTableViewCell.h" 10 | 11 | @implementation KTPomodoroTableViewCell 12 | 13 | - (void)awakeFromNib { 14 | 15 | 16 | } 17 | 18 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 19 | [super setSelected:selected animated:animated]; 20 | 21 | // Configure the view for the selected state 22 | 23 | } 24 | 25 | @end 26 | -------------------------------------------------------------------------------- /KTPomodoro/View Controller/KTPomodoroTableViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KTPomodoroTableViewController.h 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KTPomodoroTableViewController : UITableViewController 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /KTPomodoro/View Controller/KTPomodoroTableViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTPomodoroTableViewController.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import "KTPomodoroTableViewController.h" 10 | #import "KTCoreDataStack.h" 11 | #import "KTPomodoroTableViewCell.h" 12 | #import "KTPomodoroActivityModel.h" 13 | 14 | static NSString *kKTPomodoroTableRow = @"kKTPomodoroTableRow"; 15 | static CGFloat kKTPomodoroTableRowHeight = 110.0f; 16 | 17 | 18 | @interface KTPomodoroTableViewController () 19 | 20 | //@property (nonatomic) KTActiveActivityTimer *activeTaskTimer; 21 | @property (nonatomic) NSInteger activeTimerRowIndex; 22 | 23 | @end 24 | 25 | @implementation KTPomodoroTableViewController 26 | 27 | - (void)viewDidLoad { 28 | [super viewDidLoad]; 29 | [self.tableView registerNib:[UINib nibWithNibName:@"KTPomodoroTableViewCell" bundle:nil] forCellReuseIdentifier:kKTPomodoroTableRow]; 30 | 31 | self.title = @"Pomodoro Tasks"; 32 | 33 | self.activeTimerRowIndex = -1; 34 | // self.activeTaskTimer = [KTActiveActivityTimer sharedInstance]; 35 | // self.activeTaskTimer.delegate = self; 36 | 37 | } 38 | 39 | - (void)didReceiveMemoryWarning { 40 | [super didReceiveMemoryWarning]; 41 | // Dispose of any resources that can be recreated. 42 | } 43 | 44 | - (void)dealloc 45 | { 46 | // [self.activeTaskTimer stopTimer]; 47 | } 48 | 49 | #pragma mark - UITableViewController methods 50 | 51 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 52 | return [[KTCoreDataStack sharedInstance].allTasks count]; 53 | } 54 | 55 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 56 | KTPomodoroTableViewCell *cell = (KTPomodoroTableViewCell*)[tableView dequeueReusableCellWithIdentifier:kKTPomodoroTableRow forIndexPath:indexPath]; 57 | if (!cell) { 58 | cell = [[NSBundle mainBundle] loadNibNamed:@"KTPomodoroTableViewCell" owner:nil options:nil][0]; 59 | } 60 | 61 | KTPomodoroActivityModel *task = [KTCoreDataStack sharedInstance].allTasks[indexPath.row]; 62 | cell.taskNameLabel.text = task.name; 63 | cell.descLabel.text = task.desc; 64 | cell.statusLabel.text = [task.status stringValue]; 65 | 66 | if (indexPath.row == self.activeTimerRowIndex) { 67 | cell.backgroundColor = [UIColor colorWithRed:235.0f/255.0f green:231.0f/255.0f blue:231.0f/255.0f alpha:1.0]; 68 | 69 | } else { 70 | cell.backgroundColor = [UIColor clearColor]; 71 | } 72 | 73 | return cell; 74 | } 75 | 76 | - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 77 | { 78 | return kKTPomodoroTableRowHeight; 79 | } 80 | 81 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 82 | { 83 | KTPomodoroTableViewCell *cell = (KTPomodoroTableViewCell*)[self.tableView cellForRowAtIndexPath:indexPath]; 84 | [cell setSelected:NO animated:YES]; 85 | [self.tableView reloadData]; 86 | 87 | } 88 | 89 | @end 90 | -------------------------------------------------------------------------------- /KTPomodoro/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // KTPomodoro 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "KTAppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([KTAppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /KTPomodoroTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.corgitoergosum.$(PRODUCT_NAME:rfc1034identifier) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleSignature 20 | ???? 21 | CFBundleVersion 22 | 1 23 | 24 | 25 | -------------------------------------------------------------------------------- /KTPomodoroTests/KTPomodoroTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // KTPomodoroTests.m 3 | // KTPomodoroTests 4 | // 5 | // Created by Kenny Tang on 12/31/14. 6 | // Copyright (c) 2014 Kenny Tang. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface KTPomodoroTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation KTPomodoroTests 17 | 18 | - (void)setUp { 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 | // Put teardown code here. This method is called after the invocation of each test method in the class. 25 | [super tearDown]; 26 | } 27 | 28 | - (void)testExample { 29 | // This is an example of a functional test case. 30 | XCTAssert(YES, @"Pass"); 31 | } 32 | 33 | - (void)testPerformanceExample { 34 | // This is an example of a performance test case. 35 | [self measureBlock:^{ 36 | // Put the code you want to measure the time of here. 37 | }]; 38 | } 39 | 40 | @end 41 | -------------------------------------------------------------------------------- /Mockup/KTPomodoro - app.sketch: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kenshin03/KTPomodoro/18d66de5d70cbd32f1f23d152d0252bb24e342b7/Mockup/KTPomodoro - app.sketch -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | #KTPomodoro 2 | 3 | **KTPomodoro** is a miniscule Pomodoro Timer app designed for the  Watch, written in Objective-C. It has been made obsolete by the Swift version of the same project called [Cherry](https://github.com/kenshin03/Cherry). Please head over there for latest updates. 4 | 5 | 6 | --------------------------------------------------------------------------------