├── .gitignore ├── CONTRIBUTING.md ├── Frameworks ├── FBSDKCoreKit.framework │ ├── FBSDKCoreKit │ ├── Headers │ │ ├── FBSDKAccessToken.h │ │ ├── FBSDKAppEvents.h │ │ ├── FBSDKAppLinkResolver.h │ │ ├── FBSDKAppLinkUtility.h │ │ ├── FBSDKApplicationDelegate.h │ │ ├── FBSDKButton.h │ │ ├── FBSDKConstants.h │ │ ├── FBSDKCopying.h │ │ ├── FBSDKCoreKit.h │ │ ├── FBSDKGraphErrorRecoveryProcessor.h │ │ ├── FBSDKGraphRequest.h │ │ ├── FBSDKGraphRequestConnection.h │ │ ├── FBSDKGraphRequestDataAttachment.h │ │ ├── FBSDKMacros.h │ │ ├── FBSDKMutableCopying.h │ │ ├── FBSDKProfile.h │ │ ├── FBSDKProfilePictureView.h │ │ ├── FBSDKSettings.h │ │ ├── FBSDKTestUsersManager.h │ │ └── FBSDKUtility.h │ ├── Info.plist │ └── Modules │ │ └── module.modulemap ├── FBSDKLoginKit.framework │ ├── FBSDKLoginKit │ ├── Headers │ │ ├── FBSDKLoginButton.h │ │ ├── FBSDKLoginConstants.h │ │ ├── FBSDKLoginKit.h │ │ ├── FBSDKLoginManager.h │ │ ├── FBSDKLoginManagerLoginResult.h │ │ ├── FBSDKLoginTooltipView.h │ │ └── FBSDKTooltipView.h │ ├── Info.plist │ └── Modules │ │ └── module.modulemap └── README.md ├── README.md ├── ToDoLite.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── ToDoLite ├── AppDelegate.h ├── AppDelegate.m ├── Base.lproj │ ├── LaunchScreen.xib │ └── Main.storyboard ├── DetailViewController.h ├── DetailViewController.m ├── ImageViewController.h ├── ImageViewController.m ├── Images.xcassets │ ├── AppIcon.appiconset │ │ ├── Contents.json │ │ ├── Icon-29.png │ │ ├── Icon-29@2x.png │ │ ├── Icon-29@3x.png │ │ ├── Icon-57.png │ │ ├── Icon-57@2x.png │ │ ├── Icon-60@2x.png │ │ ├── Icon-60@3x.png │ │ ├── Icon-72.png │ │ ├── Icon-72@2x.png │ │ ├── Icon-76.png │ │ ├── Icon-76@2x.png │ │ ├── iPad-Settings-29.png │ │ ├── iPad-Settings-29@2x.png │ │ ├── iPad-Spotlight-40@2x-1.png │ │ ├── iPad-Spotlight-40@2x.png │ │ ├── iPad-Spotlight-50.png │ │ ├── iPad-Spotlight-50@2x.png │ │ ├── iPhone-Spotlight-40@2x.png │ │ └── iPhone-Spotlight-40@3x.png │ ├── Camera-Light.imageset │ │ ├── Camera-Light@2x.png │ │ └── Contents.json │ ├── Camera.imageset │ │ ├── Camera@2x.png │ │ └── Contents.json │ ├── LaunchImage.launchimage │ │ ├── Contents.json │ │ ├── iPad-Landscape.png │ │ ├── iPad-Landscape@2x.png │ │ ├── iPad-Portrait.png │ │ ├── iPad-Portrait@2x.png │ │ ├── iPhone-Portrait@2x.png │ │ └── iPhone-Retina@2x.png │ ├── Logo.imageset │ │ ├── AppIcon-Original.png │ │ └── Contents.json │ └── logo.imageset │ │ └── Contents.json ├── Info.plist ├── List.h ├── List.m ├── LoginViewController.h ├── LoginViewController.m ├── MasterViewController.h ├── MasterViewController.m ├── NSString+Additions.h ├── NSString+Additions.m ├── Profile.h ├── Profile.m ├── RoundedButton.h ├── RoundedButton.m ├── ShareViewController.h ├── ShareViewController.m ├── Task.h ├── Task.m ├── TaskTableViewCell.h ├── TaskTableViewCell.m ├── Titled.h ├── Titled.m └── main.m ├── ToDoLiteTests ├── Info.plist └── ToDoLiteTests.m └── sync-gateway-config.json /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.swp 3 | *.pbxuser 4 | *.perspectivev3 5 | *.mode1v3 6 | xcuserdata/ 7 | build 8 | DerivedData 9 | CouchbaseLite.framework 10 | *.xccheckout 11 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | We hate bugs, but we love bug reports! And we're grateful to our developers who exercise Couchbase Lite and the Couchbase Sync Gateway in new and unexpected ways and help us work out the kinks. 2 | 3 | We also want to hear about your ideas for new features and improvements. You can file those in the issue trackers too. 4 | 5 | And while we welcome questions, **we prefer to answer questions on our [mailing list](https://groups.google.com/forum/?fromgroups#!forum/mobile-couchbase)** rather than in Github issues. 6 | 7 | # 1. Is This A Duplicate? 8 | 9 | It's great if you can scan the open issues to see if your problem/idea has been reported already. If so, feel free to add any new details or just a note that you hit this too. But if you're in a hurry, go ahead and skip this step -- we'd rather get duplicate reports than miss an issue! 10 | 11 | # 2. Describe The Bug 12 | 13 | ## Version 14 | 15 | Please indicate **what version of the software** you're using. If you compiled it yourself from source, it helps if you give the Git commit ID, or at least the branch name and date ("I last pulled from master on 6/30.") 16 | 17 | If the bug involves replication, also indicate what software and version is on the other end of the line, i.e. "Couchbase Lite Android 1.0" or "Sync Gateway 1.0" or "Sync Gateway commit f3d3229c" or "CouchDB 1.6". 18 | 19 | ## Include Steps To Reproduce 20 | 21 | The most **important information** to provide with a bug report is a clear set of steps to reproduce the problem. Include as much information as possible that you think may be related to the bug. An example would be: 22 | 23 | * Install & run Sync Gateway 1.0.3 on Mac running OS X 10.10.1 24 | * Install app on iPhone 6 running iOS 8.1.1 25 | * Login with Facebook 26 | * Turn off WiFi 27 | * Add a new document 28 | * Turn on WiFi 29 | * Saw no new documents on Sync Gateway (expected: there should have been some documents) 30 | 31 | ## Include Actual vs. Expected 32 | 33 | As mentioned above, the last thing in your steps to reproduce is the "actual vs expected" behavior. The reason this is important is because you may have misunderstood what is supposed to happen. If you give a clear description of what actually happened as well as what you were expecting to happen, it will make the bug a lot easier to figure out. 34 | 35 | ## General Formatting 36 | 37 | Please **format source code or program output (including logs or backtraces) as code**. This makes it easier to read and prevents Github from interpreting any of it as Markdown formatting or bug numbers. To do this, put a line of just three back-quotes ("```") before and after it. (For inline code snippets, just put a single back-quote before and after.) 38 | 39 | **If you need to post a block of code/output that is longer than 1/2 a page, please don't paste it into the bug report** -- it's annoying to scroll past. Instead, create a [gist](https://gist.github.com) (or something similar) and just post a link to it. 40 | 41 | ## Crashes / Exceptions 42 | 43 | If the bug causes a crash or an uncaught exception, include a crash log or backtrace. **Please don't add this as a screenshot of the IDE** if you have any alternative. (In Xcode, use the `bt` command in the debugger console to dump a backtrace that you can copy.) 44 | 45 | If the log/backtrace is long, don't paste it in directly (see the previous section.) 46 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/FBSDKCoreKit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/Frameworks/FBSDKCoreKit.framework/FBSDKCoreKit -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKAccessToken.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | #import 23 | #import 24 | 25 | /*! 26 | @abstract Notification indicating that the `currentAccessToken` has changed. 27 | @discussion the userInfo dictionary of the notification will contain keys 28 | `FBSDKAccessTokenChangeOldKey` and 29 | `FBSDKAccessTokenChangeNewKey`. 30 | */ 31 | FBSDK_EXTERN NSString *const FBSDKAccessTokenDidChangeNotification; 32 | 33 | /*! 34 | @abstract A key in the notification's userInfo that will be set 35 | if and only if the user ID changed between the old and new tokens. 36 | @discussion Token refreshes can occur automatically with the SDK 37 | which do not change the user. If you're only interested in user 38 | changes (such as logging out), you should check for the existence 39 | of this key. The value is a NSNumber with a boolValue. 40 | 41 | On a fresh start of the app where the SDK reads in the cached value 42 | of an access token, this key will also exist since the access token 43 | is moving from a null state (no user) to a non-null state (user). 44 | */ 45 | FBSDK_EXTERN NSString *const FBSDKAccessTokenDidChangeUserID; 46 | 47 | /* 48 | @abstract key in notification's userInfo object for getting the old token. 49 | @discussion If there was no old token, the key will not be present. 50 | */ 51 | FBSDK_EXTERN NSString *const FBSDKAccessTokenChangeOldKey; 52 | 53 | /* 54 | @abstract key in notification's userInfo object for getting the new token. 55 | @discussion If there is no new token, the key will not be present. 56 | */ 57 | FBSDK_EXTERN NSString *const FBSDKAccessTokenChangeNewKey; 58 | 59 | 60 | /*! 61 | @class FBSDKAccessToken 62 | @abstract Represents an immutable access token for using Facebook services. 63 | */ 64 | @interface FBSDKAccessToken : NSObject 65 | 66 | /*! 67 | @abstract Returns the app ID. 68 | */ 69 | @property (readonly, copy, nonatomic) NSString *appID; 70 | 71 | /*! 72 | @abstract Returns the known declined permissions. 73 | */ 74 | @property (readonly, copy, nonatomic) NSSet *declinedPermissions; 75 | 76 | /*! 77 | @abstract Returns the expiration date. 78 | */ 79 | @property (readonly, copy, nonatomic) NSDate *expirationDate; 80 | 81 | /*! 82 | @abstract Returns the known granted permissions. 83 | */ 84 | @property (readonly, copy, nonatomic) NSSet *permissions; 85 | 86 | /*! 87 | @abstract Returns the date the token was last refreshed. 88 | */ 89 | @property (readonly, copy, nonatomic) NSDate *refreshDate; 90 | 91 | /*! 92 | @abstract Returns the opaque token string. 93 | */ 94 | @property (readonly, copy, nonatomic) NSString *tokenString; 95 | 96 | /*! 97 | @abstract Returns the user ID. 98 | */ 99 | @property (readonly, copy, nonatomic) NSString *userID; 100 | 101 | - (instancetype)init NS_UNAVAILABLE; 102 | + (instancetype)new NS_UNAVAILABLE; 103 | 104 | /*! 105 | @abstract Initializes a new instance. 106 | @param tokenString the opaque token string. 107 | @param permissions the granted permissions. Note this is converted to NSSet and is only 108 | an NSArray for the convenience of literal syntax. 109 | @param declinedPermissions the declined permissions. Note this is converted to NSSet and is only 110 | an NSArray for the convenience of literal syntax. 111 | @param appID the app ID. 112 | @param userID the user ID. 113 | @param expirationDate the optional expiration date (defaults to distantFuture). 114 | @param refreshDate the optional date the token was last refreshed (defaults to today). 115 | @discussion This initializer should only be used for advanced apps that 116 | manage tokens explicitly. Typical login flows only need to use `FBSDKLoginManager` 117 | along with `+currentAccessToken`. 118 | */ 119 | - (instancetype)initWithTokenString:(NSString *)tokenString 120 | permissions:(NSArray *)permissions 121 | declinedPermissions:(NSArray *)declinedPermissions 122 | appID:(NSString *)appID 123 | userID:(NSString *)userID 124 | expirationDate:(NSDate *)expirationDate 125 | refreshDate:(NSDate *)refreshDate 126 | NS_DESIGNATED_INITIALIZER; 127 | 128 | /*! 129 | @abstract Convenience getter to determine if a permission has been granted 130 | @param permission The permission to check. 131 | */ 132 | - (BOOL)hasGranted:(NSString *)permission; 133 | 134 | /*! 135 | @abstract Compares the receiver to another FBSDKAccessToken 136 | @param token The other token 137 | @return YES if the receiver's values are equal to the other token's values; otherwise NO 138 | */ 139 | - (BOOL)isEqualToAccessToken:(FBSDKAccessToken *)token; 140 | 141 | /*! 142 | @abstract Returns the "global" access token that represents the currently logged in user. 143 | @discussion The `currentAccessToken` is a convenient representation of the token of the 144 | current user and is used by other SDK components (like `FBSDKLoginManager`). 145 | */ 146 | + (FBSDKAccessToken *)currentAccessToken; 147 | 148 | /*! 149 | @abstract Sets the "global" access token that represents the currently logged in user. 150 | @param token The access token to set. 151 | @discussion This will broadcast a notification and save the token to the app keychain. 152 | */ 153 | + (void)setCurrentAccessToken:(FBSDKAccessToken *)token; 154 | 155 | /*! 156 | @abstract Refresh the current access token's permission state and extend the token's expiration date, 157 | if possible. 158 | @param completionHandler an optional callback handler that can surface any errors related to permission refreshing. 159 | @discussion On a successful refresh, the currentAccessToken will be updated so you typically only need to 160 | observe the `FBSDKAccessTokenDidChangeNotification` notification. 161 | 162 | If a token is already expired, it cannot be refreshed. 163 | */ 164 | + (void)refreshCurrentAccessToken:(FBSDKGraphRequestHandler)completionHandler; 165 | 166 | @end 167 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKAppLinkResolver.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | @class BFTask; 22 | 23 | // Check if Bolts.framework is available for import 24 | #if __has_include() 25 | // Import it if it's available 26 | # import 27 | #else 28 | // Otherwise - redeclare BFAppLinkResolving protocol to resolve the problem of missing symbols 29 | // Please note: Bolts.framework is still required for AppLink resolving to work, 30 | // but this allows FBSDKCoreKit to weakly link Bolts.framework as well as this enables clang modulemaps to work. 31 | 32 | /*! 33 | Implement this protocol to provide an alternate strategy for resolving 34 | App Links that may include pre-fetching, caching, or querying for App Link 35 | data from an index provided by a service provider. 36 | */ 37 | @protocol BFAppLinkResolving 38 | 39 | /*! 40 | Asynchronously resolves App Link data for a given URL. 41 | 42 | @param url The URL to resolve into an App Link. 43 | @returns A BFTask that will return a BFAppLink for the given URL. 44 | */ 45 | - (BFTask *)appLinkFromURLInBackground:(NSURL *)url; 46 | 47 | @end 48 | 49 | #endif 50 | 51 | /*! 52 | @class FBSDKAppLinkResolver 53 | 54 | @abstract 55 | Provides an implementation of the BFAppLinkResolving protocol that uses the Facebook App Link 56 | Index API to resolve App Links given a URL. It also provides an additional helper method that can resolve 57 | multiple App Links in a single call. 58 | 59 | @discussion 60 | Usage of this type requires a client token. See `[FBSDKSettings setClientToken:]` and linking 61 | Bolts.framework 62 | */ 63 | @interface FBSDKAppLinkResolver : NSObject 64 | 65 | /*! 66 | @abstract Asynchronously resolves App Link data for multiple URLs. 67 | 68 | @param urls An array of NSURLs to resolve into App Links. 69 | @returns A BFTask that will return dictionary mapping input NSURLs to their 70 | corresponding BFAppLink. 71 | 72 | @discussion 73 | You should set the client token before making this call. See `[FBSDKSettings setClientToken:]` 74 | */ 75 | - (BFTask *)appLinksFromURLsInBackground:(NSArray *)urls; 76 | 77 | /*! 78 | @abstract Allocates and initializes a new instance of FBSDKAppLinkResolver. 79 | */ 80 | + (instancetype)resolver; 81 | 82 | @end 83 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKAppLinkUtility.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | /*! 22 | @abstract Describes the callback for fetchDeferredAppLink. 23 | @param url the url representing the deferred App Link 24 | @param error the error during the request, if any 25 | 26 | @discussion The url may also have a fb_click_time_utc query parameter that 27 | represents when the click occurred that caused the deferred App Link to be created. 28 | */ 29 | typedef void (^FBSDKDeferredAppLinkHandler)(NSURL *url, NSError *error); 30 | 31 | /*! 32 | @abstract Class containing App Links related utility methods. 33 | */ 34 | @interface FBSDKAppLinkUtility : NSObject 35 | 36 | /*! 37 | @abstract 38 | Call this method from the main thread to fetch deferred applink data if you use Mobile App 39 | Engagement Ads (https://developers.facebook.com/docs/ads-for-apps/mobile-app-ads-engagement). 40 | This may require a network round trip. If successful, the handler is invoked with the link 41 | data (this will only return a valid URL once, and future calls will result in a nil URL 42 | value in the callback). 43 | 44 | @param handler the handler to be invoked if there is deferred App Link data 45 | 46 | @discussion The handler may contain an NSError instance to capture any errors. In the 47 | common case where there simply was no app link data, the NSError instance will be nil. 48 | 49 | This method should only be called from a location that occurs after any launching URL has 50 | been processed (e.g., you should call this method from your application delegate's 51 | applicationDidBecomeActive:). 52 | */ 53 | + (void)fetchDeferredAppLink:(FBSDKDeferredAppLinkHandler)handler; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKApplicationDelegate.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | /*! 22 | @class FBSDKApplicationDelegate 23 | 24 | @abstract 25 | The FBSDKApplicationDelegate is designed to post process the results from Facebook Login 26 | or Facebook Dialogs (or any action that requires switching over to the native Facebook 27 | app or Safari). 28 | 29 | @discussion 30 | The methods in this class are designed to mirror those in UIApplicationDelegate, and you 31 | should call them in the respective methods in your AppDelegate implementation. 32 | */ 33 | @interface FBSDKApplicationDelegate : NSObject 34 | 35 | /*! 36 | @abstract Gets the singleton instance. 37 | */ 38 | + (instancetype)sharedInstance; 39 | 40 | /*! 41 | @abstract 42 | Call this method from the [UIApplicationDelegate application:openURL:sourceApplication:annotation:] method 43 | of the AppDelegate for your app. It should be invoked for the proper processing of responses during interaction 44 | with the native Facebook app or Safari as part of SSO authorization flow or Facebook dialogs. 45 | 46 | @param application The application as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. 47 | 48 | @param url The URL as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. 49 | 50 | @param sourceApplication The sourceApplication as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. 51 | 52 | @param annotation The annotation as passed to [UIApplicationDelegate application:openURL:sourceApplication:annotation:]. 53 | 54 | @return YES if the url was intended for the Facebook SDK, NO if not. 55 | */ 56 | - (BOOL)application:(UIApplication *)application 57 | openURL:(NSURL *)url 58 | sourceApplication:(NSString *)sourceApplication 59 | annotation:(id)annotation; 60 | 61 | /*! 62 | @abstract 63 | Call this method from the [UIApplicationDelegate application:didFinishLaunchingWithOptions:] method 64 | of the AppDelegate for your app. It should be invoked for the proper use of the Facebook SDK. 65 | 66 | @param application The application as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. 67 | 68 | @param launchOptions The launchOptions as passed to [UIApplicationDelegate application:didFinishLaunchingWithOptions:]. 69 | 70 | @return YES if the url was intended for the Facebook SDK, NO if not. 71 | */ 72 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; 73 | 74 | @end 75 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKButton.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | /*! 22 | @abstract A base class for common SDK buttons. 23 | */ 24 | @interface FBSDKButton : UIButton 25 | 26 | @end 27 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKConstants.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | 23 | /*! 24 | @abstract The error domain for all errors from FBSDKCoreKit. 25 | @discussion Error codes from the SDK in the range 0-99 are reserved for this domain. 26 | */ 27 | FBSDK_EXTERN NSString *const FBSDKErrorDomain; 28 | 29 | /*! 30 | @typedef NS_ENUM(NSInteger, FBSDKErrorCode) 31 | @abstract Error codes for FBSDKErrorDomain. 32 | */ 33 | typedef NS_ENUM(NSInteger, FBSDKErrorCode) 34 | { 35 | /*! 36 | @abstract Reserved. 37 | */ 38 | FBSDKReservedErrorCode = 0, 39 | 40 | /*! 41 | @abstract The error code for errors from invalid encryption on incoming encryption URLs. 42 | */ 43 | FBSDKEncryptionErrorCode, 44 | 45 | /*! 46 | @abstract The error code for errors from invalid arguments to SDK methods. 47 | */ 48 | FBSDKInvalidArgumentErrorCode, 49 | 50 | /*! 51 | @abstract The error code for unknown errors. 52 | */ 53 | FBSDKUnknownErrorCode, 54 | 55 | /*! 56 | @abstract A request failed due to a network error. Use NSUnderlyingErrorKey to retrieve 57 | the error object from the NSURLConnection for more information. 58 | */ 59 | FBSDKNetworkErrorCode, 60 | 61 | /*! 62 | @abstract The error code for errors encounted during an App Events flush. 63 | */ 64 | FBSDKAppEventsFlushErrorCode, 65 | 66 | /*! 67 | @abstract An endpoint that returns a binary response was used with FBSDKGraphRequestConnection. 68 | @discussion Endpoints that return image/jpg, etc. should be accessed using NSURLRequest 69 | */ 70 | FBSDKGraphRequestNonTextMimeTypeReturnedErrorCode, 71 | 72 | /*! 73 | @abstract The operation failed because the server returned an unexpected response. 74 | @discussion You can get this error if you are not using the most recent SDK, or you are accessing a version of the 75 | Graph API incompatible with the current SDK. 76 | */ 77 | FBSDKGraphRequestProtocolMismatchErrorCode, 78 | 79 | /*! 80 | @abstract The Graph API returned an error. 81 | @discussion See below for useful userInfo keys (beginning with FBSDKGraphRequestError*) 82 | */ 83 | FBSDKGraphRequestGraphAPIErrorCode, 84 | 85 | /*! 86 | @abstract The specified dialog configuration is not available. 87 | @discussion This error may signify that the configuration for the dialogs has not yet been downloaded from the server 88 | or that the dialog is unavailable. Subsequent attempts to use the dialog may succeed as the configuration is loaded. 89 | */ 90 | FBSDKDialogUnavailableErrorCode, 91 | 92 | /*! 93 | @abstract Indicates an operation failed because a required access token was not found. 94 | */ 95 | FBSDKAccessTokenRequiredErrorCode, 96 | 97 | /*! 98 | @abstract Indicates an app switch (typically for a dialog) failed because the destination app is out of date. 99 | */ 100 | FBSDKAppVersionUnsupportedErrorCode, 101 | 102 | /*! 103 | @abstract Indicates an app switch to the browser (typically for a dialog) failed. 104 | */ 105 | FBSDKBrowswerUnavailableErrorCode, 106 | }; 107 | 108 | /*! 109 | @typedef NS_ENUM(NSUInteger, FBSDKGraphRequestErrorCategory) 110 | @abstract Describes the category of Facebook error. See `FBSDKGraphRequestErrorCategoryKey`. 111 | */ 112 | typedef NS_ENUM(NSUInteger, FBSDKGraphRequestErrorCategory) 113 | { 114 | /*! The default error category that is not known to be recoverable. Check `FBSDKLocalizedErrorDescriptionKey` for a user facing message. */ 115 | FBSDKGraphRequestErrorCategoryOther = 0, 116 | /*! Indicates the error is temporary (such as server throttling). While a recoveryAttempter will be provided with the error instance, the attempt is guaranteed to succeed so you can simply retry the operation if you do not want to present an alert. */ 117 | FBSDKGraphRequestErrorCategoryTransient = 1, 118 | /*! Indicates the error can be recovered (such as requiring a login). A recoveryAttempter will be provided with the error instance that can take UI action. */ 119 | FBSDKGraphRequestErrorCategoryRecoverable = 2 120 | }; 121 | 122 | /* 123 | @methodgroup error userInfo keys 124 | */ 125 | 126 | /*! 127 | @abstract The userInfo key for the invalid collection for errors with FBSDKInvalidArgumentErrorCode. 128 | @discussion If the invalid argument is a collection, the collection can be found with this key and the individual 129 | invalid item can be found with FBSDKErrorArgumentValueKey. 130 | */ 131 | FBSDK_EXTERN NSString *const FBSDKErrorArgumentCollectionKey; 132 | 133 | /*! 134 | @abstract The userInfo key for the invalid argument name for errors with FBSDKInvalidArgumentErrorCode. 135 | */ 136 | FBSDK_EXTERN NSString *const FBSDKErrorArgumentNameKey; 137 | 138 | /*! 139 | @abstract The userInfo key for the invalid argument value for errors with FBSDKInvalidArgumentErrorCode. 140 | */ 141 | FBSDK_EXTERN NSString *const FBSDKErrorArgumentValueKey; 142 | 143 | /*! 144 | @abstract The userInfo key for the message for developers in NSErrors that originate from the SDK. 145 | @discussion The developer message will not be localized and is not intended to be presented within the app. 146 | */ 147 | FBSDK_EXTERN NSString *const FBSDKErrorDeveloperMessageKey; 148 | 149 | /*! 150 | @abstract The userInfo key describing a localized description that can be presented to the user. 151 | */ 152 | FBSDK_EXTERN NSString *const FBSDKErrorLocalizedDescriptionKey; 153 | 154 | /*! 155 | @abstract The userInfo key describing a localized title that can be presented to the user, used with `FBSDKLocalizedErrorDescriptionKey`. 156 | */ 157 | FBSDK_EXTERN NSString *const FBSDKErrorLocalizedTitleKey; 158 | 159 | /* 160 | @methodgroup FBSDKGraphRequest error userInfo keys 161 | */ 162 | 163 | /*! 164 | @abstract The userInfo key describing the error category, for error recovery purposes. 165 | @discussion See `FBSDKGraphErrorRecoveryProcessor` and `[FBSDKGraphRequest disableErrorRecovery]`. 166 | */ 167 | FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorCategoryKey; 168 | 169 | /* 170 | @abstract The userInfo key for the Graph API error code. 171 | */ 172 | FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorGraphErrorCode; 173 | 174 | /* 175 | @abstract The userInfo key for the Graph API error subcode. 176 | */ 177 | FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorGraphErrorSubcode; 178 | 179 | /* 180 | @abstract The userInfo key for the HTTP status code. 181 | */ 182 | FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorHTTPStatusCodeKey; 183 | 184 | /* 185 | @abstract The userInfo key for the raw JSON response. 186 | */ 187 | FBSDK_EXTERN NSString *const FBSDKGraphRequestErrorParsedJSONResponseKey; 188 | 189 | /*! 190 | @abstract a formal protocol very similar to the informal protocol NSErrorRecoveryAttempting 191 | */ 192 | @protocol FBSDKErrorRecoveryAttempting 193 | 194 | /*! 195 | @abstract attempt the recovery 196 | @param error the error 197 | @param recoveryOptionIndex the selected option index 198 | @param delegate the delegate 199 | @param didRecoverSelector the callback selector, see discussion. 200 | @param contextInfo context info to pass back to callback selector, see discussion. 201 | @discussion 202 | Given that an error alert has been presented document-modally to the user, and the user has chosen one of the error's recovery options, attempt recovery from the error, and send the selected message to the specified delegate. The option index is an index into the error's array of localized recovery options. The method selected by didRecoverSelector must have the same signature as: 203 | 204 | - (void)didPresentErrorWithRecovery:(BOOL)didRecover contextInfo:(void *)contextInfo; 205 | 206 | The value passed for didRecover must be YES if error recovery was completely successful, NO otherwise. 207 | */ 208 | - (void)attemptRecoveryFromError:(NSError *)error optionIndex:(NSUInteger)recoveryOptionIndex delegate:(id)delegate didRecoverSelector:(SEL)didRecoverSelector contextInfo:(void *)contextInfo; 209 | 210 | @end 211 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKCopying.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | /*! 22 | @abstract Extension protocol for NSCopying that adds the copy method, which is implemented on NSObject. 23 | @discussion NSObject implicitly conforms to this protocol. 24 | */ 25 | @protocol FBSDKCopying 26 | 27 | /*! 28 | @abstract Implemented by NSObject as a convenience to copyWithZone:. 29 | @return A copy of the receiver. 30 | */ 31 | - (id)copy; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKCoreKit.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | #import 23 | #import 24 | #import 25 | #import 26 | #import 27 | #import 28 | #import 29 | #import 30 | #import 31 | #import 32 | #import 33 | #import 34 | 35 | #if !TARGET_OS_TV 36 | #import 37 | #import 38 | #import 39 | #import 40 | #import 41 | #import 42 | #endif 43 | 44 | #define FBSDK_VERSION_STRING @"4.9.1" 45 | #define FBSDK_TARGET_PLATFORM_VERSION @"v2.5" 46 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKGraphErrorRecoveryProcessor.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import "FBSDKConstants.h" 22 | 23 | @class FBSDKGraphErrorRecoveryProcessor; 24 | @class FBSDKGraphRequest; 25 | 26 | /*! 27 | @abstract Defines a delegate for `FBSDKGraphErrorRecoveryProcessor`. 28 | */ 29 | @protocol FBSDKGraphErrorRecoveryProcessorDelegate 30 | 31 | /*! 32 | @abstract Indicates the error recovery has been attempted. 33 | @param processor the processor instance. 34 | @param didRecover YES if the recovery was successful. 35 | @param error the error that that was attempted to be recovered from. 36 | */ 37 | - (void)processorDidAttemptRecovery:(FBSDKGraphErrorRecoveryProcessor *)processor didRecover:(BOOL)didRecover error:(NSError *)error; 38 | 39 | @optional 40 | /*! 41 | @abstract Indicates the processor is about to process the error. 42 | @param processor the processor instance. 43 | @param error the error is about to be processed. 44 | @discussion return NO if the processor should not process the error. For example, 45 | if you want to prevent alerts of localized messages but otherwise perform retries and recoveries, 46 | you could return NO for errors where userInfo[FBSDKGraphRequestErrorCategoryKey] equal to FBSDKGraphRequestErrorCategoryOther 47 | */ 48 | - (BOOL)processorWillProcessError:(FBSDKGraphErrorRecoveryProcessor *)processor error:(NSError *)error; 49 | 50 | @end 51 | 52 | /*! 53 | @abstract Defines a type that can process Facebook NSErrors with best practices. 54 | @discussion Facebook NSErrors can contain FBSDKErrorRecoveryAttempting instances to recover from errors, or 55 | localized messages to present to the user. This class will process the instances as follows: 56 | 57 | 1. If the error is temporary as indicated by FBSDKGraphRequestErrorCategoryKey, assume the recovery succeeded and 58 | notify the delegate. 59 | 2. If a FBSDKErrorRecoveryAttempting instance is available, display an alert (dispatched to main thread) 60 | with the recovery options and call the instance's [ attemptRecoveryFromError:optionIndex:...]. 61 | 3. If a FBSDKErrorRecoveryAttempting is not available, check the userInfo for FBSDKLocalizedErrorDescriptionKey 62 | and present that in an alert (dispatched to main thread). 63 | 64 | By default, FBSDKGraphRequests use this type to process errors and retry the request upon a successful 65 | recovery. 66 | 67 | Note that Facebook recovery attempters can present UI or even cause app switches (such as to login). Any such 68 | work is dispatched to the main thread (therefore your request handlers may then run on the main thread). 69 | 70 | Login recovery requires FBSDKLoginKit. Login will use FBSDKLoginBehaviorNative and will prompt the user 71 | for all permissions last granted. If any are declined on the new request, the recovery is not successful but 72 | the `[FBSDKAccessToken currentAccessToken]` might still have been updated. 73 | . 74 | */ 75 | @interface FBSDKGraphErrorRecoveryProcessor : NSObject 76 | 77 | /*! 78 | @abstract Gets the delegate. Note this is a strong reference, and is nil'ed out after recovery is complete. 79 | */ 80 | @property (nonatomic, strong, readonly) iddelegate; 81 | 82 | /*! 83 | @abstract Attempts to process the error, return YES if the error can be processed. 84 | @param error the error to process. 85 | @param request the relateed request that may be reissued. 86 | @param delegate the delegate that will be retained until recovery is complete. 87 | */ 88 | - (BOOL)processError:(NSError *)error request:(FBSDKGraphRequest *)request delegate:(id) delegate; 89 | 90 | /*! 91 | @abstract The callback for FBSDKErrorRecoveryAttempting 92 | @param didRecover if the recovery succeeded 93 | @param contextInfo unused 94 | */ 95 | - (void)didPresentErrorWithRecovery:(BOOL)didRecover contextInfo:(void *)contextInfo; 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKGraphRequest.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | 23 | @class FBSDKAccessToken; 24 | 25 | /*! 26 | @abstract Represents a request to the Facebook Graph API. 27 | 28 | @discussion `FBSDKGraphRequest` encapsulates the components of a request (the 29 | Graph API path, the parameters, error recovery behavior) and should be 30 | used in conjunction with `FBSDKGraphRequestConnection` to issue the request. 31 | 32 | Nearly all Graph APIs require an access token. Unless specified, the 33 | `[FBSDKAccessToken currentAccessToken]` is used. Therefore, most requests 34 | will require login first (see `FBSDKLoginManager` in FBSDKLoginKit.framework). 35 | 36 | A `- start` method is provided for convenience for single requests. 37 | 38 | By default, FBSDKGraphRequest will attempt to recover any errors returned from 39 | Facebook. You can disable this via `disableErrorRecovery:`. 40 | @see FBSDKGraphErrorRecoveryProcessor 41 | */ 42 | @interface FBSDKGraphRequest : NSObject 43 | 44 | /*! 45 | @abstract Initializes a new instance that use use `[FBSDKAccessToken currentAccessToken]`. 46 | @param graphPath the graph path (e.g., @"me"). 47 | @param parameters the optional parameters dictionary. 48 | */ 49 | - (instancetype)initWithGraphPath:(NSString *)graphPath 50 | parameters:(NSDictionary *)parameters; 51 | 52 | /*! 53 | @abstract Initializes a new instance that use use `[FBSDKAccessToken currentAccessToken]`. 54 | @param graphPath the graph path (e.g., @"me"). 55 | @param parameters the optional parameters dictionary. 56 | @param HTTPMethod the optional HTTP method. nil defaults to @"GET". 57 | */ 58 | - (instancetype)initWithGraphPath:(NSString *)graphPath 59 | parameters:(NSDictionary *)parameters 60 | HTTPMethod:(NSString *)HTTPMethod; 61 | 62 | /*! 63 | @abstract Initializes a new instance. 64 | @param graphPath the graph path (e.g., @"me"). 65 | @param parameters the optional parameters dictionary. 66 | @param tokenString the token string to use. Specifying nil will cause no token to be used. 67 | @param version the optional Graph API version (e.g., @"v2.0"). nil defaults to FBSDK_TARGET_PLATFORM_VERSION. 68 | @param HTTPMethod the optional HTTP method (e.g., @"POST"). nil defaults to @"GET". 69 | */ 70 | - (instancetype)initWithGraphPath:(NSString *)graphPath 71 | parameters:(NSDictionary *)parameters 72 | tokenString:(NSString *)tokenString 73 | version:(NSString *)version 74 | HTTPMethod:(NSString *)HTTPMethod 75 | NS_DESIGNATED_INITIALIZER; 76 | 77 | /*! 78 | @abstract The request parameters. 79 | */ 80 | @property (nonatomic, strong, readonly) NSMutableDictionary *parameters; 81 | 82 | /*! 83 | @abstract The access token string used by the request. 84 | */ 85 | @property (nonatomic, copy, readonly) NSString *tokenString; 86 | 87 | /*! 88 | @abstract The Graph API endpoint to use for the request, for example "me". 89 | */ 90 | @property (nonatomic, copy, readonly) NSString *graphPath; 91 | 92 | /*! 93 | @abstract The HTTPMethod to use for the request, for example "GET" or "POST". 94 | */ 95 | @property (nonatomic, copy, readonly) NSString *HTTPMethod; 96 | 97 | /*! 98 | @abstract The Graph API version to use (e.g., "v2.0") 99 | */ 100 | @property (nonatomic, copy, readonly) NSString *version; 101 | 102 | /*! 103 | @abstract If set, disables the automatic error recovery mechanism. 104 | @param disable whether to disable the automatic error recovery mechanism 105 | @discussion By default, non-batched FBSDKGraphRequest instances will automatically try to recover 106 | from errors by constructing a `FBSDKGraphErrorRecoveryProcessor` instance that 107 | re-issues the request on successful recoveries. The re-issued request will call the same 108 | handler as the receiver but may occur with a different `FBSDKGraphRequestConnection` instance. 109 | 110 | This will override [FBSDKSettings setGraphErrorRecoveryDisabled:]. 111 | */ 112 | - (void)setGraphErrorRecoveryDisabled:(BOOL)disable; 113 | 114 | /*! 115 | @abstract Starts a connection to the Graph API. 116 | @param handler The handler block to call when the request completes. 117 | */ 118 | - (FBSDKGraphRequestConnection *)startWithCompletionHandler:(FBSDKGraphRequestHandler)handler; 119 | 120 | @end 121 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKGraphRequestConnection.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | 23 | @class FBSDKGraphRequest; 24 | @class FBSDKGraphRequestConnection; 25 | 26 | /*! 27 | @typedef FBSDKGraphRequestHandler 28 | 29 | @abstract 30 | A block that is passed to addRequest to register for a callback with the results of that 31 | request once the connection completes. 32 | 33 | @discussion 34 | Pass a block of this type when calling addRequest. This will be called once 35 | the request completes. The call occurs on the UI thread. 36 | 37 | @param connection The `FBSDKGraphRequestConnection` that sent the request. 38 | 39 | @param result The result of the request. This is a translation of 40 | JSON data to `NSDictionary` and `NSArray` objects. This 41 | is nil if there was an error. 42 | 43 | @param error The `NSError` representing any error that occurred. 44 | 45 | */ 46 | typedef void (^FBSDKGraphRequestHandler)(FBSDKGraphRequestConnection *connection, 47 | id result, 48 | NSError *error); 49 | 50 | /*! 51 | @protocol 52 | 53 | @abstract 54 | The `FBSDKGraphRequestConnectionDelegate` protocol defines the methods used to receive network 55 | activity progress information from a . 56 | */ 57 | @protocol FBSDKGraphRequestConnectionDelegate 58 | 59 | @optional 60 | 61 | /*! 62 | @method 63 | 64 | @abstract 65 | Tells the delegate the request connection will begin loading 66 | 67 | @discussion 68 | If the is created using one of the convenience factory methods prefixed with 69 | start, the object returned from the convenience method has already begun loading and this method 70 | will not be called when the delegate is set. 71 | 72 | @param connection The request connection that is starting a network request 73 | */ 74 | - (void)requestConnectionWillBeginLoading:(FBSDKGraphRequestConnection *)connection; 75 | 76 | /*! 77 | @method 78 | 79 | @abstract 80 | Tells the delegate the request connection finished loading 81 | 82 | @discussion 83 | If the request connection completes without a network error occuring then this method is called. 84 | Invocation of this method does not indicate success of every made, only that the 85 | request connection has no further activity. Use the error argument passed to the FBSDKGraphRequestHandler 86 | block to determine success or failure of each . 87 | 88 | This method is invoked after the completion handler for each . 89 | 90 | @param connection The request connection that successfully completed a network request 91 | */ 92 | - (void)requestConnectionDidFinishLoading:(FBSDKGraphRequestConnection *)connection; 93 | 94 | /*! 95 | @method 96 | 97 | @abstract 98 | Tells the delegate the request connection failed with an error 99 | 100 | @discussion 101 | If the request connection fails with a network error then this method is called. The `error` 102 | argument specifies why the network connection failed. The `NSError` object passed to the 103 | FBSDKGraphRequestHandler block may contain additional information. 104 | 105 | @param connection The request connection that successfully completed a network request 106 | @param error The `NSError` representing the network error that occurred, if any. May be nil 107 | in some circumstances. Consult the `NSError` for the for reliable 108 | failure information. 109 | */ 110 | - (void)requestConnection:(FBSDKGraphRequestConnection *)connection 111 | didFailWithError:(NSError *)error; 112 | 113 | /*! 114 | @method 115 | 116 | @abstract 117 | Tells the delegate how much data has been sent and is planned to send to the remote host 118 | 119 | @discussion 120 | The byte count arguments refer to the aggregated objects, not a particular . 121 | 122 | Like `NSURLConnection`, the values may change in unexpected ways if data needs to be resent. 123 | 124 | @param connection The request connection transmitting data to a remote host 125 | @param bytesWritten The number of bytes sent in the last transmission 126 | @param totalBytesWritten The total number of bytes sent to the remote host 127 | @param totalBytesExpectedToWrite The total number of bytes expected to send to the remote host 128 | */ 129 | - (void)requestConnection:(FBSDKGraphRequestConnection *)connection 130 | didSendBodyData:(NSInteger)bytesWritten 131 | totalBytesWritten:(NSInteger)totalBytesWritten 132 | totalBytesExpectedToWrite:(NSInteger)totalBytesExpectedToWrite; 133 | 134 | @end 135 | 136 | /*! 137 | @class FBSDKGraphRequestConnection 138 | 139 | @abstract 140 | The `FBSDKGraphRequestConnection` represents a single connection to Facebook to service a request. 141 | 142 | @discussion 143 | The request settings are encapsulated in a reusable object. The 144 | `FBSDKGraphRequestConnection` object encapsulates the concerns of a single communication 145 | e.g. starting a connection, canceling a connection, or batching requests. 146 | 147 | */ 148 | @interface FBSDKGraphRequestConnection : NSObject 149 | 150 | /*! 151 | @abstract 152 | The delegate object that receives updates. 153 | */ 154 | @property (nonatomic, assign) id delegate; 155 | 156 | /*! 157 | @abstract Gets or sets the timeout interval to wait for a response before giving up. 158 | */ 159 | @property (nonatomic) NSTimeInterval timeout; 160 | 161 | /*! 162 | @abstract 163 | The raw response that was returned from the server. (readonly) 164 | 165 | @discussion 166 | This property can be used to inspect HTTP headers that were returned from 167 | the server. 168 | 169 | The property is nil until the request completes. If there was a response 170 | then this property will be non-nil during the FBSDKGraphRequestHandler callback. 171 | */ 172 | @property (nonatomic, retain, readonly) NSHTTPURLResponse *URLResponse; 173 | 174 | /*! 175 | @methodgroup Class methods 176 | */ 177 | 178 | /*! 179 | @method 180 | 181 | @abstract 182 | This method sets the default timeout on all FBSDKGraphRequestConnection instances. Defaults to 60 seconds. 183 | 184 | @param defaultConnectionTimeout The timeout interval. 185 | */ 186 | + (void)setDefaultConnectionTimeout:(NSTimeInterval)defaultConnectionTimeout; 187 | 188 | /*! 189 | @methodgroup Adding requests 190 | */ 191 | 192 | /*! 193 | @method 194 | 195 | @abstract 196 | This method adds an object to this connection. 197 | 198 | @param request A request to be included in the round-trip when start is called. 199 | @param handler A handler to call back when the round-trip completes or times out. 200 | 201 | @discussion 202 | The completion handler is retained until the block is called upon the 203 | completion or cancellation of the connection. 204 | */ 205 | - (void)addRequest:(FBSDKGraphRequest *)request 206 | completionHandler:(FBSDKGraphRequestHandler)handler; 207 | 208 | /*! 209 | @method 210 | 211 | @abstract 212 | This method adds an object to this connection. 213 | 214 | @param request A request to be included in the round-trip when start is called. 215 | 216 | @param handler A handler to call back when the round-trip completes or times out. 217 | The handler will be invoked on the main thread. 218 | 219 | @param name An optional name for this request. This can be used to feed 220 | the results of one request to the input of another in the same 221 | `FBSDKGraphRequestConnection` as described in 222 | [Graph API Batch Requests]( https://developers.facebook.com/docs/reference/api/batch/ ). 223 | 224 | @discussion 225 | The completion handler is retained until the block is called upon the 226 | completion or cancellation of the connection. This request can be named 227 | to allow for using the request's response in a subsequent request. 228 | */ 229 | - (void)addRequest:(FBSDKGraphRequest *)request 230 | completionHandler:(FBSDKGraphRequestHandler)handler 231 | batchEntryName:(NSString *)name; 232 | 233 | /*! 234 | @method 235 | 236 | @abstract 237 | This method adds an object to this connection. 238 | 239 | @param request A request to be included in the round-trip when start is called. 240 | 241 | @param handler A handler to call back when the round-trip completes or times out. 242 | 243 | @param batchParameters The optional dictionary of parameters to include for this request 244 | as described in [Graph API Batch Requests]( https://developers.facebook.com/docs/reference/api/batch/ ). 245 | Examples include "depends_on", "name", or "omit_response_on_success". 246 | 247 | @discussion 248 | The completion handler is retained until the block is called upon the 249 | completion or cancellation of the connection. This request can be named 250 | to allow for using the request's response in a subsequent request. 251 | */ 252 | - (void)addRequest:(FBSDKGraphRequest *)request 253 | completionHandler:(FBSDKGraphRequestHandler)handler 254 | batchParameters:(NSDictionary *)batchParameters; 255 | 256 | /*! 257 | @methodgroup Instance methods 258 | */ 259 | 260 | /*! 261 | @method 262 | 263 | @abstract 264 | Signals that a connection should be logically terminated as the 265 | application is no longer interested in a response. 266 | 267 | @discussion 268 | Synchronously calls any handlers indicating the request was cancelled. Cancel 269 | does not guarantee that the request-related processing will cease. It 270 | does promise that all handlers will complete before the cancel returns. A call to 271 | cancel prior to a start implies a cancellation of all requests associated 272 | with the connection. 273 | */ 274 | - (void)cancel; 275 | 276 | /*! 277 | @method 278 | 279 | @abstract 280 | This method starts a connection with the server and is capable of handling all of the 281 | requests that were added to the connection. 282 | 283 | @discussion By default, a connection is scheduled on the current thread in the default mode when it is created. 284 | See `setDelegateQueue:` for other options. 285 | 286 | This method cannot be called twice for an `FBSDKGraphRequestConnection` instance. 287 | */ 288 | - (void)start; 289 | 290 | /*! 291 | @abstract Determines the operation queue that is used to call methods on the connection's delegate. 292 | @param queue The operation queue to use when calling delegate methods. 293 | @discussion By default, a connection is scheduled on the current thread in the default mode when it is created. 294 | You cannot reschedule a connection after it has started. 295 | 296 | This is very similar to `[NSURLConnection setDelegateQueue:]`. 297 | */ 298 | - (void)setDelegateQueue:(NSOperationQueue *)queue; 299 | 300 | /*! 301 | @method 302 | 303 | @abstract 304 | Overrides the default version for a batch request 305 | 306 | @discussion 307 | The SDK automatically prepends a version part, such as "v2.0" to API paths in order to simplify API versioning 308 | for applications. If you want to override the version part while using batch requests on the connection, call 309 | this method to set the version for the batch request. 310 | 311 | @param version This is a string in the form @"v2.0" which will be used for the version part of an API path 312 | */ 313 | - (void)overrideVersionPartWith:(NSString *)version; 314 | 315 | @end 316 | 317 | /*! 318 | @abstract The key in the result dictionary for requests to old versions of the Graph API 319 | whose response is not a JSON object. 320 | 321 | @discussion When a request returns a non-JSON response (such as a "true" literal), that response 322 | will be wrapped into a dictionary using this const as the key. This only applies for very few Graph API 323 | prior to v2.1. 324 | */ 325 | FBSDK_EXTERN NSString *const FBSDKNonJSONResponseProperty; 326 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKGraphRequestDataAttachment.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | /*! 22 | @abstract A container class for data attachments so that additional metadata can be provided about the attachment. 23 | */ 24 | @interface FBSDKGraphRequestDataAttachment : NSObject 25 | 26 | /*! 27 | @abstract Initializes the receiver with the attachment data and metadata. 28 | @param data The attachment data (retained, not copied) 29 | @param filename The filename for the attachment 30 | @param contentType The content type for the attachment 31 | */ 32 | - (instancetype)initWithData:(NSData *)data 33 | filename:(NSString *)filename 34 | contentType:(NSString *)contentType 35 | NS_DESIGNATED_INITIALIZER; 36 | 37 | /*! 38 | @abstract The content type for the attachment. 39 | */ 40 | @property (nonatomic, copy, readonly) NSString *contentType; 41 | 42 | /*! 43 | @abstract The attachment data. 44 | */ 45 | @property (nonatomic, strong, readonly) NSData *data; 46 | 47 | /*! 48 | @abstract The filename for the attachment. 49 | */ 50 | @property (nonatomic, copy, readonly) NSString *filename; 51 | 52 | @end 53 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKMacros.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #ifdef __cplusplus 22 | #define FBSDK_EXTERN extern "C" __attribute__((visibility ("default"))) 23 | #else 24 | #define FBSDK_EXTERN extern __attribute__((visibility ("default"))) 25 | #endif 26 | 27 | #define FBSDK_STATIC_INLINE static inline 28 | 29 | #define FBSDK_NO_DESIGNATED_INITIALIZER() \ 30 | @throw [NSException exceptionWithName:NSInvalidArgumentException \ 31 | reason:[NSString stringWithFormat:@"unrecognized selector sent to instance %p", self] \ 32 | userInfo:nil] 33 | 34 | #define FBSDK_NOT_DESIGNATED_INITIALIZER(DESIGNATED_INITIALIZER) \ 35 | @throw [NSException exceptionWithName:NSInvalidArgumentException \ 36 | reason:[NSString stringWithFormat:@"Please use the designated initializer [%p %@]", \ 37 | self, \ 38 | NSStringFromSelector(@selector(DESIGNATED_INITIALIZER))] \ 39 | userInfo:nil] 40 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKMutableCopying.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | 23 | /*! 24 | @abstract Extension protocol for NSMutableCopying that adds the mutableCopy method, which is implemented on NSObject. 25 | @discussion NSObject implicitly conforms to this protocol. 26 | */ 27 | @protocol FBSDKMutableCopying 28 | 29 | /*! 30 | @abstract Implemented by NSObject as a convenience to mutableCopyWithZone:. 31 | @return A mutable copy of the receiver. 32 | */ 33 | - (id)mutableCopy; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKProfile.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import "FBSDKMacros.h" 20 | #import "FBSDKProfilePictureView.h" 21 | 22 | /*! 23 | @abstract Notification indicating that the `currentProfile` has changed. 24 | @discussion the userInfo dictionary of the notification will contain keys 25 | `FBSDKProfileChangeOldKey` and 26 | `FBSDKProfileChangeNewKey`. 27 | */ 28 | FBSDK_EXTERN NSString *const FBSDKProfileDidChangeNotification; 29 | 30 | /* @abstract key in notification's userInfo object for getting the old profile. 31 | @discussion If there was no old profile, the key will not be present. 32 | */ 33 | FBSDK_EXTERN NSString *const FBSDKProfileChangeOldKey; 34 | 35 | /* @abstract key in notification's userInfo object for getting the new profile. 36 | @discussion If there is no new profile, the key will not be present. 37 | */ 38 | FBSDK_EXTERN NSString *const FBSDKProfileChangeNewKey; 39 | 40 | /*! 41 | @abstract Represents an immutable Facebook profile 42 | @discussion This class provides a global "currentProfile" instance to more easily 43 | add social context to your application. When the profile changes, a notification is 44 | posted so that you can update relevant parts of your UI and is persisted to NSUserDefaults. 45 | 46 | Typically, you will want to call `enableUpdatesOnAccessTokenChange:YES` so that 47 | it automatically observes changes to the `[FBSDKAccessToken currentAccessToken]`. 48 | 49 | You can use this class to build your own `FBSDKProfilePictureView` or in place of typical requests to "/me". 50 | */ 51 | @interface FBSDKProfile : NSObject 52 | 53 | /*! 54 | @abstract initializes a new instance. 55 | @param userID the user ID 56 | @param firstName the user's first name 57 | @param middleName the user's middle name 58 | @param lastName the user's last name 59 | @param name the user's complete name 60 | @param linkURL the link for this profile 61 | @param refreshDate the optional date this profile was fetched. Defaults to [NSDate date]. 62 | */ 63 | - (instancetype)initWithUserID:(NSString *)userID 64 | firstName:(NSString *)firstName 65 | middleName:(NSString *)middleName 66 | lastName:(NSString *)lastName 67 | name:(NSString *)name 68 | linkURL:(NSURL *)linkURL 69 | refreshDate:(NSDate *)refreshDate NS_DESIGNATED_INITIALIZER; 70 | /*! 71 | @abstract The user id 72 | */ 73 | @property (nonatomic, readonly) NSString *userID; 74 | /*! 75 | @abstract The user's first name 76 | */ 77 | @property (nonatomic, readonly) NSString *firstName; 78 | /*! 79 | @abstract The user's middle name 80 | */ 81 | @property (nonatomic, readonly) NSString *middleName; 82 | /*! 83 | @abstract The user's last name 84 | */ 85 | @property (nonatomic, readonly) NSString *lastName; 86 | /*! 87 | @abstract The user's complete name 88 | */ 89 | @property (nonatomic, readonly) NSString *name; 90 | /*! 91 | @abstract A URL to the user's profile. 92 | @discussion Consider using Bolts and `FBSDKAppLinkResolver` to resolve this 93 | to an app link to link directly to the user's profile in the Facebook app. 94 | */ 95 | @property (nonatomic, readonly) NSURL *linkURL; 96 | 97 | /*! 98 | @abstract The last time the profile data was fetched. 99 | */ 100 | @property (nonatomic, readonly) NSDate *refreshDate; 101 | 102 | /*! 103 | @abstract Gets the current FBSDKProfile instance. 104 | */ 105 | + (FBSDKProfile *)currentProfile; 106 | 107 | /*! 108 | @abstract Sets the current instance and posts the appropriate notification if the profile parameter is different 109 | than the receiver. 110 | @param profile the profile to set 111 | @discussion This persists the profile to NSUserDefaults. 112 | */ 113 | + (void)setCurrentProfile:(FBSDKProfile *)profile; 114 | 115 | /*! 116 | @abstract Indicates if `currentProfile` will automatically observe `FBSDKAccessTokenDidChangeNotification` notifications 117 | @param enable YES is observing 118 | @discussion If observing, this class will issue a graph request for public profile data when the current token's userID 119 | differs from the current profile. You can observe `FBSDKProfileDidChangeNotification` for when the profile is updated. 120 | 121 | Note that if `[FBSDKAccessToken currentAccessToken]` is unset, the `currentProfile` instance remains. It's also possible 122 | for `currentProfile` to return nil until the data is fetched. 123 | */ 124 | + (void)enableUpdatesOnAccessTokenChange:(BOOL)enable; 125 | 126 | /*! 127 | @abstract A convenience method for returning a complete `NSURL` for retrieving the user's profile image. 128 | @param mode The picture mode 129 | @param size The height and width. This will be rounded to integer precision. 130 | */ 131 | - (NSURL *)imageURLForPictureMode:(FBSDKProfilePictureMode)mode size:(CGSize)size; 132 | 133 | /*! 134 | @abstract A convenience method for returning a Graph API path for retrieving the user's profile image. 135 | @deprecated use `imageURLForPictureMode:size:` instead 136 | @discussion You can pass this to a `FBSDKGraphRequest` instance to download the image. 137 | @param mode The picture mode 138 | @param size The height and width. This will be rounded to integer precision. 139 | */ 140 | - (NSString *)imagePathForPictureMode:(FBSDKProfilePictureMode)mode size:(CGSize)size 141 | __attribute__ ((deprecated("use imageURLForPictureMode:size: instead"))); 142 | 143 | /*! 144 | @abstract Returns YES if the profile is equivalent to the receiver. 145 | @param profile the profile to compare to. 146 | */ 147 | - (BOOL)isEqualToProfile:(FBSDKProfile *)profile; 148 | @end 149 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKProfilePictureView.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | /*! 22 | @typedef FBSDKProfilePictureMode enum 23 | @abstract Defines the aspect ratio mode for the source image of the profile picture. 24 | */ 25 | typedef NS_ENUM(NSUInteger, FBSDKProfilePictureMode) 26 | { 27 | /*! 28 | @abstract A square cropped version of the image will be included in the view. 29 | */ 30 | FBSDKProfilePictureModeSquare, 31 | /*! 32 | @abstract The original picture's aspect ratio will be used for the source image in the view. 33 | */ 34 | FBSDKProfilePictureModeNormal, 35 | }; 36 | 37 | /*! 38 | @abstract A view to display a profile picture. 39 | */ 40 | @interface FBSDKProfilePictureView : UIView 41 | 42 | /*! 43 | @abstract The mode for the receiver to determine the aspect ratio of the source image. 44 | */ 45 | @property (nonatomic, assign) FBSDKProfilePictureMode pictureMode; 46 | 47 | /*! 48 | @abstract The profile ID to show the picture for. 49 | */ 50 | @property (nonatomic, copy) NSString *profileID; 51 | 52 | /*! 53 | @abstract Explicitly marks the receiver as needing to update the image. 54 | @discussion This method is called whenever any properties that affect the source image are modified, but this can also 55 | be used to trigger a manual update of the image if it needs to be re-downloaded. 56 | */ 57 | - (void)setNeedsImageUpdate; 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKSettings.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | 23 | /* 24 | * Constants defining logging behavior. Use with <[FBSDKSettings setLoggingBehavior]>. 25 | */ 26 | 27 | /*! Include access token in logging. */ 28 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorAccessTokens; 29 | 30 | /*! Log performance characteristics */ 31 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorPerformanceCharacteristics; 32 | 33 | /*! Log FBSDKAppEvents interactions */ 34 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorAppEvents; 35 | 36 | /*! Log Informational occurrences */ 37 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorInformational; 38 | 39 | /*! Log cache errors. */ 40 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorCacheErrors; 41 | 42 | /*! Log errors from SDK UI controls */ 43 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorUIControlErrors; 44 | 45 | /*! Log debug warnings from API response, i.e. when friends fields requested, but user_friends permission isn't granted. */ 46 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorGraphAPIDebugWarning; 47 | 48 | /*! Log warnings from API response, i.e. when requested feature will be deprecated in next version of API. 49 | Info is the lowest level of severity, using it will result in logging all previously mentioned levels. 50 | */ 51 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorGraphAPIDebugInfo; 52 | 53 | /*! Log errors from SDK network requests */ 54 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorNetworkRequests; 55 | 56 | /*! Log errors likely to be preventable by the developer. This is in the default set of enabled logging behaviors. */ 57 | FBSDK_EXTERN NSString *const FBSDKLoggingBehaviorDeveloperErrors; 58 | 59 | @interface FBSDKSettings : NSObject 60 | 61 | /*! 62 | @abstract Get the Facebook App ID used by the SDK. 63 | @discussion If not explicitly set, the default will be read from the application's plist (FacebookAppID). 64 | */ 65 | + (NSString *)appID; 66 | 67 | /*! 68 | @abstract Set the Facebook App ID to be used by the SDK. 69 | @param appID The Facebook App ID to be used by the SDK. 70 | */ 71 | + (void)setAppID:(NSString *)appID; 72 | 73 | /*! 74 | @abstract Get the default url scheme suffix used for sessions. 75 | @discussion If not explicitly set, the default will be read from the application's plist (FacebookUrlSchemeSuffix). 76 | */ 77 | + (NSString *)appURLSchemeSuffix; 78 | 79 | /*! 80 | @abstract Set the app url scheme suffix used by the SDK. 81 | @param appURLSchemeSuffix The url scheme suffix to be used by the SDK. 82 | */ 83 | + (void)setAppURLSchemeSuffix:(NSString *)appURLSchemeSuffix; 84 | 85 | /*! 86 | @abstract Retrieve the Client Token that has been set via [FBSDKSettings setClientToken]. 87 | @discussion If not explicitly set, the default will be read from the application's plist (FacebookClientToken). 88 | */ 89 | + (NSString *)clientToken; 90 | 91 | /*! 92 | @abstract Sets the Client Token for the Facebook App. 93 | @discussion This is needed for certain API calls when made anonymously, without a user-based access token. 94 | @param clientToken The Facebook App's "client token", which, for a given appid can be found in the Security 95 | section of the Advanced tab of the Facebook App settings found at 96 | */ 97 | + (void)setClientToken:(NSString *)clientToken; 98 | 99 | /*! 100 | @abstract A convenient way to toggle error recovery for all FBSDKGraphRequest instances created after this is set. 101 | @param disableGraphErrorRecovery YES or NO. 102 | */ 103 | + (void)setGraphErrorRecoveryDisabled:(BOOL)disableGraphErrorRecovery; 104 | 105 | /*! 106 | @abstract Get the Facebook Display Name used by the SDK. 107 | @discussion If not explicitly set, the default will be read from the application's plist (FacebookDisplayName). 108 | */ 109 | + (NSString *)displayName; 110 | 111 | /*! 112 | @abstract Set the default Facebook Display Name to be used by the SDK. 113 | @discussion This should match the Display Name that has been set for the app with the corresponding Facebook App ID, 114 | in the Facebook App Dashboard. 115 | @param displayName The Facebook Display Name to be used by the SDK. 116 | */ 117 | + (void)setDisplayName:(NSString *)displayName; 118 | 119 | /*! 120 | @abstract Get the Facebook domain part. 121 | @discussion If not explicitly set, the default will be read from the application's plist (FacebookDomainPart). 122 | */ 123 | + (NSString *)facebookDomainPart; 124 | 125 | /*! 126 | @abstract Set the subpart of the Facebook domain. 127 | @discussion This can be used to change the Facebook domain (e.g. @"beta") so that requests will be sent to 128 | graph.beta.facebook.com 129 | @param facebookDomainPart The domain part to be inserted into facebook.com. 130 | */ 131 | + (void)setFacebookDomainPart:(NSString *)facebookDomainPart; 132 | 133 | /*! 134 | @abstract The quality of JPEG images sent to Facebook from the SDK. 135 | @discussion If not explicitly set, the default is 0.9. 136 | @see [UIImageJPEGRepresentation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIImageJPEGRepresentation) */ 137 | + (CGFloat)JPEGCompressionQuality; 138 | 139 | /*! 140 | @abstract Set the quality of JPEG images sent to Facebook from the SDK. 141 | @param JPEGCompressionQuality The quality for JPEG images, expressed as a value from 0.0 to 1.0. 142 | @see [UIImageJPEGRepresentation](https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIKitFunctionReference/#//apple_ref/c/func/UIImageJPEGRepresentation) */ 143 | + (void)setJPEGCompressionQuality:(CGFloat)JPEGCompressionQuality; 144 | 145 | /*! 146 | @abstract 147 | Gets whether data such as that generated through FBSDKAppEvents and sent to Facebook should be restricted from being used for other than analytics and conversions. Defaults to NO. This value is stored on the device and persists across app launches. 148 | */ 149 | + (BOOL)limitEventAndDataUsage; 150 | 151 | /*! 152 | @abstract 153 | Sets whether data such as that generated through FBSDKAppEvents and sent to Facebook should be restricted from being used for other than analytics and conversions. Defaults to NO. This value is stored on the device and persists across app launches. 154 | 155 | @param limitEventAndDataUsage The desired value. 156 | */ 157 | + (void)setLimitEventAndDataUsage:(BOOL)limitEventAndDataUsage; 158 | 159 | /*! 160 | @abstract Retrieve the current iOS SDK version. 161 | */ 162 | + (NSString *)sdkVersion; 163 | 164 | /*! 165 | @abstract Retrieve the current Facebook SDK logging behavior. 166 | */ 167 | + (NSSet *)loggingBehavior; 168 | 169 | /*! 170 | @abstract Set the current Facebook SDK logging behavior. This should consist of strings defined as 171 | constants with FBSDKLoggingBehavior*. 172 | 173 | @param loggingBehavior A set of strings indicating what information should be logged. If nil is provided, the logging 174 | behavior is reset to the default set of enabled behaviors. Set to an empty set in order to disable all logging. 175 | 176 | @discussion You can also define this via an array in your app plist with key "FacebookLoggingBehavior" or add and remove individual values via enableLoggingBehavior: or disableLogginBehavior: 177 | */ 178 | + (void)setLoggingBehavior:(NSSet *)loggingBehavior; 179 | 180 | /*! 181 | @abstract Enable a particular Facebook SDK logging behavior. 182 | 183 | @param loggingBehavior The LoggingBehavior to enable. This should be a string defined as a constant with FBSDKLoggingBehavior*. 184 | */ 185 | + (void)enableLoggingBehavior:(NSString *)loggingBehavior; 186 | 187 | /*! 188 | @abstract Disable a particular Facebook SDK logging behavior. 189 | 190 | @param loggingBehavior The LoggingBehavior to disable. This should be a string defined as a constant with FBSDKLoggingBehavior*. 191 | */ 192 | + (void)disableLoggingBehavior:(NSString *)loggingBehavior; 193 | 194 | /*! 195 | @abstract Set the user defaults key used by legacy token caches. 196 | 197 | @param tokenInformationKeyName the key used by legacy token caches. 198 | 199 | @discussion Use this only if you customized FBSessionTokenCachingStrategy in v3.x of 200 | the Facebook SDK for iOS. 201 | */ 202 | + (void)setLegacyUserDefaultTokenInformationKeyName:(NSString *)tokenInformationKeyName; 203 | 204 | /*! 205 | @abstract Get the user defaults key used by legacy token caches. 206 | */ 207 | + (NSString *)legacyUserDefaultTokenInformationKeyName; 208 | 209 | @end 210 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKTestUsersManager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | @class FBSDKAccessToken; 22 | 23 | /*! 24 | @typedef 25 | 26 | @abstract Callback block for returning an array of FBSDKAccessToken instances (and possibly `NSNull` instances); or an error. 27 | */ 28 | typedef void (^FBSDKTestUsersManagerRetrieveTestAccountTokensHandler)(NSArray *tokens, NSError *error) ; 29 | 30 | /*! 31 | @typedef 32 | 33 | @abstract Callback block for removing a test user. 34 | */ 35 | typedef void (^FBSDKTestUsersManagerRemoveTestAccountHandler)(NSError *error) ; 36 | 37 | 38 | /*! 39 | @class FBSDKTestUsersManager 40 | @abstract Provides methods for managing test accounts for testing Facebook integration. 41 | 42 | @discussion Facebook allows developers to create test accounts for testing their applications' 43 | Facebook integration (see https://developers.facebook.com/docs/test_users/). This class 44 | simplifies use of these accounts for writing tests. It is not designed for use in 45 | production application code. 46 | 47 | This class will make Graph API calls on behalf of your app to manage test accounts and requires 48 | an app id and app secret. You will typically use this class to write unit or integration tests. 49 | Make sure you NEVER include your app secret in your production app. 50 | */ 51 | @interface FBSDKTestUsersManager : NSObject 52 | 53 | /*! 54 | @abstract construct or return the shared instance 55 | @param appID the Facebook app id 56 | @param appSecret the Facebook app secret 57 | */ 58 | + (instancetype)sharedInstanceForAppID:(NSString *)appID appSecret:(NSString *)appSecret; 59 | 60 | /*! 61 | @abstract retrieve FBSDKAccessToken instances for test accounts with the specific permissions. 62 | @param arraysOfPermissions an array of permissions sets, such as @[ [NSSet setWithObject:@"email"], [NSSet setWithObject:@"user_birthday"]] 63 | if you needed two test accounts with email and birthday permissions, respectively. You can pass in empty nested sets 64 | if you need two arbitrary test accounts. For convenience, passing nil is treated as @[ [NSSet set] ] 65 | for fetching a single test user. 66 | @param createIfNotFound if YES, new test accounts are created if no test accounts existed that fit the permissions 67 | requirement 68 | @param handler the callback to invoke which will return an array of `FBAccessTokenData` instances or an `NSError`. 69 | If param `createIfNotFound` is NO, the array may contain `[NSNull null]` instances. 70 | 71 | @discussion If you are requesting test accounts with differing number of permissions, try to order 72 | `arrayOfPermissionsArrays` so that the most number of permissions come first to minimize creation of new 73 | test accounts. 74 | */ 75 | - (void)requestTestAccountTokensWithArraysOfPermissions:(NSArray *)arraysOfPermissions 76 | createIfNotFound:(BOOL)createIfNotFound 77 | completionHandler:(FBSDKTestUsersManagerRetrieveTestAccountTokensHandler)handler; 78 | 79 | /*! 80 | @abstract add a test account with the specified permissions 81 | @param permissions the set of permissions, e.g., [NSSet setWithObjects:@"email", @"user_friends"] 82 | @param handler the callback handler 83 | */ 84 | - (void)addTestAccountWithPermissions:(NSSet *)permissions 85 | completionHandler:(FBSDKTestUsersManagerRetrieveTestAccountTokensHandler)handler; 86 | 87 | /*! 88 | @abstract remove a test account for the given user id 89 | @param userId the user id 90 | @param handler the callback handler 91 | */ 92 | - (void)removeTestAccount:(NSString *)userId completionHandler:(FBSDKTestUsersManagerRemoveTestAccountHandler)handler; 93 | 94 | /*! 95 | @abstract Make two test users friends with each other. 96 | @param first the token of the first user 97 | @param second the token of the second user 98 | @param callback the callback handler 99 | */ 100 | - (void)makeFriendsWithFirst:(FBSDKAccessToken *)first second:(FBSDKAccessToken *)second callback:(void (^)(NSError *))callback; 101 | 102 | @end 103 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Headers/FBSDKUtility.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | /*! 22 | @abstract Class to contain common utility methods. 23 | */ 24 | @interface FBSDKUtility : NSObject 25 | 26 | /*! 27 | @abstract Parses a query string into a dictionary. 28 | @param queryString The query string value. 29 | @return A dictionary with the key/value pairs. 30 | */ 31 | + (NSDictionary *)dictionaryWithQueryString:(NSString *)queryString; 32 | 33 | /*! 34 | @abstract Constructs a query string from a dictionary. 35 | @param dictionary The dictionary with key/value pairs for the query string. 36 | @param errorRef If an error occurs, upon return contains an NSError object that describes the problem. 37 | @result Query string representation of the parameters. 38 | */ 39 | + (NSString *)queryStringWithDictionary:(NSDictionary *)dictionary error:(NSError *__autoreleasing *)errorRef; 40 | 41 | /*! 42 | @abstract Decodes a value from an URL. 43 | @param value The value to decode. 44 | @result The decoded value. 45 | */ 46 | + (NSString *)URLDecode:(NSString *)value; 47 | 48 | /*! 49 | @abstract Encodes a value for an URL. 50 | @param value The value to encode. 51 | @result The encoded value. 52 | */ 53 | + (NSString *)URLEncode:(NSString *)value; 54 | 55 | @end 56 | -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/Frameworks/FBSDKCoreKit.framework/Info.plist -------------------------------------------------------------------------------- /Frameworks/FBSDKCoreKit.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module FBSDKCoreKit { 2 | umbrella header "FBSDKCoreKit.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/FBSDKLoginKit: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/Frameworks/FBSDKLoginKit.framework/FBSDKLoginKit -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/Headers/FBSDKLoginButton.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | 23 | #import 24 | 25 | #import "FBSDKTooltipView.h" 26 | 27 | @protocol FBSDKLoginButtonDelegate; 28 | 29 | /*! 30 | @typedef NS_ENUM(NSUInteger, FBSDKLoginButtonTooltipBehavior) 31 | @abstract Indicates the desired login tooltip behavior. 32 | */ 33 | typedef NS_ENUM(NSUInteger, FBSDKLoginButtonTooltipBehavior) 34 | { 35 | /*! The default behavior. The tooltip will only be displayed if 36 | the app is eligible (determined by possible server round trip) */ 37 | FBSDKLoginButtonTooltipBehaviorAutomatic = 0, 38 | /*! Force display of the tooltip (typically for UI testing) */ 39 | FBSDKLoginButtonTooltipBehaviorForceDisplay = 1, 40 | /*! Force disable. In this case you can still exert more refined 41 | control by manually constructing a `FBSDKLoginTooltipView` instance. */ 42 | FBSDKLoginButtonTooltipBehaviorDisable = 2 43 | }; 44 | 45 | /*! 46 | @abstract A button that initiates a log in or log out flow upon tapping. 47 | @discussion `FBSDKLoginButton` works with `[FBSDKAccessToken currentAccessToken]` to 48 | determine what to display, and automatically starts authentication when tapped (i.e., 49 | you do not need to manually subscribe action targets). 50 | 51 | Like `FBSDKLoginManager`, you should make sure your app delegate is connected to 52 | `FBSDKApplicationDelegate` in order for the button's delegate to receive messages. 53 | 54 | `FBSDKLoginButton` has a fixed height of @c 30 pixels, but you may change the width. `initWithFrame:CGRectZero` 55 | will size the button to its minimum frame. 56 | */ 57 | @interface FBSDKLoginButton : FBSDKButton 58 | 59 | /*! 60 | @abstract The default audience to use, if publish permissions are requested at login time. 61 | */ 62 | @property (assign, nonatomic) FBSDKDefaultAudience defaultAudience; 63 | /*! 64 | @abstract Gets or sets the delegate. 65 | */ 66 | @property (weak, nonatomic) IBOutlet id delegate; 67 | /*! 68 | @abstract Gets or sets the login behavior to use 69 | */ 70 | @property (assign, nonatomic) FBSDKLoginBehavior loginBehavior; 71 | /*! 72 | @abstract The publish permissions to request. 73 | 74 | @discussion Use `defaultAudience` to specify the default audience to publish to. 75 | Note this is converted to NSSet and is only 76 | an NSArray for the convenience of literal syntax. 77 | */ 78 | @property (copy, nonatomic) NSArray *publishPermissions; 79 | /*! 80 | @abstract The read permissions to request. 81 | 82 | @discussion Note, that if read permissions are specified, then publish permissions should not be specified. This is converted to NSSet and is only 83 | an NSArray for the convenience of literal syntax. 84 | */ 85 | @property (copy, nonatomic) NSArray *readPermissions; 86 | /*! 87 | @abstract Gets or sets the desired tooltip behavior. 88 | */ 89 | @property (assign, nonatomic) FBSDKLoginButtonTooltipBehavior tooltipBehavior; 90 | /*! 91 | @abstract Gets or sets the desired tooltip color style. 92 | */ 93 | @property (assign, nonatomic) FBSDKTooltipColorStyle tooltipColorStyle; 94 | 95 | @end 96 | 97 | /*! 98 | @protocol 99 | @abstract A delegate for `FBSDKLoginButton` 100 | */ 101 | @protocol FBSDKLoginButtonDelegate 102 | 103 | @required 104 | /*! 105 | @abstract Sent to the delegate when the button was used to login. 106 | @param loginButton the sender 107 | @param result The results of the login 108 | @param error The error (if any) from the login 109 | */ 110 | - (void) loginButton:(FBSDKLoginButton *)loginButton 111 | didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result 112 | error:(NSError *)error; 113 | 114 | /*! 115 | @abstract Sent to the delegate when the button was used to logout. 116 | @param loginButton The button that was clicked. 117 | */ 118 | - (void)loginButtonDidLogOut:(FBSDKLoginButton *)loginButton; 119 | 120 | @optional 121 | /*! 122 | @abstract Sent to the delegate when the button is about to login. 123 | @param loginButton the sender 124 | @return YES if the login should be allowed to proceed, NO otherwise 125 | */ 126 | - (BOOL) loginButtonWillLogin:(FBSDKLoginButton *)loginButton; 127 | 128 | @end 129 | -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/Headers/FBSDKLoginConstants.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | 23 | /*! 24 | @abstract The error domain for all errors from FBSDKLoginKit 25 | @discussion Error codes from the SDK in the range 300-399 are reserved for this domain. 26 | */ 27 | FBSDK_EXTERN NSString *const FBSDKLoginErrorDomain; 28 | 29 | /*! 30 | @typedef NS_ENUM(NSInteger, FBSDKLoginErrorCode) 31 | @abstract Error codes for FBSDKLoginErrorDomain. 32 | */ 33 | typedef NS_ENUM(NSInteger, FBSDKLoginErrorCode) 34 | { 35 | /*! 36 | @abstract Reserved. 37 | */ 38 | FBSDKLoginReservedErrorCode = 300, 39 | /*! 40 | @abstract The error code for unknown errors. 41 | */ 42 | FBSDKLoginUnknownErrorCode, 43 | 44 | /*! 45 | @abstract The user's password has changed and must log in again 46 | */ 47 | FBSDKLoginPasswordChangedErrorCode, 48 | /*! 49 | @abstract The user must log in to their account on www.facebook.com to restore access 50 | */ 51 | FBSDKLoginUserCheckpointedErrorCode, 52 | /*! 53 | @abstract Indicates a failure to request new permissions because the user has changed. 54 | */ 55 | FBSDKLoginUserMismatchErrorCode, 56 | /*! 57 | @abstract The user must confirm their account with Facebook before logging in 58 | */ 59 | FBSDKLoginUnconfirmedUserErrorCode, 60 | 61 | /*! 62 | @abstract The Accounts framework failed without returning an error, indicating the 63 | app's slider in the iOS Facebook Settings (device Settings -> Facebook -> App Name) has 64 | been disabled. 65 | */ 66 | FBSDKLoginSystemAccountAppDisabledErrorCode, 67 | /*! 68 | @abstract An error occurred related to Facebook system Account store 69 | */ 70 | FBSDKLoginSystemAccountUnavailableErrorCode, 71 | /*! 72 | @abstract The login response was missing a valid challenge string. 73 | */ 74 | FBSDKLoginBadChallengeString, 75 | }; 76 | -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/Headers/FBSDKLoginKit.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | #import 23 | #import 24 | #import 25 | #import 26 | -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/Headers/FBSDKLoginManager.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | #import 21 | #import 22 | 23 | @class FBSDKLoginManagerLoginResult; 24 | 25 | /*! 26 | @abstract Describes the call back to the FBSDKLoginManager 27 | @param result the result of the authorization 28 | @param error the authorization error, if any. 29 | */ 30 | typedef void (^FBSDKLoginManagerRequestTokenHandler)(FBSDKLoginManagerLoginResult *result, NSError *error); 31 | 32 | 33 | /*! 34 | @typedef FBSDKDefaultAudience enum 35 | 36 | @abstract 37 | Passed to open to indicate which default audience to use for sessions that post data to Facebook. 38 | 39 | @discussion 40 | Certain operations such as publishing a status or publishing a photo require an audience. When the user 41 | grants an application permission to perform a publish operation, a default audience is selected as the 42 | publication ceiling for the application. This enumerated value allows the application to select which 43 | audience to ask the user to grant publish permission for. 44 | */ 45 | typedef NS_ENUM(NSUInteger, FBSDKDefaultAudience) 46 | { 47 | /*! Indicates that the user's friends are able to see posts made by the application */ 48 | FBSDKDefaultAudienceFriends = 0, 49 | /*! Indicates that only the user is able to see posts made by the application */ 50 | FBSDKDefaultAudienceOnlyMe, 51 | /*! Indicates that all Facebook users are able to see posts made by the application */ 52 | FBSDKDefaultAudienceEveryone, 53 | }; 54 | 55 | /*! 56 | @typedef FBSDKLoginBehavior enum 57 | 58 | @abstract 59 | Passed to the \c FBSDKLoginManager to indicate how Facebook Login should be attempted. 60 | 61 | @discussion 62 | Facebook Login authorizes the application to act on behalf of the user, using the user's 63 | Facebook account. Usually a Facebook Login will rely on an account maintained outside of 64 | the application, by the native Facebook application, the browser, or perhaps the device 65 | itself. This avoids the need for a user to enter their username and password directly, and 66 | provides the most secure and lowest friction way for a user to authorize the application to 67 | interact with Facebook. 68 | 69 | The \c FBSDKLoginBehavior enum specifies which log-in methods may be used. The SDK 70 | will determine the best behavior based on the current device (such as iOS version). 71 | */ 72 | typedef NS_ENUM(NSUInteger, FBSDKLoginBehavior) 73 | { 74 | /*! 75 | @abstract This is the default behavior, and indicates logging in through the native 76 | Facebook app may be used. The SDK may still use Safari instead. 77 | */ 78 | FBSDKLoginBehaviorNative = 0, 79 | /*! 80 | @abstract Attempts log in through the Safari or SFSafariViewController, if available. 81 | */ 82 | FBSDKLoginBehaviorBrowser, 83 | /*! 84 | @abstract Attempts log in through the Facebook account currently signed in through 85 | the device Settings. 86 | @note If the account is not available to the app (either not configured by user or 87 | as determined by the SDK) this behavior falls back to \c FBSDKLoginBehaviorNative. 88 | */ 89 | FBSDKLoginBehaviorSystemAccount, 90 | /*! 91 | @abstract Attemps log in through a modal \c UIWebView pop up 92 | 93 | @note This behavior is only available to certain types of apps. Please check the Facebook 94 | Platform Policy to verify your app meets the restrictions. 95 | */ 96 | FBSDKLoginBehaviorWeb, 97 | }; 98 | 99 | /*! 100 | @abstract `FBSDKLoginManager` provides methods for logging the user in and out. 101 | @discussion `FBSDKLoginManager` works directly with `[FBSDKAccessToken currentAccessToken]` and 102 | sets the "currentAccessToken" upon successful authorizations (or sets `nil` in case of `logOut`). 103 | 104 | You should check `[FBSDKAccessToken currentAccessToken]` before calling logIn* to see if there is 105 | a cached token available (typically in your viewDidLoad). 106 | 107 | If you are managing your own token instances outside of "currentAccessToken", you will need to set 108 | "currentAccessToken" before calling logIn* to authorize futher permissions on your tokens. 109 | */ 110 | @interface FBSDKLoginManager : NSObject 111 | 112 | /*! 113 | @abstract the default audience. 114 | @discussion you should set this if you intend to ask for publish permissions. 115 | */ 116 | @property (assign, nonatomic) FBSDKDefaultAudience defaultAudience; 117 | 118 | /*! 119 | @abstract the login behavior 120 | */ 121 | @property (assign, nonatomic) FBSDKLoginBehavior loginBehavior; 122 | 123 | /*! 124 | @deprecated use logInWithReadPermissions:fromViewController:handler: instead 125 | */ 126 | - (void)logInWithReadPermissions:(NSArray *)permissions handler:(FBSDKLoginManagerRequestTokenHandler)handler 127 | __attribute__ ((deprecated("use logInWithReadPermissions:fromViewController:handler: instead"))); 128 | 129 | /*! 130 | @deprecated use logInWithPublishPermissions:fromViewController:handler: instead 131 | */ 132 | - (void)logInWithPublishPermissions:(NSArray *)permissions handler:(FBSDKLoginManagerRequestTokenHandler)handler 133 | __attribute__ ((deprecated("use logInWithPublishPermissions:fromViewController:handler: instead"))); 134 | 135 | /*! 136 | @abstract Logs the user in or authorizes additional permissions. 137 | @param permissions the optional array of permissions. Note this is converted to NSSet and is only 138 | an NSArray for the convenience of literal syntax. 139 | @param fromViewController the view controller to present from. If nil, the topmost view controller will be 140 | automatically determined as best as possible. 141 | @param handler the callback. 142 | @discussion Use this method when asking for read permissions. You should only ask for permissions when they 143 | are needed and explain the value to the user. You can inspect the result.declinedPermissions to also 144 | provide more information to the user if they decline permissions. 145 | 146 | If `[FBSDKAccessToken currentAccessToken]` is not nil, it will be treated as a reauthorization for that user 147 | and will pass the "rerequest" flag to the login dialog. 148 | 149 | This method will present UI the user. You typically should check if `[FBSDKAccessToken currentAccessToken]` 150 | already contains the permissions you need before asking to reduce unnecessary app switching. For example, 151 | you could make that check at viewDidLoad. 152 | */ 153 | - (void)logInWithReadPermissions:(NSArray *)permissions 154 | fromViewController:(UIViewController *)fromViewController 155 | handler:(FBSDKLoginManagerRequestTokenHandler)handler; 156 | 157 | /*! 158 | @abstract Logs the user in or authorizes additional permissions. 159 | @param permissions the optional array of permissions. Note this is converted to NSSet and is only 160 | an NSArray for the convenience of literal syntax. 161 | @param fromViewController the view controller to present from. If nil, the topmost view controller will be 162 | automatically determined as best as possible. 163 | @param handler the callback. 164 | @discussion Use this method when asking for publish permissions. You should only ask for permissions when they 165 | are needed and explain the value to the user. You can inspect the result.declinedPermissions to also 166 | provide more information to the user if they decline permissions. 167 | 168 | If `[FBSDKAccessToken currentAccessToken]` is not nil, it will be treated as a reauthorization for that user 169 | and will pass the "rerequest" flag to the login dialog. 170 | 171 | This method will present UI the user. You typically should check if `[FBSDKAccessToken currentAccessToken]` 172 | already contains the permissions you need before asking to reduce unnecessary app switching. For example, 173 | you could make that check at viewDidLoad. 174 | */ 175 | - (void)logInWithPublishPermissions:(NSArray *)permissions 176 | fromViewController:(UIViewController *)fromViewController 177 | handler:(FBSDKLoginManagerRequestTokenHandler)handler; 178 | 179 | /*! 180 | @abstract Logs the user out 181 | @discussion This calls [FBSDKAccessToken setCurrentAccessToken:nil] and [FBSDKProfile setCurrentProfile:nil]. 182 | */ 183 | - (void)logOut; 184 | 185 | /*! 186 | @method 187 | 188 | @abstract Issues an asychronous renewCredentialsForAccount call to the device's Facebook account store. 189 | 190 | @param handler The completion handler to call when the renewal is completed. This can be invoked on an arbitrary thread. 191 | 192 | @discussion This can be used to explicitly renew account credentials and is provided as a convenience wrapper around 193 | `[ACAccountStore renewCredentialsForAccount:completion]`. Note the method will not issue the renewal call if the the 194 | Facebook account has not been set on the device, or if access had not been granted to the account (though the handler 195 | wil receive an error). 196 | 197 | If the `[FBSDKAccessToken currentAccessToken]` was from the account store, a succesful renewal will also set 198 | a new "currentAccessToken". 199 | */ 200 | + (void)renewSystemCredentials:(void (^)(ACAccountCredentialRenewResult result, NSError *error))handler; 201 | 202 | @end 203 | -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/Headers/FBSDKLoginManagerLoginResult.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | @class FBSDKAccessToken; 22 | 23 | /*! 24 | @abstract Describes the result of a login attempt. 25 | */ 26 | @interface FBSDKLoginManagerLoginResult : NSObject 27 | 28 | /*! 29 | @abstract the access token. 30 | */ 31 | @property (copy, nonatomic) FBSDKAccessToken *token; 32 | 33 | /*! 34 | @abstract whether the login was cancelled by the user. 35 | */ 36 | @property (readonly, nonatomic) BOOL isCancelled; 37 | 38 | /*! 39 | @abstract the set of permissions granted by the user in the associated request. 40 | @discussion inspect the token's permissions set for a complete list. 41 | */ 42 | @property (copy, nonatomic) NSSet *grantedPermissions; 43 | 44 | /*! 45 | @abstract the set of permissions declined by the user in the associated request. 46 | @discussion inspect the token's permissions set for a complete list. 47 | */ 48 | @property (copy, nonatomic) NSSet *declinedPermissions; 49 | 50 | /*! 51 | @abstract Initializes a new instance. 52 | @param token the access token 53 | @param isCancelled whether the login was cancelled by the user 54 | @param grantedPermissions the set of granted permissions 55 | @param declinedPermissions the set of declined permissions 56 | */ 57 | - (instancetype)initWithToken:(FBSDKAccessToken *)token 58 | isCancelled:(BOOL)isCancelled 59 | grantedPermissions:(NSSet *)grantedPermissions 60 | declinedPermissions:(NSSet *)declinedPermissions 61 | NS_DESIGNATED_INITIALIZER; 62 | @end 63 | -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/Headers/FBSDKLoginTooltipView.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | #import 22 | 23 | @protocol FBSDKLoginTooltipViewDelegate; 24 | 25 | /*! 26 | @class FBSDKLoginTooltipView 27 | 28 | @abstract Represents a tooltip to be displayed next to a Facebook login button 29 | to highlight features for new users. 30 | 31 | @discussion The `FBSDKLoginButton` may display this view automatically. If you do 32 | not use the `FBSDKLoginButton`, you can manually call one of the `present*` methods 33 | as appropriate and customize behavior via `FBSDKLoginTooltipViewDelegate` delegate. 34 | 35 | By default, the `FBSDKLoginTooltipView` is not added to the superview until it is 36 | determined the app has migrated to the new login experience. You can override this 37 | (e.g., to test the UI layout) by implementing the delegate or setting `forceDisplay` to YES. 38 | 39 | */ 40 | @interface FBSDKLoginTooltipView : FBSDKTooltipView 41 | 42 | /*! @abstract the delegate */ 43 | @property (nonatomic, assign) id delegate; 44 | 45 | /*! @abstract if set to YES, the view will always be displayed and the delegate's 46 | `loginTooltipView:shouldAppear:` will NOT be called. */ 47 | @property (nonatomic, assign) BOOL forceDisplay; 48 | 49 | @end 50 | 51 | /*! 52 | @protocol 53 | 54 | @abstract 55 | The `FBSDKLoginTooltipViewDelegate` protocol defines the methods used to receive event 56 | notifications from `FBSDKLoginTooltipView` objects. 57 | */ 58 | @protocol FBSDKLoginTooltipViewDelegate 59 | 60 | @optional 61 | 62 | /*! 63 | @abstract 64 | Asks the delegate if the tooltip view should appear 65 | 66 | @param view The tooltip view. 67 | @param appIsEligible The value fetched from the server identifying if the app 68 | is eligible for the new login experience. 69 | 70 | @discussion Use this method to customize display behavior. 71 | */ 72 | - (BOOL)loginTooltipView:(FBSDKLoginTooltipView *)view shouldAppear:(BOOL)appIsEligible; 73 | 74 | /*! 75 | @abstract 76 | Tells the delegate the tooltip view will appear, specifically after it's been 77 | added to the super view but before the fade in animation. 78 | 79 | @param view The tooltip view. 80 | */ 81 | - (void)loginTooltipViewWillAppear:(FBSDKLoginTooltipView *)view; 82 | 83 | /*! 84 | @abstract 85 | Tells the delegate the tooltip view will not appear (i.e., was not 86 | added to the super view). 87 | 88 | @param view The tooltip view. 89 | */ 90 | - (void)loginTooltipViewWillNotAppear:(FBSDKLoginTooltipView *)view; 91 | 92 | 93 | @end 94 | -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/Headers/FBSDKTooltipView.h: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2014-present, Facebook, Inc. All rights reserved. 2 | // 3 | // You are hereby granted a non-exclusive, worldwide, royalty-free license to use, 4 | // copy, modify, and distribute this software in source code or binary form for use 5 | // in connection with the web services and APIs provided by Facebook. 6 | // 7 | // As with any software that integrates with the Facebook platform, your use of 8 | // this software is subject to the Facebook Developer Principles and Policies 9 | // [http://developers.facebook.com/policy/]. This copyright notice shall be 10 | // included in all copies or substantial portions of the software. 11 | // 12 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 13 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 14 | // FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 15 | // COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 16 | // IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 17 | // CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 18 | 19 | #import 20 | 21 | /*! 22 | @typedef FBSDKTooltipViewArrowDirection enum 23 | 24 | @abstract 25 | Passed on construction to determine arrow orientation. 26 | */ 27 | typedef NS_ENUM(NSUInteger, FBSDKTooltipViewArrowDirection) 28 | { 29 | /*! View is located above given point, arrow is pointing down. */ 30 | FBSDKTooltipViewArrowDirectionDown = 0, 31 | /*! View is located below given point, arrow is pointing up. */ 32 | FBSDKTooltipViewArrowDirectionUp = 1, 33 | }; 34 | 35 | /*! 36 | @typedef FBSDKTooltipColorStyle enum 37 | 38 | @abstract 39 | Passed on construction to determine color styling. 40 | */ 41 | typedef NS_ENUM(NSUInteger, FBSDKTooltipColorStyle) 42 | { 43 | /*! Light blue background, white text, faded blue close button. */ 44 | FBSDKTooltipColorStyleFriendlyBlue = 0, 45 | /*! Dark gray background, white text, light gray close button. */ 46 | FBSDKTooltipColorStyleNeutralGray = 1, 47 | }; 48 | 49 | /*! 50 | @class FBSDKTooltipView 51 | 52 | @abstract 53 | Tooltip bubble with text in it used to display tips for UI elements, 54 | with a pointed arrow (to refer to the UI element). 55 | 56 | @discussion 57 | The tooltip fades in and will automatically fade out. See `displayDuration`. 58 | */ 59 | @interface FBSDKTooltipView : UIView 60 | 61 | /*! 62 | @abstract Gets or sets the amount of time in seconds the tooltip should be displayed. 63 | 64 | @discussion Set this to zero to make the display permanent until explicitly dismissed. 65 | Defaults to six seconds. 66 | */ 67 | @property (nonatomic, assign) CFTimeInterval displayDuration; 68 | 69 | /*! 70 | @abstract Gets or sets the color style after initialization. 71 | 72 | @discussion Defaults to value passed to -initWithTagline:message:colorStyle:. 73 | */ 74 | @property (nonatomic, assign) FBSDKTooltipColorStyle colorStyle; 75 | 76 | /*! 77 | @abstract Gets or sets the message. 78 | */ 79 | @property (nonatomic, copy) NSString *message; 80 | 81 | /*! 82 | @abstract Gets or sets the optional phrase that comprises the first part of the label (and is highlighted differently). 83 | */ 84 | @property (nonatomic, copy) NSString *tagline; 85 | 86 | /*! 87 | @abstract 88 | Designated initializer. 89 | 90 | @param tagline First part of the label, that will be highlighted with different color. Can be nil. 91 | 92 | @param message Main message to display. 93 | 94 | @param colorStyle Color style to use for tooltip. 95 | 96 | @discussion 97 | If you need to show a tooltip for login, consider using the `FBSDKLoginTooltipView` view. 98 | 99 | @see FBSDKLoginTooltipView 100 | */ 101 | - (instancetype)initWithTagline:(NSString *)tagline message:(NSString *)message colorStyle:(FBSDKTooltipColorStyle)colorStyle; 102 | 103 | /*! 104 | @abstract 105 | Show tooltip at the top or at the bottom of given view. 106 | Tooltip will be added to anchorView.window.rootViewController.view 107 | 108 | @param anchorView view to show at, must be already added to window view hierarchy, in order to decide 109 | where tooltip will be shown. (If there's not enough space at the top of the anchorView in window bounds - 110 | tooltip will be shown at the bottom of it) 111 | 112 | @discussion 113 | Use this method to present the tooltip with automatic positioning or 114 | use -presentInView:withArrowPosition:direction: for manual positioning 115 | If anchorView is nil or has no window - this method does nothing. 116 | */ 117 | - (void)presentFromView:(UIView *)anchorView; 118 | 119 | /*! 120 | @abstract 121 | Adds tooltip to given view, with given position and arrow direction. 122 | 123 | @param view View to be used as superview. 124 | 125 | @param arrowPosition Point in view's cordinates, where arrow will be pointing 126 | 127 | @param arrowDirection whenever arrow should be pointing up (message bubble is below the arrow) or 128 | down (message bubble is above the arrow). 129 | */ 130 | - (void)presentInView:(UIView *)view withArrowPosition:(CGPoint)arrowPosition direction:(FBSDKTooltipViewArrowDirection)arrowDirection; 131 | 132 | /*! 133 | @abstract 134 | Remove tooltip manually. 135 | 136 | @discussion 137 | Calling this method isn't necessary - tooltip will dismiss itself automatically after the `displayDuration`. 138 | */ 139 | - (void)dismiss; 140 | 141 | @end 142 | -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/Info.plist: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/Frameworks/FBSDKLoginKit.framework/Info.plist -------------------------------------------------------------------------------- /Frameworks/FBSDKLoginKit.framework/Modules/module.modulemap: -------------------------------------------------------------------------------- 1 | framework module FBSDKLoginKit { 2 | umbrella header "FBSDKLoginKit.h" 3 | 4 | export * 5 | module * { export * } 6 | } 7 | -------------------------------------------------------------------------------- /Frameworks/README.md: -------------------------------------------------------------------------------- 1 | Copy CouchbaseLite.framework here 2 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | 2 | **This repository is in the process of being deprecated. See the [Swift TODO app](https://developer.couchbase.com/documentation/mobile/1.3/training/develop/create-database/index.html) in the training documentation for a more up-to-date sample. 3 | 4 | ## ToDo Lite for iOS 5 | 6 | This is a demo app showing how to use the [Couchbase Lite][CBL] framework to embed a nonrelational ("NoSQL") document-oriented database in an iOS app and sync it with [Couchbase Server][CBS] in "the cloud". 7 | 8 | ![screenshot](http://cl.ly/image/1K2X1W1W2V2E/ios_todolite.png) 9 | 10 | The app is a simple shared to-do list manager. Users can create multiple lists, each with its own items that can be checked off when done. Lists are private by default but can be shared with other users (which is very useful if your housemate is halfway to the grocery store when you remember you're out of pasta.) 11 | 12 | You can download a pre-buit version from the [iTunes App Store](https://itunes.apple.com/uy/app/todo-lite-sync/id697235451?mt=8). 13 | 14 | TodoLite for the [PhoneGap](https://github.com/couchbaselabs/ToDoLite-Phonegap) and [Android](https://github.com/couchbaselabs/ToDoLite-Android) platforms are also available. 15 | 16 | ### Benefits of Couchbase Lite 17 | 18 | What does Couchbase Lite bring to the table? 19 | 20 | * **Transparent data sync.** By now, users practically _expect_ that data they enter on one device will be accessible from others, including their laptops. Couchbase Lite makes this easy. The app code operates on the local database, and bidirectional sync happens in the background. 21 | * **Flexible, schemaless database.** Documents are stored as JSON, though they can be accessed as native Objective-C objects for convenience. There is no predefined schema. If you want to add new features like due dates or photo attachments, you won't have to deal with data migrations. The data will even interoperate with older versions of the app. 22 | * **Multi-user capability.** With the Couchbase Sync Gateway, any number of users can securely sync with a single server database and share only the data they want to. The design of the gateway makes writing collaborative and social apps extremely easy. 23 | * **Control over the back-end server.** You're not dependent on a big company to host everyone's data for you: you can run your own server, whether in a data center, on a host like EC2, or just on a spare PC in your office. It's even possible (though this app doesn't show how) to synchronize directly between two devices (P2P), with no server. 24 | * **Cross-platform.** Couchbase Lite currently supports iOS, Android and Mac OS X, and its underlying data formats and protocols (as well as source code) are fully open. 25 | 26 | 27 | ## Building & Running The Demo App 28 | 29 | Down to business: You should be familiar with how to build and run an iOS app. And you'll need a copy of Xcode version 6 or later. 30 | 31 | If you have questions or get stuck or just want to say hi, please visit the [Mobile Couchbase group][LIST] on Google Groups. 32 | 33 | 1. Clone or download this repository. 34 | 2. Download [Couchbase Lite][CBL_DOWNLOAD] 1.1 or later, or [check out and build it yourself][CBL_BUILD]. 35 | 3. Copy `CouchbaseLite.framework` into the `Frameworks` directory of this repo. 36 | 4. Open ToDoList.xcodeproj. 37 | 5. Select the "ToDoLite" scheme and the appropriate destination (simulator or attached iOS device) from the pop-up menu in the Xcode toolbar. 38 | 6. Click the Run button 39 | 40 | That's it! Now that you're set up, you can just use the Run command again after making changes to the demo code. 41 | 42 | ## Quick modifications you might want to make. 43 | 44 | In the AppDelegate.m file, there is a constant defined `kSyncGatewayUrl` -- by default when you log into the app via Facebook, it will sync with this test database hosted by Couchbase. If you deploy your own Sync Gateway, you will probably want to change this URL to point at your server. 45 | 46 | If you run your own Sync Gateway, the sync function source code we use is available in the `sync-gateway-config.json` file in the root of this repository. 47 | 48 | ## To add the framework to your existing Xcode project 49 | 50 | Please see the documentation for [Couchbase Lite][CBL]. 51 | 52 | 53 | ## License 54 | 55 | Released under the Apache license, 2.0. 56 | 57 | Copyright 2011-2016, Couchbase, Inc. 58 | 59 | 60 | [CBL]: https://github.com/couchbase/Couchbase-Lite-iOS/ 61 | [CBS]: http://www.couchbase.com/couchbase-server/overview 62 | [TODO_PHONEGAP]: https://github.com/couchbaselabs/TodoLite-PhoneGap 63 | [LIST]: https://groups.google.com/group/mobile-couchbase 64 | [CBL_DOWNLOAD]: http://www.couchbase.com/download#cb-mobile 65 | [CBL_BUILD]: https://github.com/couchbase/couchbase-lite-ios/wiki/Building-Couchbase-Lite 66 | -------------------------------------------------------------------------------- /ToDoLite.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ToDoLite/AppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.h 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/11/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface AppDelegate : UIResponder 13 | 14 | @property (strong, nonatomic) UIWindow *window; 15 | 16 | @property (strong, nonatomic, readonly) CBLDatabase *database; 17 | 18 | @property (strong, nonatomic, readonly) NSString *currentUserId; 19 | 20 | - (void)logout; 21 | 22 | - (void)showMessage:(NSString *)text withTitle:(NSString *)title; 23 | 24 | @end 25 | -------------------------------------------------------------------------------- /ToDoLite/AppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.m 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/11/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "DetailViewController.h" 11 | #import "LoginViewController.h" 12 | #import "Profile.h" 13 | #import "NSString+Additions.h" 14 | 15 | // Sync Gateway: 16 | #define kSyncGatewayUrl @"http://us-east.testfest.couchbasemobile.com:4984/todolite" 17 | //#define kSyncGatewayUrl @"http://:4984/todos" 18 | 19 | // Enable/disable WebSocket in pull replication: 20 | #define kSyncGatewayWebSocketSupport YES 21 | 22 | // Guest DB Name: 23 | #define kGuestDBName @"guest" 24 | 25 | // Storage Type: kCBLSQLiteStorage or kCBLForestDBStorage 26 | #define kStorageType kCBLSQLiteStorage 27 | 28 | // Encryption: 29 | // Note: This is just a sample showing how to set an encryption key. 30 | // In the any production apps, generate an encryption key and keep it 31 | // in the secure storage (e.g. keychain), not in source code. 32 | #define kEncryptionEnabled NO 33 | #define kEncryptionKey @"seekrit" 34 | 35 | // Enable or disable logging: 36 | #define kLoggingEnabled YES 37 | 38 | @interface AppDelegate () 39 | 40 | @property (nonatomic) CBLReplication *push; 41 | @property (nonatomic) CBLReplication *pull; 42 | @property (nonatomic) NSError *lastSyncError; 43 | @property (nonatomic) LoginViewController *loginViewController; 44 | 45 | @end 46 | 47 | @implementation AppDelegate 48 | 49 | - (BOOL)application:(UIApplication *)application 50 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 51 | [self enableLogging]; 52 | 53 | [LoginViewController application:application 54 | didFinishLaunchingWithOptions:launchOptions]; 55 | 56 | self.loginViewController = (LoginViewController *)self.window.rootViewController; 57 | self.loginViewController.delegate = self; 58 | 59 | return YES; 60 | } 61 | 62 | - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url 63 | sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { 64 | return [LoginViewController application:application 65 | openURL:url 66 | sourceApplication:sourceApplication 67 | annotation:annotation]; 68 | } 69 | 70 | #pragma mark - Logging 71 | 72 | - (void)enableLogging { 73 | if (kLoggingEnabled) { 74 | [CBLManager enableLogging:@"Database"]; 75 | [CBLManager enableLogging:@"View"]; 76 | [CBLManager enableLogging:@"ViewVerbose"]; 77 | [CBLManager enableLogging:@"Query"]; 78 | [CBLManager enableLogging:@"Sync"]; 79 | [CBLManager enableLogging:@"SyncVerbose"]; 80 | [CBLManager enableLogging:@"ChangeTracker"]; 81 | } 82 | } 83 | 84 | #pragma mark - Database 85 | 86 | - (void)setCurrentDatabase:(CBLDatabase *)database { 87 | [self willChangeValueForKey:@"database"]; 88 | _database = database; 89 | [self didChangeValueForKey:@"database"]; 90 | } 91 | 92 | - (CBLDatabase *)databaseForName:(NSString *)name { 93 | NSString *dbName = [NSString stringWithFormat:@"db%@", [[name MD5] lowercaseString]]; 94 | 95 | CBLDatabaseOptions *option = [[CBLDatabaseOptions alloc] init]; 96 | option.create = YES; 97 | option.storageType = kStorageType; 98 | option.encryptionKey = kEncryptionEnabled ? kEncryptionKey : nil; 99 | 100 | NSError *error; 101 | CBLDatabase *database = [[CBLManager sharedInstance] openDatabaseNamed:dbName 102 | withOptions:option 103 | error:&error]; 104 | if (error) 105 | NSLog(@"Cannot create database with an error : %@", [error description]); 106 | 107 | return database; 108 | } 109 | 110 | - (CBLDatabase *)databaseForUser:(NSString *)user { 111 | if (!user) return nil; 112 | return [self databaseForName:user]; 113 | } 114 | 115 | - (CBLDatabase *)databaseForGuest { 116 | return [self databaseForName:kGuestDBName]; 117 | } 118 | 119 | #pragma mark - Replication 120 | 121 | - (void)startReplicationWithAuthenticator:(id )authenticator { 122 | if (!_pull) { 123 | NSURL *syncUrl = [NSURL URLWithString:kSyncGatewayUrl]; 124 | _pull = [self.database createPullReplication:syncUrl]; 125 | _pull.continuous = YES; 126 | 127 | if (!kSyncGatewayWebSocketSupport) 128 | _pull.customProperties = @{@"websocket": @NO}; 129 | 130 | _push = [self.database createPushReplication:syncUrl]; 131 | _push.continuous = YES; 132 | 133 | // Observe replication progress changes, in both directions: 134 | NSNotificationCenter *nctr = [NSNotificationCenter defaultCenter]; 135 | [nctr addObserver:self selector:@selector(replicationProgress:) 136 | name:kCBLReplicationChangeNotification object:_pull]; 137 | [nctr addObserver: self selector: @selector(replicationProgress:) 138 | name:kCBLReplicationChangeNotification object:_push]; 139 | } 140 | 141 | _pull.authenticator = authenticator; 142 | _push.authenticator = authenticator; 143 | 144 | if (_push.running) 145 | [_push stop]; 146 | [_push start]; 147 | 148 | if (_pull.running) 149 | [_pull stop]; 150 | [_pull start]; 151 | } 152 | 153 | - (void)stopReplication { 154 | NSNotificationCenter *nctr = [NSNotificationCenter defaultCenter]; 155 | if (_pull) { 156 | [_pull stop]; 157 | [_pull clearAuthenticationStores:nil]; 158 | [nctr removeObserver:self name:kCBLReplicationChangeNotification object:_pull]; 159 | _pull = nil; 160 | } 161 | if (_push) { 162 | [_push stop]; 163 | [_push clearAuthenticationStores:nil]; 164 | [nctr removeObserver:self name:kCBLReplicationChangeNotification object:_push]; 165 | _pull = nil; 166 | } 167 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 168 | } 169 | 170 | - (void)replicationProgress:(NSNotification *)notification { 171 | if (_pull.status == kCBLReplicationActive || _push.status == kCBLReplicationActive) 172 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 173 | else 174 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 175 | 176 | // Check for any change in error status and display new errors: 177 | NSError* error = _pull.lastError ? _pull.lastError : _push.lastError; 178 | if (error != _lastSyncError) { 179 | _lastSyncError = error; 180 | if (error.code == 401) { 181 | [self showMessage:@"Authentication failed" withTitle:@"Sync Error"]; 182 | [self logout]; 183 | } else 184 | [self showMessage:error.description withTitle:@"Sync Error"]; 185 | } 186 | } 187 | 188 | #pragma mark - LoginViewControllerDelegate 189 | 190 | - (void)didLogInAsGuest { 191 | CBLDatabase *database = [self databaseForGuest]; 192 | [self setCurrentDatabase:database]; 193 | [self setCurrentUserId:nil]; 194 | } 195 | 196 | - (void)didLogInAsFacebookUserId:(NSString *)userId name:(NSString *)name token:(NSString *)token { 197 | [self setCurrentUserId:userId]; 198 | 199 | CBLDatabase *database = [self databaseForUser:userId]; 200 | [self setCurrentDatabase:database]; 201 | 202 | Profile *profile = [Profile profileInDatabase:database forExistingUserId:userId]; 203 | if (!profile) { 204 | if (name) { 205 | NSError *error; 206 | profile = [Profile profileInDatabase:database forNewUserId:userId name:name]; 207 | if ([profile save:&error]) 208 | [self migrateGuestDataToUser:profile]; 209 | else 210 | NSLog(@"Cannot create a new user profile with error : %@", error); 211 | } else 212 | NSLog(@"Cannot create a new user profile as there is no name information."); 213 | } 214 | 215 | if (profile) 216 | [self startReplicationWithAuthenticator: 217 | [CBLAuthenticator facebookAuthenticatorWithToken:token]]; 218 | else 219 | [self showMessage:@"Cannot create a new user profile" withTitle:@"Error"]; 220 | } 221 | 222 | - (void)didLogout { 223 | [self setCurrentUserId:nil]; 224 | [self stopReplication]; 225 | [self setCurrentDatabase:nil]; 226 | [self.loginViewController dismissViewControllerAnimated:YES completion:nil]; 227 | } 228 | 229 | #pragma mark - Login & Logout 230 | 231 | - (NSString *)currentUserId { 232 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 233 | return [defaults objectForKey:@"user_id"]; 234 | } 235 | 236 | - (void)setCurrentUserId:(NSString *)userId { 237 | NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; 238 | [defaults setObject:userId forKey:@"user_id"]; 239 | [defaults synchronize]; 240 | } 241 | 242 | - (void)logout { 243 | [self.loginViewController logout]; 244 | } 245 | 246 | - (void)migrateGuestDataToUser:(Profile *)profile { 247 | CBLDatabase *guestDB = [self databaseForGuest]; 248 | if (guestDB.lastSequenceNumber > 0) { 249 | CBLQueryEnumerator *rows = [[guestDB createAllDocumentsQuery] run:nil]; 250 | if (!rows) { 251 | return; 252 | } 253 | 254 | NSError *error; 255 | CBLDatabase *userDB = profile.database; 256 | for (CBLQueryRow *row in rows) { 257 | CBLDocument *doc = row.document; 258 | 259 | CBLDocument *newDoc = [userDB documentWithID:doc.documentID]; 260 | [newDoc putProperties:doc.userProperties error:&error]; 261 | if (error) { 262 | NSLog(@"Error when saving a new document during migrating guest data : %@", 263 | [error description]); 264 | continue; 265 | } 266 | 267 | NSArray *attachments = doc.currentRevision.attachments; 268 | if ([attachments count] > 0) { 269 | CBLUnsavedRevision *rev = [newDoc.currentRevision createRevision]; 270 | for (CBLAttachment *att in attachments) { 271 | [rev setAttachmentNamed:att.name 272 | withContentType:att.contentType 273 | content:att.content]; 274 | } 275 | 276 | CBLSavedRevision *saved = [rev save:&error]; 277 | if (!saved) { 278 | NSLog(@"Error when saving an attachment during migrating guest data : %@", 279 | [error description]); 280 | } 281 | } 282 | } 283 | 284 | error = nil; 285 | [List updateAllListsInDatabase:profile.database withOwner:profile error:&error]; 286 | if (error) { 287 | NSLog(@"Error when transfering the ownership of the list documents : %@", 288 | [error description]); 289 | } 290 | 291 | error = nil; 292 | if (![guestDB deleteDatabase:&error]) { 293 | NSLog(@"Error when deleting the guest database during migrating guest data : %@", 294 | [error description]); 295 | } 296 | } 297 | } 298 | 299 | #pragma mark - Message 300 | 301 | - (void)showMessage:(NSString *)text withTitle:(NSString *)title { 302 | [[[UIAlertView alloc] initWithTitle:title 303 | message:text 304 | delegate:nil 305 | cancelButtonTitle:@"OK" 306 | otherButtonTitles:nil] show]; 307 | } 308 | 309 | @end 310 | -------------------------------------------------------------------------------- /ToDoLite/Base.lproj/LaunchScreen.xib: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /ToDoLite/DetailViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.h 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/11/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import "List.h" 12 | #import "RoundedButton.h" 13 | #import "TaskTableViewCell.h" 14 | 15 | @interface DetailViewController : UIViewController 17 | 18 | @property (strong, nonatomic) List *list; 19 | @property (weak, nonatomic) IBOutlet UITableView *tableView; 20 | @property (weak, nonatomic) IBOutlet UITextField *addItemTextField; 21 | @property (weak, nonatomic) IBOutlet RoundedButton *addImageButton; 22 | 23 | @end 24 | 25 | -------------------------------------------------------------------------------- /ToDoLite/DetailViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // DetailViewController.m 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/11/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import "DetailViewController.h" 10 | #import "AppDelegate.h" 11 | #import "Task.h" 12 | #import "Profile.h" 13 | #import "ShareViewController.h" 14 | #import "ImageViewController.h" 15 | 16 | #define ImageDataContentType @"image/jpg" 17 | 18 | @interface DetailViewController () { 19 | Task *taskToAddImageTo; 20 | UIImage *imageForNewTask; 21 | UIImage *imageToDisplay; 22 | UIView *imageActionSheetSenderView; 23 | UIPopoverController *imagePickerPopover; 24 | } 25 | 26 | @property CBLDatabase *database; 27 | @property CBLLiveQuery *liveQuery; 28 | @property NSArray *tasks; 29 | 30 | @end 31 | 32 | @implementation DetailViewController 33 | 34 | - (void)viewDidLoad { 35 | [super viewDidLoad]; 36 | 37 | self.title = self.list.title; 38 | self.addImageButton.enabled = YES; 39 | self.addItemTextField.enabled = YES; 40 | 41 | self.liveQuery = [[self.list queryTasks] asLiveQuery]; 42 | [self.liveQuery addObserver:self forKeyPath:@"rows" options:0 context:nil]; 43 | } 44 | 45 | - (void)viewWillAppear:(BOOL)animated { 46 | // Hide the share button if the current user is guest or is not the owner of the list: 47 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 48 | if (![app.currentUserId isEqualToString:self.list.owner.user_id]) 49 | self.navigationItem.rightBarButtonItem = nil; 50 | 51 | NSIndexPath *selected = [self.tableView indexPathForSelectedRow]; 52 | if (selected) 53 | [self.tableView deselectRowAtIndexPath:selected animated:NO]; 54 | } 55 | 56 | - (void)didReceiveMemoryWarning { 57 | [super didReceiveMemoryWarning]; 58 | } 59 | 60 | - (void)dealloc { 61 | [self.liveQuery removeObserver:self forKeyPath:@"rows"]; 62 | } 63 | 64 | 65 | #pragma mark - KVO Observer for live query 66 | 67 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change 68 | context:(void *)context { 69 | self.tasks = self.liveQuery.rows.allObjects; 70 | [self.tableView reloadData]; 71 | } 72 | 73 | #pragma mark - Segues 74 | 75 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 76 | if ([[segue identifier] isEqualToString:@"share"]) { 77 | ShareViewController *controller = (ShareViewController *)[segue destinationViewController]; 78 | controller.list = self.list; 79 | } else if ([[segue identifier] isEqualToString:@"showImage"]) { 80 | ImageViewController *controller = (ImageViewController *)[segue destinationViewController]; 81 | controller.image = imageToDisplay; 82 | imageToDisplay = nil; 83 | } 84 | } 85 | 86 | #pragma mark - Text Field 87 | 88 | // Called when the text field's Return key is tapped. 89 | - (BOOL)textFieldShouldReturn:(UITextField *)textField { 90 | NSString *title = _addItemTextField.text; 91 | if (title.length == 0) { 92 | return NO; // Nothing entered 93 | } 94 | [_addItemTextField setText:nil]; 95 | 96 | NSData *image = imageForNewTask ? [self dataForImage:imageForNewTask] : nil; 97 | Task *task = [self.list addTaskWithTitle:title 98 | withImage:image 99 | withImageContentType:ImageDataContentType]; 100 | NSError *error; 101 | if ([task save:&error]) { 102 | imageForNewTask = nil; 103 | [self updateAddImageButtonWithImage:nil]; 104 | } else { 105 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 106 | [app showMessage:@"Couldn't save new task" withTitle:@"Error"]; 107 | } 108 | 109 | [textField resignFirstResponder]; 110 | 111 | return YES; 112 | } 113 | 114 | #pragma mark - UIImagePicker 115 | 116 | - (BOOL)hasCamera { 117 | return [UIImagePickerController isSourceTypeAvailable:UIImagePickerControllerSourceTypeCamera]; 118 | } 119 | 120 | - (void)displayAddImageActionSheetFor:(UIView *)sender forTask:(Task *)task { 121 | taskToAddImageTo = task; 122 | imageActionSheetSenderView = sender; 123 | 124 | UIActionSheet *actionSheet = [[UIActionSheet alloc] init]; 125 | 126 | if ([self hasCamera]) [actionSheet addButtonWithTitle:@"Take Photo"]; 127 | [actionSheet addButtonWithTitle:@"Choose Existing"]; 128 | if (imageForNewTask)[actionSheet addButtonWithTitle:@"Delete"]; 129 | [actionSheet addButtonWithTitle:@"Cancel"]; 130 | 131 | [actionSheet setCancelButtonIndex:actionSheet.numberOfButtons - 1]; 132 | [actionSheet setDelegate:self]; 133 | [actionSheet showFromRect:sender.frame inView:[sender superview] animated:YES]; 134 | } 135 | 136 | - (void)displayImagePickerForSender:(UIView *)senderView 137 | sourceType:(UIImagePickerControllerSourceType)sourceType { 138 | UIImagePickerController *picker = [[UIImagePickerController alloc] init]; 139 | picker.sourceType = sourceType; 140 | picker.allowsEditing = YES; 141 | picker.delegate = self; 142 | 143 | imagePickerPopover = nil; 144 | 145 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad && 146 | sourceType == UIImagePickerControllerSourceTypePhotoLibrary) { 147 | CGRect displayFrame = [[senderView superview] 148 | convertRect:senderView.frame toView:self.view]; 149 | imagePickerPopover = [[UIPopoverController alloc] initWithContentViewController:picker]; 150 | [imagePickerPopover presentPopoverFromRect:displayFrame 151 | inView:self.view 152 | permittedArrowDirections:UIPopoverArrowDirectionAny 153 | animated:YES]; 154 | } else { 155 | [self presentViewController:picker animated:YES completion:^{ }]; 156 | } 157 | } 158 | 159 | - (void)updateAddImageButtonWithImage:(UIImage *)image { 160 | if (image) { 161 | [_addImageButton setImage:image forState:UIControlStateNormal]; 162 | } else { 163 | [_addImageButton setImage:[UIImage imageNamed:@"Camera"] forState:UIControlStateNormal]; 164 | } 165 | } 166 | 167 | - (NSData *)dataForImage:(UIImage *)image { 168 | return UIImageJPEGRepresentation(image, 0.5); 169 | } 170 | 171 | - (IBAction)addImageButtonAction:(UIButton *)sender { 172 | [self.addItemTextField resignFirstResponder]; 173 | [self displayAddImageActionSheetFor:sender forTask:nil]; 174 | } 175 | 176 | #pragma mark - UIImagePickerViewDelegate 177 | 178 | - (void)imagePickerController:(UIImagePickerController *)picker 179 | didFinishPickingMediaWithInfo:(NSDictionary *)info { 180 | UIImage *selectedImage = (UIImage *) [info objectForKey:UIImagePickerControllerEditedImage]; 181 | if (taskToAddImageTo) { 182 | [taskToAddImageTo setImage: 183 | [self dataForImage:selectedImage] contentType:ImageDataContentType]; 184 | 185 | NSError *error; 186 | if (![taskToAddImageTo save:&error]) { 187 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 188 | [app showMessage:@"Couldn't save the image to the task" withTitle:@"Error"]; 189 | } 190 | } else { 191 | // new task 192 | imageForNewTask = selectedImage; 193 | [self updateAddImageButtonWithImage:imageForNewTask]; 194 | } 195 | 196 | if (imagePickerPopover) { 197 | [imagePickerPopover dismissPopoverAnimated:YES]; 198 | } else { 199 | [picker.presentingViewController dismissViewControllerAnimated:YES completion:^{ }]; 200 | } 201 | } 202 | 203 | #pragma mark - ActionSheetDelegate 204 | 205 | - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { 206 | if (buttonIndex == actionSheet.cancelButtonIndex) { 207 | return; 208 | } 209 | 210 | if (imageForNewTask && buttonIndex == actionSheet.cancelButtonIndex - 1) { 211 | [self updateAddImageButtonWithImage:nil]; 212 | imageForNewTask = nil; 213 | return; 214 | } 215 | 216 | UIImagePickerControllerSourceType sourceType = ([self hasCamera] && buttonIndex == 0) ? 217 | UIImagePickerControllerSourceTypeCamera : UIImagePickerControllerSourceTypePhotoLibrary; 218 | 219 | dispatch_async(dispatch_get_main_queue(), ^{ 220 | [self displayImagePickerForSender:imageActionSheetSenderView sourceType:sourceType]; 221 | }); 222 | } 223 | 224 | #pragma mark - Table View Datasource 225 | 226 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 227 | return self.tasks.count; 228 | } 229 | 230 | - (UITableViewCell *)tableView:(UITableView *)tableView 231 | cellForRowAtIndexPath:(NSIndexPath *)indexPath { 232 | TaskTableViewCell *cell = (TaskTableViewCell *) 233 | [tableView dequeueReusableCellWithIdentifier:@"Task" forIndexPath:indexPath]; 234 | CBLQueryRow* row = [self.tasks objectAtIndex:indexPath.row]; 235 | Task *task = [Task modelForDocument:row.document]; 236 | cell.task = task; 237 | cell.delegate = self; 238 | return cell; 239 | } 240 | 241 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 242 | CBLQueryRow* row = [self.tasks objectAtIndex:indexPath.row]; 243 | Task *task = [Task modelForDocument:row.document]; 244 | task.checked = !task.checked; 245 | 246 | NSError *error; 247 | if (![task save:&error]) { 248 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 249 | [app showMessage:@"Failed to update the task" withTitle:@"Error"]; 250 | } 251 | } 252 | 253 | - (void)didSelectImageButton:(UIButton *)imageButton ofTask:(Task *)task { 254 | [self.addItemTextField resignFirstResponder]; 255 | CBLAttachment *attachment = [task attachmentNamed:@"image"]; 256 | if (attachment) { 257 | imageToDisplay = [UIImage imageWithData:attachment.content]; 258 | [self performSegueWithIdentifier: @"showImage" sender: self]; 259 | } else { 260 | [self displayAddImageActionSheetFor:imageButton forTask:task]; 261 | } 262 | } 263 | 264 | - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)style 265 | forRowAtIndexPath:(NSIndexPath *)indexPath { 266 | if (style == UITableViewCellEditingStyleDelete) { 267 | CBLQueryRow* row = [self.tasks objectAtIndex:indexPath.row]; 268 | Task *task = [Task modelForDocument:row.document]; 269 | [task deleteTask:nil]; 270 | } 271 | } 272 | 273 | #pragma mark - UIScrollViewDelegate 274 | 275 | - (void)scrollViewDidScroll:(UIScrollView *)scrollView { 276 | [self.addItemTextField resignFirstResponder]; 277 | } 278 | 279 | @end 280 | -------------------------------------------------------------------------------- /ToDoLite/ImageViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.h 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 4/8/14. 6 | // Copyright (c) 2014 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface ImageViewController : UIViewController 12 | 13 | @property (weak, nonatomic) IBOutlet UIImageView *imageView; 14 | 15 | @property (strong, nonatomic) UIImage *image; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /ToDoLite/ImageViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ImageViewController.m 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 4/8/14. 6 | // Copyright (c) 2014 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import "ImageViewController.h" 10 | 11 | @interface ImageViewController () 12 | 13 | @end 14 | 15 | @implementation ImageViewController 16 | 17 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 18 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 19 | return self; 20 | } 21 | 22 | - (void)viewDidLoad { 23 | [super viewDidLoad]; 24 | [self.imageView addGestureRecognizer: 25 | [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)]]; 26 | [self.imageView setImage:self.image]; 27 | } 28 | 29 | - (void)didReceiveMemoryWarning { 30 | [super didReceiveMemoryWarning]; 31 | } 32 | 33 | - (BOOL)prefersStatusBarHidden { 34 | return YES; 35 | } 36 | 37 | #pragma mark - Properties 38 | 39 | - (void)setImage:(UIImage *)image { 40 | _image = image; 41 | [self.imageView setImage:image]; 42 | } 43 | 44 | #pragma mark - Gesture Recognizer 45 | 46 | - (void)handleTap:(UIGestureRecognizer *)recognizer { 47 | [self dismissViewControllerAnimated:NO completion:^{ }]; 48 | } 49 | 50 | @end 51 | -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "29x29", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-29.png", 7 | "scale" : "1x" 8 | }, 9 | { 10 | "size" : "29x29", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-29@2x.png", 13 | "scale" : "2x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-29@3x.png", 19 | "scale" : "3x" 20 | }, 21 | { 22 | "size" : "40x40", 23 | "idiom" : "iphone", 24 | "filename" : "iPhone-Spotlight-40@2x.png", 25 | "scale" : "2x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "iPhone-Spotlight-40@3x.png", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "size" : "57x57", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-57.png", 37 | "scale" : "1x" 38 | }, 39 | { 40 | "size" : "57x57", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-57@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-60@2x.png", 49 | "scale" : "2x" 50 | }, 51 | { 52 | "size" : "60x60", 53 | "idiom" : "iphone", 54 | "filename" : "Icon-60@3x.png", 55 | "scale" : "3x" 56 | }, 57 | { 58 | "size" : "29x29", 59 | "idiom" : "ipad", 60 | "filename" : "iPad-Settings-29.png", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "iPad-Settings-29@2x.png", 67 | "scale" : "2x" 68 | }, 69 | { 70 | "size" : "40x40", 71 | "idiom" : "ipad", 72 | "filename" : "iPad-Spotlight-40@2x.png", 73 | "scale" : "1x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "iPad-Spotlight-40@2x-1.png", 79 | "scale" : "2x" 80 | }, 81 | { 82 | "size" : "50x50", 83 | "idiom" : "ipad", 84 | "filename" : "iPad-Spotlight-50.png", 85 | "scale" : "1x" 86 | }, 87 | { 88 | "size" : "50x50", 89 | "idiom" : "ipad", 90 | "filename" : "iPad-Spotlight-50@2x.png", 91 | "scale" : "2x" 92 | }, 93 | { 94 | "size" : "72x72", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-72.png", 97 | "scale" : "1x" 98 | }, 99 | { 100 | "size" : "72x72", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-72@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "76x76", 107 | "idiom" : "ipad", 108 | "filename" : "Icon-76.png", 109 | "scale" : "1x" 110 | }, 111 | { 112 | "size" : "76x76", 113 | "idiom" : "ipad", 114 | "filename" : "Icon-76@2x.png", 115 | "scale" : "2x" 116 | } 117 | ], 118 | "info" : { 119 | "version" : 1, 120 | "author" : "xcode" 121 | } 122 | } -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-29.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-29@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-29@3x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-57.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-57.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-57@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-57@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-60@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-60@3x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-72.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-72.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-72@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-76.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-76.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/Icon-76@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Settings-29.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Settings-29.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Settings-29@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Settings-29@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Spotlight-40@2x-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Spotlight-40@2x-1.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Spotlight-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Spotlight-40@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Spotlight-50.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Spotlight-50.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Spotlight-50@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/iPad-Spotlight-50@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/iPhone-Spotlight-40@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/iPhone-Spotlight-40@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/AppIcon.appiconset/iPhone-Spotlight-40@3x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/AppIcon.appiconset/iPhone-Spotlight-40@3x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/Camera-Light.imageset/Camera-Light@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/Camera-Light.imageset/Camera-Light@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/Camera-Light.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "Camera-Light@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/Camera.imageset/Camera@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/Camera.imageset/Camera@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/Camera.imageset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "universal", 5 | "scale" : "1x" 6 | }, 7 | { 8 | "idiom" : "universal", 9 | "scale" : "2x", 10 | "filename" : "Camera@2x.png" 11 | }, 12 | { 13 | "idiom" : "universal", 14 | "scale" : "3x" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "iphone", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "filename" : "iPhone-Portrait@2x.png", 9 | "scale" : "2x" 10 | }, 11 | { 12 | "extent" : "full-screen", 13 | "idiom" : "iphone", 14 | "subtype" : "retina4", 15 | "filename" : "iPhone-Retina@2x.png", 16 | "minimum-system-version" : "7.0", 17 | "orientation" : "portrait", 18 | "scale" : "2x" 19 | }, 20 | { 21 | "orientation" : "portrait", 22 | "idiom" : "ipad", 23 | "extent" : "full-screen", 24 | "minimum-system-version" : "7.0", 25 | "filename" : "iPad-Portrait.png", 26 | "scale" : "1x" 27 | }, 28 | { 29 | "orientation" : "landscape", 30 | "idiom" : "ipad", 31 | "extent" : "full-screen", 32 | "minimum-system-version" : "7.0", 33 | "filename" : "iPad-Landscape.png", 34 | "scale" : "1x" 35 | }, 36 | { 37 | "orientation" : "portrait", 38 | "idiom" : "ipad", 39 | "extent" : "full-screen", 40 | "minimum-system-version" : "7.0", 41 | "filename" : "iPad-Portrait@2x.png", 42 | "scale" : "2x" 43 | }, 44 | { 45 | "orientation" : "landscape", 46 | "idiom" : "ipad", 47 | "extent" : "full-screen", 48 | "minimum-system-version" : "7.0", 49 | "filename" : "iPad-Landscape@2x.png", 50 | "scale" : "2x" 51 | } 52 | ], 53 | "info" : { 54 | "version" : 1, 55 | "author" : "xcode" 56 | } 57 | } -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/LaunchImage.launchimage/iPad-Landscape.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/LaunchImage.launchimage/iPad-Landscape.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/LaunchImage.launchimage/iPad-Landscape@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/LaunchImage.launchimage/iPad-Landscape@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/LaunchImage.launchimage/iPad-Portrait.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/LaunchImage.launchimage/iPad-Portrait.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/LaunchImage.launchimage/iPad-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/LaunchImage.launchimage/iPad-Portrait@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/LaunchImage.launchimage/iPhone-Portrait@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/LaunchImage.launchimage/iPhone-Portrait@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/LaunchImage.launchimage/iPhone-Retina@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/LaunchImage.launchimage/iPhone-Retina@2x.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/Logo.imageset/AppIcon-Original.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/couchbaselabs/ToDoLite-iOS/d209cb7d0399761899bb39d2dd3f8a6c5b99a09a/ToDoLite/Images.xcassets/Logo.imageset/AppIcon-Original.png -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/Logo.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 | "filename" : "AppIcon-Original.png" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ToDoLite/Images.xcassets/logo.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 | "filename" : "AppIcon-Original.png" 15 | } 16 | ], 17 | "info" : { 18 | "version" : 1, 19 | "author" : "xcode" 20 | } 21 | } -------------------------------------------------------------------------------- /ToDoLite/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.couchbase.todolite 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.4 19 | CFBundleSignature 20 | ???? 21 | CFBundleURLTypes 22 | 23 | 24 | CFBundleURLSchemes 25 | 26 | fb510926975701287 27 | 28 | 29 | 30 | CFBundleVersion 31 | 1.4.1 32 | FacebookAppID 33 | 510926975701287 34 | FacebookDisplayName 35 | ToDoLite 36 | LSRequiresIPhoneOS 37 | 38 | UILaunchStoryboardName 39 | LaunchScreen 40 | UIMainStoryboardFile 41 | Main 42 | UIRequiredDeviceCapabilities 43 | 44 | armv7 45 | 46 | UIStatusBarTintParameters 47 | 48 | UINavigationBar 49 | 50 | Style 51 | UIBarStyleDefault 52 | Translucent 53 | 54 | 55 | 56 | UISupportedInterfaceOrientations 57 | 58 | UIInterfaceOrientationPortrait 59 | UIInterfaceOrientationLandscapeLeft 60 | UIInterfaceOrientationLandscapeRight 61 | 62 | UISupportedInterfaceOrientations~ipad 63 | 64 | UIInterfaceOrientationPortrait 65 | UIInterfaceOrientationPortraitUpsideDown 66 | UIInterfaceOrientationLandscapeLeft 67 | UIInterfaceOrientationLandscapeRight 68 | 69 | NSAppTransportSecurity 70 | 71 | NSAllowsArbitraryLoads 72 | 73 | 74 | LSApplicationQueriesSchemes 75 | 76 | fbapi 77 | fb-messenger-api 78 | fbauth2 79 | fbshareextension 80 | 81 | NSCameraUsageDescription 82 | Taking a photo and attach to the task. 83 | NSPhotoLibraryUsageDescription 84 | Select your photo and attach to the task. 85 | 86 | 87 | -------------------------------------------------------------------------------- /ToDoLite/List.h: -------------------------------------------------------------------------------- 1 | // 2 | // List.h 3 | // ToDo Lite 4 | // 5 | // Created by Jens Alfke on 8/22/13. 6 | // 7 | // 8 | 9 | #import "Titled.h" 10 | 11 | @class Task, Profile; 12 | 13 | /** A list of Tasks. (See Titled for inherited properties!) */ 14 | @interface List : Titled 15 | 16 | /** Returns a query for all the lists in a database. */ 17 | + (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db; 18 | 19 | /** Run before first sync to tag existing local lists as belonging to the current user. */ 20 | + (void) updateAllListsInDatabase: (CBLDatabase*)database withOwner: (Profile*)owner error: (NSError**)error ; 21 | 22 | /** Returns a query for this list's tasks, in reverse chronological order. */ 23 | - (CBLQuery*) queryTasks; 24 | 25 | /** Creates a new task. */ 26 | - (Task*) addTaskWithTitle: (NSString*)title withImage: (NSData*)image withImageContentType: (NSString*)contentType; 27 | 28 | /** Delete the list. */ 29 | - (BOOL) deleteList: (NSError**)error; 30 | 31 | @property (readwrite) Profile* owner; 32 | 33 | @property (readwrite) NSArray* members; 34 | 35 | @end 36 | -------------------------------------------------------------------------------- /ToDoLite/List.m: -------------------------------------------------------------------------------- 1 | // 2 | // List.m 3 | // ToDo Lite 4 | // 5 | // Created by Jens Alfke on 8/22/13. 6 | // 7 | // 8 | 9 | #import "List.h" 10 | #import "Task.h" 11 | #import "Profile.h" 12 | 13 | #define kListDocType @"list" 14 | 15 | @implementation List 16 | 17 | @dynamic owner, members; 18 | 19 | + (NSString*) docType { 20 | return kListDocType; 21 | } 22 | 23 | // Returns a query for all the lists in a database. 24 | + (CBLQuery*) queryListsInDatabase: (CBLDatabase*)db { 25 | CBLView* view = [db viewNamed: @"lists"]; 26 | if (!view.mapBlock) { 27 | // Register the map function, the first time we access the view: 28 | [view setMapBlock: MAPBLOCK({ 29 | if ([doc[@"type"] isEqualToString:kListDocType]) 30 | emit(doc[@"title"], nil); 31 | }) reduceBlock: nil version: @"1"]; // bump version any time you change the MAPBLOCK body! 32 | } 33 | return [view createQuery]; 34 | } 35 | 36 | + (void) updateAllListsInDatabase: (CBLDatabase*)database withOwner: (Profile*)owner error: (NSError**)error { 37 | CBLQueryEnumerator *myLists = [[List queryListsInDatabase:database] run:error]; 38 | if (!myLists) { 39 | return; 40 | } 41 | 42 | for (CBLQueryRow* row in myLists) { 43 | List* list = [List modelForDocument: row.document]; 44 | list.owner = owner; 45 | if (![list save:error]) { 46 | return; 47 | } 48 | } 49 | } 50 | 51 | // Creates a new task. 52 | - (Task*) addTaskWithTitle: (NSString*)title withImage: (NSData*)image withImageContentType: (NSString*)contentType { 53 | Task *task = [Task modelForNewDocumentInDatabase:self.database]; 54 | task.title = title; 55 | task.list_id = self; 56 | [task setImage:image contentType:contentType]; 57 | return task; 58 | } 59 | 60 | // Returns a query for this list's tasks, in reverse chronological order. 61 | - (CBLQuery*) queryTasks { 62 | CBLView* view = [self.document.database viewNamed: @"tasksByDate"]; 63 | if (!view.mapBlock) { 64 | // On first query after launch, register the map function: 65 | NSString* const kTaskDocType = [Task docType]; 66 | [view setMapBlock: MAPBLOCK({ 67 | if ([doc[@"type"] isEqualToString: kTaskDocType]) { 68 | id date = doc[@"created_at"]; 69 | NSString* listID = doc[@"list_id"]; 70 | emit(@[listID, date], doc); 71 | } 72 | }) reduceBlock: nil version: @"4"]; // bump version any time you change the MAPBLOCK body! 73 | } 74 | 75 | // Configure the query. Since it's in descending order, the startKey is the maximum key, 76 | // while the endKey is the _minimum_ key. (The empty object @{} is a placeholder that's 77 | // greater than any actual value.) Got that? 78 | CBLQuery* query = [view createQuery]; 79 | query.descending = YES; 80 | NSString* myListId = self.document.documentID; 81 | query.startKey = @[myListId, @{}]; 82 | query.endKey = @[myListId]; 83 | return query; 84 | } 85 | 86 | // Delete list 87 | - (BOOL)deleteList: (NSError**)error { 88 | CBLQueryEnumerator* tasks = [[self queryTasks] run: error]; 89 | for (CBLQueryRow* row in tasks) { 90 | if (![row.document.currentRevision deleteDocument: error]) { 91 | return NO; 92 | } 93 | } 94 | return [self deleteDocument: error]; 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /ToDoLite/LoginViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.h 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/13/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @protocol LoginViewControllerDelegate; 12 | 13 | @interface LoginViewController : UIViewController 14 | 15 | @property id delegate; 16 | 17 | + (BOOL)application:(UIApplication *)application 18 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions; 19 | 20 | + (BOOL)application:(UIApplication *)application openURL:(NSURL *)url 21 | sourceApplication:(NSString *)sourceApplication annotation:(id)annotation; 22 | 23 | - (void)logout; 24 | 25 | @end 26 | 27 | @protocol LoginViewControllerDelegate 28 | 29 | - (void)didLogInAsGuest; 30 | - (void)didLogInAsFacebookUserId:(NSString *)userId name:(NSString *)name token:(NSString *)token; 31 | - (void)didLogout; 32 | 33 | @end 34 | -------------------------------------------------------------------------------- /ToDoLite/LoginViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // LoginViewController.m 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/13/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import "LoginViewController.h" 10 | #import 11 | #import 12 | #import "AppDelegate.h" 13 | 14 | @interface LoginViewController () 15 | 16 | @property (nonatomic) FBSDKLoginManager *facebookLoginManager; 17 | @property (nonatomic) UIAlertView *facebookLoginAlertView; 18 | 19 | @end 20 | 21 | @implementation LoginViewController 22 | 23 | - (void)viewDidLoad { 24 | [super viewDidLoad]; 25 | } 26 | 27 | - (void)didReceiveMemoryWarning { 28 | [super didReceiveMemoryWarning]; 29 | } 30 | 31 | #pragma mark - Buttons 32 | 33 | - (IBAction)facebookLoginAction:(id)sender { 34 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 35 | [self loginWithFacebook:^(BOOL success, NSError *error) { 36 | if (success) { 37 | [self start]; 38 | } else { 39 | [app showMessage:@"Facebook Login Error. Please try again." withTitle:@"Error"]; 40 | } 41 | }]; 42 | } 43 | 44 | - (IBAction)loginAsGuestAction:(id)sender { 45 | if ([self.delegate respondsToSelector:@selector(didLogInAsGuest)]) 46 | [self.delegate didLogInAsGuest]; 47 | [self start]; 48 | } 49 | 50 | #pragma mark - Navigation 51 | 52 | - (void)start { 53 | [self performSegueWithIdentifier:@"start" sender:self]; 54 | } 55 | 56 | 57 | #pragma mark - Application Level Setup 58 | 59 | + (BOOL)application:(UIApplication *)application 60 | didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 61 | return [[FBSDKApplicationDelegate sharedInstance] application:application 62 | didFinishLaunchingWithOptions:launchOptions]; 63 | } 64 | 65 | + (BOOL)application:(UIApplication *)application openURL:(NSURL *)url 66 | sourceApplication:(NSString *)sourceApplication annotation:(id)annotation { 67 | return [[FBSDKApplicationDelegate sharedInstance] application:application 68 | openURL:url 69 | sourceApplication:sourceApplication 70 | annotation:annotation]; 71 | } 72 | 73 | #pragma mark - Login 74 | 75 | - (void)logout { 76 | if (self.facebookLoginManager) { 77 | [self unobserveFacebookAccessTokenChange]; 78 | [self.facebookLoginManager logOut]; 79 | self.facebookLoginManager = nil; 80 | } 81 | 82 | if ([self.delegate respondsToSelector:@selector(didLogout)]) 83 | [self.delegate didLogout]; 84 | } 85 | 86 | #pragma mark - Facebook 87 | 88 | - (FBSDKLoginManager *)facebookLoginManager { 89 | if (!_facebookLoginManager) 90 | _facebookLoginManager = [[FBSDKLoginManager alloc] init]; 91 | return _facebookLoginManager; 92 | } 93 | 94 | - (void)loginWithFacebook:(void (^)(BOOL success, NSError *error))resultBlock { 95 | [self.facebookLoginManager logInWithReadPermissions:@[@"email"] 96 | fromViewController:self 97 | handler: 98 | ^(FBSDKLoginManagerLoginResult *loginResult, NSError *error) { 99 | if (error || loginResult.isCancelled) { 100 | resultBlock(NO, error); 101 | } else { 102 | [[[FBSDKGraphRequest alloc] initWithGraphPath:@"me" 103 | parameters:@{@"fields": @"name"}] 104 | startWithCompletionHandler: 105 | ^(FBSDKGraphRequestConnection *connection, id result, NSError *error) { 106 | if (!error) { 107 | [self observeFacebookAccessTokenChange]; 108 | [self facebookUserDidLoginWithToken:loginResult.token userInfo:result]; 109 | resultBlock(YES, nil); 110 | } else { 111 | [self.facebookLoginManager logOut]; 112 | resultBlock(NO, error); 113 | } 114 | }]; 115 | } 116 | }]; 117 | } 118 | 119 | - (void)facebookUserDidLoginWithToken:(FBSDKAccessToken *)token userInfo:(NSDictionary *)info { 120 | NSAssert(token, @"Facebook Access Token Data is nil"); 121 | if ([self.delegate respondsToSelector:@selector(didLogInAsFacebookUserId:name:token:)]) 122 | [self.delegate didLogInAsFacebookUserId:token.userID 123 | name:info[@"name"] token:token.tokenString]; 124 | } 125 | 126 | - (void)observeFacebookAccessTokenChange { 127 | [[NSNotificationCenter defaultCenter] removeObserver:self 128 | name:FBSDKAccessTokenDidChangeNotification 129 | object:nil]; 130 | [[NSNotificationCenter defaultCenter] addObserver:self 131 | selector:@selector(facebookAccessTokenChange:) 132 | name:FBSDKAccessTokenDidChangeNotification 133 | object:nil]; 134 | } 135 | 136 | - (void)unobserveFacebookAccessTokenChange { 137 | [[NSNotificationCenter defaultCenter] removeObserver:self 138 | name:FBSDKAccessTokenDidChangeNotification 139 | object:nil]; 140 | } 141 | 142 | - (void)facebookAccessTokenChange:(NSNotification *)notification { 143 | NSString *message = @"Facebook Session is expired. " 144 | "Please login again to review your session."; 145 | self.facebookLoginAlertView = [[UIAlertView alloc] initWithTitle:@"Facebook" 146 | message:message 147 | delegate:self 148 | cancelButtonTitle:@"OK" 149 | otherButtonTitles:nil]; 150 | [self.facebookLoginAlertView show]; 151 | } 152 | 153 | - (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { 154 | if (alertView == self.facebookLoginAlertView) { 155 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 156 | [app logout]; 157 | } 158 | } 159 | 160 | @end 161 | -------------------------------------------------------------------------------- /ToDoLite/MasterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // MasterViewController.h 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/11/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class DetailViewController; 13 | 14 | @interface MasterViewController : UIViewController 15 | 16 | @property (weak, nonatomic) IBOutlet UIBarButtonItem *loginButton; 17 | @property (weak, nonatomic) IBOutlet UITableView *tableView; 18 | @property (strong, nonatomic) DetailViewController *detailViewController; 19 | 20 | @end 21 | 22 | -------------------------------------------------------------------------------- /ToDoLite/MasterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // MasterViewController.m 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/11/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import "MasterViewController.h" 10 | #import "DetailViewController.h" 11 | #import "AppDelegate.h" 12 | #import "Profile.h" 13 | #import "List.h" 14 | 15 | @interface MasterViewController () 16 | 17 | @property CBLDatabase *database; 18 | @property CBLLiveQuery *liveQuery; 19 | @property NSArray *listsResult; 20 | 21 | @end 22 | 23 | @implementation MasterViewController 24 | 25 | - (void)awakeFromNib { 26 | [super awakeFromNib]; 27 | self.title = @"ToDo Lists"; 28 | } 29 | 30 | - (void)viewDidLoad { 31 | [super viewDidLoad]; 32 | [self setup]; 33 | 34 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 35 | self.loginButton.title = app.currentUserId != nil ? @"Logout" : @"Login"; 36 | 37 | [self.tableView reloadData]; 38 | } 39 | 40 | - (void)viewWillAppear:(BOOL)animated { 41 | NSIndexPath *selected = [self.tableView indexPathForSelectedRow]; 42 | if (selected) { 43 | [self.tableView deselectRowAtIndexPath:selected animated:NO]; 44 | } 45 | } 46 | 47 | - (void)didReceiveMemoryWarning { 48 | [super didReceiveMemoryWarning]; 49 | } 50 | 51 | - (void)dealloc { 52 | [self.liveQuery removeObserver:self forKeyPath:@"rows"]; 53 | } 54 | 55 | #pragma mark - Database 56 | 57 | // In this View Controller, we show an example of a Live Query 58 | // and KVO to update the Table View accordingly when data changed. 59 | // See DetailViewController and ShareViewController for 60 | // examples of a Live Query used with the CBLUITableSource api. 61 | - (void)setup { 62 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 63 | self.database = app.database; 64 | 65 | self.liveQuery = [List queryListsInDatabase:self.database].asLiveQuery; 66 | [self.liveQuery addObserver:self forKeyPath:@"rows" options:0 context:nil]; 67 | } 68 | 69 | - (List *)createListWithTitle:(NSString*)title { 70 | List *list = [List modelForNewDocumentInDatabase:self.database]; 71 | list.title = title; 72 | 73 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 74 | NSString *currentUserId = app.currentUserId; 75 | if (currentUserId) { 76 | Profile *owner = [Profile profileInDatabase:self.database forExistingUserId:currentUserId]; 77 | list.owner = owner; 78 | } 79 | 80 | NSError *error; 81 | if (![list save:&error]) { 82 | [app showMessage:@"Cannot create a new list" withTitle:@"Error"]; 83 | return nil; 84 | } 85 | 86 | return list; 87 | } 88 | 89 | #pragma mark - Observers 90 | 91 | - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change 92 | context:(void *)context { 93 | self.listsResult = self.liveQuery.rows.allObjects; 94 | [self.tableView reloadData]; 95 | } 96 | 97 | #pragma mark - Segues 98 | 99 | - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { 100 | if ([[segue identifier] isEqualToString:@"showDetail"]) { 101 | NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow]; 102 | CBLQueryRow *row = [self.listsResult objectAtIndex:indexPath.row]; 103 | List *list = [List modelForDocument:row.document]; 104 | 105 | DetailViewController *controller = [segue destinationViewController]; 106 | controller.list = list; 107 | } 108 | } 109 | 110 | #pragma mark - Buttons 111 | 112 | - (IBAction)addButtonAction:(id)sender { 113 | UIAlertView* alert= [[UIAlertView alloc] initWithTitle:@"New ToDo List" 114 | message:@"Title for new list:" 115 | delegate:self 116 | cancelButtonTitle:@"Cancel" 117 | otherButtonTitles:@"Create", nil]; 118 | alert.alertViewStyle = UIAlertViewStylePlainTextInput; 119 | [alert show]; 120 | } 121 | 122 | - (IBAction)loginButtonAction:(id)sender { 123 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 124 | [app logout]; 125 | } 126 | 127 | #pragma mark - UIAlertViewDelegate 128 | 129 | - (void)alertView:(UIAlertView *)alert didDismissWithButtonIndex:(NSInteger)buttonIndex { 130 | if (buttonIndex > 0) { 131 | NSString* title = [alert textFieldAtIndex:0].text; 132 | if (title.length > 0) { 133 | [self createListWithTitle:title]; 134 | } 135 | } 136 | } 137 | 138 | #pragma mark - Table View Datasource 139 | 140 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { 141 | return self.listsResult.count; 142 | } 143 | 144 | - (UITableViewCell *)tableView:(UITableView *)tableView 145 | cellForRowAtIndexPath:(NSIndexPath *)indexPath { 146 | UITableViewCell* cell = [tableView dequeueReusableCellWithIdentifier:@"List" 147 | forIndexPath:indexPath]; 148 | 149 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 150 | 151 | CBLQueryRow* row = [self.listsResult objectAtIndex:indexPath.row]; 152 | cell.textLabel.text = [row.document propertyForKey:@"title"]; 153 | 154 | return cell; 155 | } 156 | 157 | #pragma mark - Table View Delegate 158 | 159 | - (void)tableView:(UITableView *)tableView 160 | commitEditingStyle:(UITableViewCellEditingStyle)style 161 | forRowAtIndexPath:(NSIndexPath *)indexPath { 162 | if (style == UITableViewCellEditingStyleDelete) { 163 | CBLQueryRow* row = [self.listsResult objectAtIndex:indexPath.row]; 164 | List *list = [List modelForDocument:row.document]; 165 | AppDelegate *app = [[UIApplication sharedApplication] delegate]; 166 | if (!app.currentUserId || [app.currentUserId isEqualToString:list.owner.user_id]) 167 | [list deleteList:nil]; 168 | else 169 | [app showMessage:@"Only the owner can delete the list." withTitle:@"Info"]; 170 | } 171 | } 172 | 173 | 174 | @end 175 | -------------------------------------------------------------------------------- /ToDoLite/NSString+Additions.h: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Additions.h 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/13/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface NSString (Additions) 12 | 13 | - (NSString *)MD5; 14 | 15 | @end 16 | -------------------------------------------------------------------------------- /ToDoLite/NSString+Additions.m: -------------------------------------------------------------------------------- 1 | // 2 | // NSString+Additions.m 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/13/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import "NSString+Additions.h" 10 | #import 11 | 12 | @implementation NSString (Additions) 13 | 14 | - (NSString *)MD5 { 15 | const char *ptr = [self UTF8String]; 16 | 17 | unsigned char buffer[CC_MD5_DIGEST_LENGTH]; 18 | 19 | CC_MD5(ptr, (CC_LONG)[self lengthOfBytesUsingEncoding:NSUTF8StringEncoding], buffer); 20 | 21 | NSMutableString *result = [NSMutableString string]; 22 | for(int i = 0; i < CC_MD5_DIGEST_LENGTH; i++) { 23 | [result appendFormat:@"%02x", buffer[i]]; 24 | } 25 | 26 | return result; 27 | } 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ToDoLite/Profile.h: -------------------------------------------------------------------------------- 1 | // 2 | // Profile.h 3 | // TodoLite7 4 | // 5 | // Created by Chris Anderson on 11/15/13. 6 | // Copyright (c) 2013 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface Profile : CBLModel 12 | 13 | /** Returns a query for all the profiles in a database. */ 14 | + (CBLQuery*) queryProfilesInDatabase: (CBLDatabase*)db; 15 | 16 | + (instancetype) profileInDatabase: (CBLDatabase*)db forExistingUserId: (NSString*)userId; 17 | 18 | + (instancetype) profileInDatabase: (CBLDatabase*)database forNewUserId: (NSString*)userId name: (NSString*)name; 19 | 20 | /** The readwrite full name. */ 21 | @property (readwrite) NSString* name; 22 | 23 | /** The user id. */ 24 | @property (readwrite) NSString* user_id; 25 | 26 | /** The type is "profile". */ 27 | @property (copy, nonatomic) NSString* type; 28 | 29 | @end 30 | -------------------------------------------------------------------------------- /ToDoLite/Profile.m: -------------------------------------------------------------------------------- 1 | // 2 | // Profile.m 3 | // TodoLite7 4 | // 5 | // Created by Chris Anderson on 11/15/13. 6 | // Copyright (c) 2013 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import "Profile.h" 10 | 11 | #define kProfileDocType @"profile" 12 | #define kPrefProfileDocId @"MyProfileDocID" 13 | 14 | @implementation Profile 15 | 16 | @dynamic user_id, name, type; 17 | 18 | // Returns a query for all the profiles in a database. 19 | + (CBLQuery*) queryProfilesInDatabase: (CBLDatabase*)db { 20 | CBLView* view = [db viewNamed: @"profiles"]; 21 | if (!view.mapBlock) { 22 | // Register the map function, the first time we access the view: 23 | [view setMapBlock: MAPBLOCK({ 24 | if ([doc[@"type"] isEqualToString:kProfileDocType]) 25 | emit(doc[@"name"], nil); 26 | }) reduceBlock: nil version: @"1"]; // bump version any time you change the MAPBLOCK body! 27 | } 28 | return [view createQuery]; 29 | } 30 | 31 | + (instancetype) profileInDatabase: (CBLDatabase*)db forExistingUserId: (NSString*)userId { 32 | NSParameterAssert(userId); 33 | NSString* profileDocId = [@"p:" stringByAppendingString:userId]; 34 | CBLDocument *doc; 35 | if (profileDocId.length > 0) 36 | doc = [db existingDocumentWithID: profileDocId]; 37 | return doc ? [Profile modelForDocument: doc] : nil; 38 | } 39 | 40 | + (instancetype) profileInDatabase: (CBLDatabase*)database forNewUserId: (NSString*)userId name: (NSString*)name { 41 | NSParameterAssert(name); 42 | NSParameterAssert(userId); 43 | 44 | CBLDocument* doc = [database documentWithID: [@"p:" stringByAppendingString:userId]]; 45 | Profile* profile = [Profile modelForDocument:doc]; 46 | profile.type = kProfileDocType; 47 | profile.name = name; 48 | profile.user_id = userId; 49 | return profile; 50 | } 51 | 52 | - (NSString*) description { 53 | return [NSString stringWithFormat: @"%@[%@ '%@']", self.class, self.document.abbreviatedID, self.user_id]; 54 | } 55 | 56 | @end 57 | -------------------------------------------------------------------------------- /ToDoLite/RoundedButton.h: -------------------------------------------------------------------------------- 1 | // 2 | // RoundedButton.h 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 4/8/14. 6 | // Copyright (c) 2014 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface RoundedButton : UIButton 12 | 13 | @end 14 | -------------------------------------------------------------------------------- /ToDoLite/RoundedButton.m: -------------------------------------------------------------------------------- 1 | // 2 | // RoundedButton.m 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 4/8/14. 6 | // Copyright (c) 2014 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import "RoundedButton.h" 10 | 11 | @implementation RoundedButton 12 | 13 | - (id)initWithFrame:(CGRect)frame { 14 | self = [super initWithFrame:frame]; 15 | if (self) { 16 | 17 | } 18 | return self; 19 | } 20 | 21 | - (void)setFrame:(CGRect)frame { 22 | [super setFrame:frame]; 23 | 24 | if (!self.layer.mask) { 25 | [self addCircleMaskToBounds:frame]; 26 | } 27 | } 28 | 29 | - (void)addCircleMaskToBounds:(CGRect)maskBounds { 30 | CAShapeLayer *maskLayer = [[CAShapeLayer alloc] init]; 31 | 32 | maskLayer.bounds = maskBounds; 33 | CGPathRef path = CGPathCreateWithEllipseInRect(maskBounds, NULL); 34 | maskLayer.path = path; 35 | CGPathRelease(path); 36 | maskLayer.position = CGPointMake(maskBounds.size.width/2, maskBounds.size.height/2); 37 | maskLayer.shouldRasterize = YES; 38 | maskLayer.rasterizationScale = [UIScreen mainScreen].scale; 39 | 40 | self.layer.mask = maskLayer; 41 | } 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /ToDoLite/ShareViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ShareViewController.h 3 | // TodoLite7 4 | // 5 | // Created by Chris Anderson on 11/14/13. 6 | // Copyright (c) 2013 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @class List; 13 | 14 | @interface ShareViewController : UIViewController 15 | 16 | @property (strong, nonatomic) IBOutlet CBLUITableSource *dataSource; 17 | @property (weak, nonatomic) IBOutlet UITableView *tableView; 18 | @property (strong, nonatomic) List *list; 19 | 20 | @end 21 | -------------------------------------------------------------------------------- /ToDoLite/ShareViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // ShareViewController.m 3 | // TodoLite7 4 | // 5 | // Created by Chris Anderson on 11/14/13. 6 | // Copyright (c) 2013 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import "AppDelegate.h" 10 | #import "ShareViewController.h" 11 | #import "Profile.h" 12 | #import "List.h" 13 | 14 | @interface ShareViewController () { 15 | CBLDatabase *database; 16 | AppDelegate *app; 17 | NSString* myDocId; 18 | } 19 | 20 | @end 21 | 22 | @implementation ShareViewController 23 | 24 | - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 25 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 26 | if (self) { 27 | // Custom initialization 28 | } 29 | return self; 30 | } 31 | 32 | - (void)viewDidLoad { 33 | [super viewDidLoad]; 34 | app = [[UIApplication sharedApplication] delegate]; 35 | database = app.database; 36 | myDocId = [@"p:" stringByAppendingString:app.currentUserId]; 37 | 38 | [self configureView]; 39 | } 40 | 41 | - (void)didReceiveMemoryWarning { 42 | [super didReceiveMemoryWarning]; 43 | } 44 | 45 | - (void)configureView { 46 | _dataSource.query = [Profile queryProfilesInDatabase:database].asLiveQuery; 47 | _dataSource.labelProperty = @"name"; // Document property to display in the cell label 48 | _dataSource.deletionAllowed = NO; 49 | } 50 | 51 | #pragma mark - Properties 52 | 53 | - (void)setList:(List *)newList { 54 | if (_list != newList) { 55 | _list = newList; 56 | [self.tableView reloadData]; 57 | } 58 | } 59 | 60 | #pragma mark - TableView 61 | 62 | // Customizes the appearance of table view cells. 63 | - (void)couchTableSource:(CBLUITableSource*)source willUseCell:(UITableViewCell*)cell forRow:(CBLQueryRow*)row { 64 | NSString *personId = row.document.documentID; 65 | 66 | // if the person's id is in the list of members, or is the owner we are happy. 67 | bool member = NO; 68 | if ([myDocId isEqualToString:personId]) { 69 | member = YES; 70 | } else { 71 | NSMutableSet *intersection = [NSMutableSet setWithArray:_list.members]; 72 | [intersection intersectSet:[NSSet setWithObject:personId]]; 73 | if ([intersection count] > 0) { 74 | member = YES; 75 | } 76 | } 77 | 78 | if (member) { 79 | cell.accessoryType = UITableViewCellAccessoryCheckmark; 80 | } else { 81 | cell.accessoryType = UITableViewCellAccessoryNone; 82 | } 83 | } 84 | 85 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { 86 | CBLQueryRow *row = [self.dataSource rowAtIndex:indexPath.row]; 87 | NSString *toggleMemberId = row.document.documentID; 88 | NSArray *members = _list.members; 89 | if (!members) members = @[]; 90 | 91 | NSUInteger index = [members indexOfObject:toggleMemberId]; 92 | if (index == NSNotFound) { 93 | _list.members = [members arrayByAddingObject:toggleMemberId]; 94 | } else { 95 | _list.members = [members filteredArrayUsingPredicate: 96 | [NSPredicate predicateWithFormat:@"SELF != %@" argumentArray:@[toggleMemberId]]]; 97 | } 98 | 99 | // Save changes: 100 | NSError* error; 101 | if ([_list save: &error]) { 102 | [self.tableView reloadData]; 103 | } 104 | } 105 | 106 | @end 107 | -------------------------------------------------------------------------------- /ToDoLite/Task.h: -------------------------------------------------------------------------------- 1 | // 2 | // Task.h 3 | // ToDo Lite 4 | // 5 | // Created by Jens Alfke on 8/22/13. 6 | // 7 | // 8 | 9 | #import "Titled.h" 10 | 11 | @class List; 12 | 13 | /** Model object for a task item. (See Titled for inherited properties!) */ 14 | @interface Task : Titled 15 | 16 | /** Is the task checked off / completed? */ 17 | @property bool checked; 18 | 19 | /** The List this item belongs to. */ 20 | @property (weak) List* list_id; 21 | 22 | /** Attach an image to the task */ 23 | - (void) setImage: (NSData*)image contentType: (NSString*)contentType; 24 | 25 | - (BOOL) deleteTask: (NSError**)error; 26 | 27 | @end 28 | -------------------------------------------------------------------------------- /ToDoLite/Task.m: -------------------------------------------------------------------------------- 1 | // 2 | // Task.m 3 | // ToDo Lite 4 | // 5 | // Created by Jens Alfke on 8/22/13. 6 | // 7 | // 8 | 9 | #import "Task.h" 10 | #import "List.h" 11 | 12 | #define kTaskDocType @"task" 13 | #define kTaskImageName @"image" 14 | 15 | @implementation Task 16 | 17 | @dynamic checked, list_id; 18 | 19 | + (NSString*) docType { 20 | return kTaskDocType; 21 | } 22 | 23 | - (void) setImage: (NSData*)image contentType: (NSString*)contentType { 24 | [self setAttachmentNamed:kTaskImageName withContentType:contentType content:image]; 25 | } 26 | 27 | - (BOOL) deleteTask: (NSError**)error { 28 | return [self deleteDocument: error]; 29 | } 30 | 31 | @end 32 | -------------------------------------------------------------------------------- /ToDoLite/TaskTableViewCell.h: -------------------------------------------------------------------------------- 1 | // 2 | // TaskTableViewCell.h 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 4/8/14. 6 | // Copyright (c) 2014 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class Task; 12 | 13 | @protocol TaskTableViewCellDelegate; 14 | 15 | @interface TaskTableViewCell : UITableViewCell 16 | 17 | @property (weak, nonatomic) IBOutlet UIButton *image; 18 | @property (weak, nonatomic) IBOutlet UILabel *name; 19 | 20 | @property (strong, nonatomic) Task *task; 21 | @property (weak, nonatomic) id delegate; 22 | 23 | - (IBAction)imageButtonAction:(id)sender; 24 | 25 | @end 26 | 27 | @protocol TaskTableViewCellDelegate 28 | - (void)didSelectImageButton:(UIButton *)imageButton ofTask:(Task *)task; 29 | @end 30 | -------------------------------------------------------------------------------- /ToDoLite/TaskTableViewCell.m: -------------------------------------------------------------------------------- 1 | // 2 | // TaskTableViewCell.m 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 4/8/14. 6 | // Copyright (c) 2014 Chris Anderson. All rights reserved. 7 | // 8 | 9 | #import "TaskTableViewCell.h" 10 | #import "Task.h" 11 | 12 | @implementation TaskTableViewCell 13 | 14 | - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier { 15 | self = [super initWithStyle:style reuseIdentifier:reuseIdentifier]; 16 | if (self) { 17 | 18 | } 19 | return self; 20 | } 21 | 22 | - (void)awakeFromNib { 23 | 24 | } 25 | 26 | - (void)setSelected:(BOOL)selected animated:(BOOL)animated { 27 | [super setSelected:selected animated:animated]; 28 | } 29 | 30 | - (void)setTask:(Task *)task { 31 | _task = task; 32 | 33 | self.name.text = task.title; 34 | 35 | bool checked = task.checked; 36 | self.name.textColor = checked ? [UIColor grayColor] : [UIColor blackColor]; 37 | if (checked) { 38 | self.accessoryType = UITableViewCellAccessoryCheckmark; 39 | } else { 40 | self.accessoryType = UITableViewCellAccessoryNone; 41 | } 42 | 43 | NSArray *attachments = [task attachmentNames]; 44 | if ([attachments count] > 0) { 45 | CBLAttachment *attachment = [task attachmentNamed:[attachments objectAtIndex:0]]; 46 | UIImage *attachedImage = [UIImage imageWithData:attachment.content]; 47 | [self.image setImage:attachedImage forState:UIControlStateNormal]; 48 | } else { 49 | [self.image setImage:[UIImage imageNamed:@"Camera-Light"] forState:UIControlStateNormal]; 50 | } 51 | } 52 | 53 | - (IBAction)imageButtonAction:(id)sender { 54 | if ([self.delegate respondsToSelector:@selector(didSelectImageButton:ofTask:)]) { 55 | [self.delegate didSelectImageButton:(UIButton *)sender ofTask:self.task]; 56 | } 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /ToDoLite/Titled.h: -------------------------------------------------------------------------------- 1 | // 2 | // Titled.h 3 | // ToDoLite 4 | // 5 | // Created by Jens Alfke on 8/26/13. 6 | // 7 | // 8 | 9 | #import 10 | 11 | /** Abstract superclass of List and Task. A generic model object with a title and creation date. */ 12 | @interface Titled : CBLModel 13 | 14 | /** The "type" property value for documents that belong to this class. Abstract. */ 15 | + (NSString*) docType; 16 | 17 | /** The object's user-visible title. */ 18 | @property (copy) NSString* title; 19 | 20 | /** When the object was created. */ 21 | @property (readonly) NSDate* created_at; 22 | 23 | @end 24 | -------------------------------------------------------------------------------- /ToDoLite/Titled.m: -------------------------------------------------------------------------------- 1 | // 2 | // Titled.m 3 | // ToDoLite 4 | // 5 | // Created by Jens Alfke on 8/26/13. 6 | // 7 | // 8 | 9 | #import "Titled.h" 10 | 11 | @interface Titled () 12 | @property (readwrite) NSDate* created_at; // internally make it settable 13 | @end 14 | 15 | @implementation Titled 16 | 17 | // These properties will be hooked up at runtime by CBLModel to map to the document properties. 18 | @dynamic title, created_at; 19 | 20 | // Subclasses must override this to return the value of their documents' "type" property. 21 | + (NSString*) docType { 22 | NSAssert(NO, @"Unimplemented method +[%@ docType]", [self class]); 23 | return nil; 24 | } 25 | 26 | - (void)awakeFromInitializer { 27 | self.type = [[self class] docType]; 28 | if (!self.created_at) 29 | self.created_at = [NSDate date]; 30 | } 31 | 32 | - (NSString*) description { 33 | return [NSString stringWithFormat: @"%@[%@ '%@']", 34 | self.class, self.document.abbreviatedID, self.title]; 35 | } 36 | 37 | @end 38 | -------------------------------------------------------------------------------- /ToDoLite/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // ToDoLite 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/11/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /ToDoLiteTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | com.couchbase.$(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 | -------------------------------------------------------------------------------- /ToDoLiteTests/ToDoLiteTests.m: -------------------------------------------------------------------------------- 1 | // 2 | // ToDoLiteTests.m 3 | // ToDoLiteTests 4 | // 5 | // Created by Pasin Suriyentrakorn on 10/11/14. 6 | // Copyright (c) 2014 Pasin Suriyentrakorn. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | @interface ToDoLiteTests : XCTestCase 13 | 14 | @end 15 | 16 | @implementation ToDoLiteTests 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 | -------------------------------------------------------------------------------- /sync-gateway-config.json: -------------------------------------------------------------------------------- 1 | { 2 | "log": ["*"], 3 | "facebook": { "register": true }, 4 | "databases": { 5 | "todolite": { 6 | "server": "walrus:", 7 | "users": { 8 | "GUEST": {"disabled": true} 9 | }, 10 | "sync": ` 11 | function(doc, oldDoc) { 12 | // NOTE this function is the same across the iOS, Android, and PhoneGap versions. 13 | if (doc.type == "task") { 14 | if (!doc.list_id) { 15 | throw({forbidden : "Items must have a list_id."}); 16 | } 17 | channel("list-"+doc.list_id); 18 | } else if (doc.type == "list" || (doc._deleted && oldDoc && oldDoc.type == "list")) { 19 | // Make sure that the owner propery exists: 20 | var owner = oldDoc ? oldDoc.owner : doc.owner; 21 | if (!owner) { 22 | throw({forbidden : "List must have an owner."}); 23 | } 24 | 25 | // Make sure that only the owner of the list can update the list: 26 | if (doc.owner && owner != doc.owner) { 27 | throw({forbidden : "Cannot change owner for lists."}); 28 | } 29 | 30 | var ownerName = owner.substring(owner.indexOf(":")+1); 31 | requireUser(ownerName); 32 | 33 | var ch = "list-"+doc._id; 34 | if (!doc._deleted) { 35 | channel(ch); 36 | } 37 | 38 | // Grant owner access to the channel: 39 | access(ownerName, ch); 40 | 41 | // Grant shared members access to the channel: 42 | var members = !doc._deleted ? doc.members : oldDoc.members; 43 | if (Array.isArray(members)) { 44 | var memberNames = []; 45 | for (var i = members.length - 1; i >= 0; i--) { 46 | memberNames.push(members[i].substring(members[i].indexOf(":")+1)) 47 | }; 48 | access(memberNames, ch); 49 | } 50 | } else if (doc.type == "profile") { 51 | channel("profiles"); 52 | var user = doc._id.substring(doc._id.indexOf(":")+1); 53 | if (user !== doc.user_id) { 54 | throw({forbidden : "Profile user_id must match docid."}); 55 | } 56 | requireUser(user); 57 | access(user, "profiles"); 58 | } 59 | } 60 | ` 61 | } 62 | } 63 | } 64 | --------------------------------------------------------------------------------