From 1184425df3d4c346fc62292cd3fa2dcd21060244 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Tue, 19 Nov 2013 18:21:32 +0100 Subject: [PATCH 01/64] Use case insensitive sorting for blogs list --- WordPress/Classes/BlogListViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index a974f6571ec3..987b27671802 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -263,7 +263,7 @@ - (NSFetchedResultsController *)resultsController { NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[WordPressAppDelegate sharedWordPressApplicationDelegate] managedObjectContext]; [fetchRequest setEntity:[NSEntityDescription entityForName:@"Blog" inManagedObjectContext:moc]]; - [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES]]]; + [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]]; // For some reasons, the cache sometimes gets corrupted // Since we don't really use sections we skip the cache here From eb70228fcbd5e5084990e9fbb4b8dc200aba2e03 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Tue, 19 Nov 2013 18:38:54 +0100 Subject: [PATCH 02/64] Present login screen on sign out. If settings or other modal is present, dismiss it and force the Login screen --- WordPress/Classes/WordPressAppDelegate.m | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index bd9f402b6303..abd0b606a562 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -42,7 +42,7 @@ - (void)runStats; - (void)cleanUnusedMediaFileFromTmpDir; - (void)customizeAppearance; - (void)toggleExtraDebuggingIfNeeded; -- (void)handleLogoutOrBlogsChangedNotification:(NSNotification *)notification; +- (void)handleDefaultAccountChangedNotification:(NSNotification *)notification; @end @@ -274,7 +274,11 @@ - (void)showWelcomeScreenIfNeeded { aNavigationController.navigationBar.translucent = NO; aNavigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; aNavigationController.modalPresentationStyle = UIModalPresentationFormSheet; - + + UIViewController *presenter = window.rootViewController; + if (presenter.presentedViewController) { + [presenter dismissViewControllerAnimated:NO completion:nil]; + } [window.rootViewController presentViewController:aNavigationController animated:NO completion:nil]; } } @@ -1144,8 +1148,7 @@ - (void)cleanUnusedMediaFileFromTmpDir { - (void)toggleExtraDebuggingIfNeeded { if (!_listeningForBlogChanges) { _listeningForBlogChanges = YES; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleLogoutOrBlogsChangedNotification:) name:BlogChangedNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleLogoutOrBlogsChangedNotification:) name:WordPressComApiDidLogoutNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDefaultAccountChangedNotification:) name:WPAccountDefaultWordPressComAccountChangedNotification object:nil]; } int num_blogs = [Blog countWithContext:[self managedObjectContext]]; @@ -1179,8 +1182,9 @@ - (void)toggleExtraDebuggingIfNeeded { } } -- (void)handleLogoutOrBlogsChangedNotification:(NSNotification *)notification { +- (void)handleDefaultAccountChangedNotification:(NSNotification *)notification { [self toggleExtraDebuggingIfNeeded]; + [self showWelcomeScreenIfNeeded]; } - (void)showNotificationsTab { From 0bfa1c37d2cc5e1a43bb418679298a0fbfe73a47 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Tue, 19 Nov 2013 18:40:48 +0100 Subject: [PATCH 03/64] Removed some obsolete code --- WordPress/Classes/Blog.h | 2 -- WordPress/Classes/Blog.m | 9 --------- WordPress/Classes/WordPressAppDelegate.m | 8 -------- 3 files changed, 19 deletions(-) diff --git a/WordPress/Classes/Blog.h b/WordPress/Classes/Blog.h index 31beb8209f90..c4521794b24a 100644 --- a/WordPress/Classes/Blog.h +++ b/WordPress/Classes/Blog.h @@ -12,8 +12,6 @@ #import "Reachability.h" -#define BlogChangedNotification @"BlogChangedNotification" - @class WPAccount; @interface Blog : NSManagedObject diff --git a/WordPress/Classes/Blog.m b/WordPress/Classes/Blog.m index 0120a93564b9..441b864d3d78 100644 --- a/WordPress/Classes/Blog.m +++ b/WordPress/Classes/Blog.m @@ -290,15 +290,6 @@ - (void)dataSaveWithContext:(NSManagedObjectContext*)context { } }]; } - // Is this needed? -// dispatch_block_t notify = ^{ -// [[NSNotificationCenter defaultCenter] postNotificationName:BlogChangedNotification object:nil]; -// }; -// if (![NSThread isMainThread]) { -// dispatch_async(dispatch_get_main_queue(), notify); -// } else { -// notify(); -// } }]; } diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index abd0b606a562..50c572041e44 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -36,14 +36,6 @@ @interface WordPressAppDelegate (Private) -- (void)setAppBadge; -- (void)checkIfStatsShouldRun; -- (void)runStats; -- (void)cleanUnusedMediaFileFromTmpDir; -- (void)customizeAppearance; -- (void)toggleExtraDebuggingIfNeeded; -- (void)handleDefaultAccountChangedNotification:(NSNotification *)notification; - @end int ddLogLevel = LOG_LEVEL_INFO; From d5db5dc22a7a0aac51b4756d1320d4d7a79afe2c Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Tue, 19 Nov 2013 18:42:26 +0100 Subject: [PATCH 04/64] =?UTF-8?q?Don=E2=80=99t=20refresh=20tokens=20if=20t?= =?UTF-8?q?hey=20are=20invalid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If users revoke access from the web, the app should respect that --- WordPress/Classes/WPError.m | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/WordPress/Classes/WPError.m b/WordPress/Classes/WPError.m index 028d972d1df2..4ca7b0a4329a 100644 --- a/WordPress/Classes/WPError.m +++ b/WordPress/Classes/WPError.m @@ -65,12 +65,7 @@ + (void)showAlertWithError:(NSError *)error title:(NSString *)title { } else if ([error.domain isEqualToString:WordPressComApiErrorDomain]) { DDLogError(@"wp.com API error: %@: %@", [error.userInfo objectForKey:WordPressComApiErrorCodeKey], [error localizedDescription]); if (error.code == WordPressComApiErrorInvalidToken || error.code == WordPressComApiErrorAuthorizationRequired) { - if ([[WPAccount defaultWordPressComAccount] password] == nil) { - [WPcomLoginViewController presentLoginScreen]; - } - [[WordPressComApi sharedApi] refreshTokenWithSuccess:nil failure:^(NSError *error) { - [WPcomLoginViewController presentLoginScreen]; - }]; + [WPcomLoginViewController presentLoginScreen]; return; } } From dbd47cb4c9170b76313cec374c0d65bb62d08cc9 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Tue, 19 Nov 2013 19:11:14 +0100 Subject: [PATCH 05/64] Add all user's blog by default Bigger commit than I'd like, but here's the summary: - Addded new WordPressComOAuthClient to handle OAuth2 - Skip the add blogs screen on wp.com and just add them all - Prefetch reader/notifications after successful login - Deprecate `[WordPressComApi sharedApi]` and return the default account's API instead. --- WordPress/Classes/Blog+Jetpack.m | 2 +- WordPress/Classes/LoginViewController.m | 53 +++++++----- WordPress/Classes/WPAccount.h | 23 ++++- WordPress/Classes/WPAccount.m | 82 +++++++++++++++++- WordPress/Classes/WPcomLoginViewController.m | 2 +- WordPress/WordPress.xcodeproj/project.pbxproj | 6 ++ WordPress/WordPressApi/WordPressComApi.h | 3 +- WordPress/WordPressApi/WordPressComApi.m | 52 +++--------- .../WordPressApi/WordPressComOAuthClient.h | 41 +++++++++ .../WordPressApi/WordPressComOAuthClient.m | 84 +++++++++++++++++++ 10 files changed, 280 insertions(+), 68 deletions(-) create mode 100644 WordPress/WordPressApi/WordPressComOAuthClient.h create mode 100644 WordPress/WordPressApi/WordPressComOAuthClient.m diff --git a/WordPress/Classes/Blog+Jetpack.m b/WordPress/Classes/Blog+Jetpack.m index 7d17e390683e..5f00c13d33ed 100644 --- a/WordPress/Classes/Blog+Jetpack.m +++ b/WordPress/Classes/Blog+Jetpack.m @@ -129,7 +129,7 @@ - (void)removeJetpackCredentials { - (void)saveJetpackUsername:(NSString *)username andPassword:(NSString *)password { NSAssert(![self isWPcom], @"Blog+Jetpack doesn't support WordPress.com blogs"); - WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username andPassword:password]; + WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:nil]; self.jetpackAccount = account; } diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index d7910b6d85a2..c7965122e5c3 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -19,7 +19,7 @@ #import "WPNUXPrimaryButton.h" #import "WPNUXSecondaryButton.h" #import "WPWalkthroughTextField.h" -#import "WordPressComApi.h" +#import "WordPressComOAuthClient.h" #import "WPWebViewController.h" #import "Blog+Jetpack.h" #import "LoginCompletedWalkthroughViewController.h" @@ -29,6 +29,8 @@ #import "ReachabilityUtils.h" #import "WPNUXUtility.h" #import "WPAccount.h" +#import "ReaderPost.h" +#import "Note.h" @interface LoginViewController () < UITextFieldDelegate> { @@ -674,24 +676,17 @@ - (void)signInForWPComForUsername:(NSString *)username andPassword:(NSString *)p [SVProgressHUD showWithStatus:NSLocalizedString(@"Connecting to WordPress.com", nil) maskType:SVProgressHUDMaskTypeBlack]; - void (^loginSuccessBlock)(void) = ^{ - [SVProgressHUD dismiss]; - _userIsDotCom = YES; - [self showAddUsersBlogsForWPCom]; - }; - - void (^loginFailBlock)(NSError *) = ^(NSError *error){ - // User shouldn't get here because the getOptions call should fail, but in the unlikely case they do throw up an error message. - [SVProgressHUD dismiss]; - DDLogError(@"Login failed with username %@ : %@", username, error); - [self displayGenericErrorMessage:NSLocalizedString(@"Please try entering your login details again.", nil)]; - }; - - [[WordPressComApi sharedApi] signInWithUsername:username - password:password - success:loginSuccessBlock - failure:loginFailBlock]; - + WordPressComOAuthClient *client = [WordPressComOAuthClient client]; + [client authenticateWithUsername:username + password:password + success:^(NSString *authToken) { + [SVProgressHUD dismiss]; + _userIsDotCom = YES; + [self createWordPressComAccountForUsername:username password:password authToken:authToken]; + } failure:^(NSError *error) { + [SVProgressHUD dismiss]; + [self displayRemoteError:error]; + }]; } - (void)signInForSelfHostedForUsername:(NSString *)username password:(NSString *)password options:(NSDictionary *)options andApi:(WordPressXMLRPCApi *)api @@ -702,11 +697,27 @@ - (void)signInForSelfHostedForUsername:(NSString *)username password:(NSString * [api getBlogsWithSuccess:^(NSArray *blogs) { _blogs = blogs; - [self handleGetBlogsSuccess:[api.xmlrpc absoluteString]]; + + } failure:^(NSError *error) { + [SVProgressHUD dismiss]; + [self displayRemoteError:error]; + }]; +} + +- (void)createWordPressComAccountForUsername:(NSString *)username password:(NSString *)password authToken:(NSString *)authToken +{ + [SVProgressHUD showWithStatus:NSLocalizedString(@"Getting account information", @"") maskType:SVProgressHUDMaskTypeBlack]; + WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:authToken]; + [account syncBlogsWithSuccess:^{ + [SVProgressHUD dismiss]; + [self.navigationController popViewControllerAnimated:NO]; + [self showCompletionWalkthrough]; } failure:^(NSError *error) { [SVProgressHUD dismiss]; [self displayRemoteError:error]; }]; + [ReaderPost fetchPostsWithCompletionHandler:nil]; + [account.restApi getNotificationsSince:nil success:nil failure:nil]; } - (void)handleGuessXMLRPCURLFailure:(NSError *)error @@ -844,7 +855,7 @@ - (void)createBlogWithXmlRpc:(NSString *)xmlRPCUrl andBlogDetails:(NSDictionary - (WPAccount *)createAccountWithUsername:(NSString *)username andPassword:(NSString *)password isWPCom:(BOOL)isWPCom xmlRPCUrl:(NSString *)xmlRPCUrl { WPAccount *account; if (isWPCom) { - account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username andPassword:password]; + account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:nil]; } else { account = [WPAccount createOrUpdateSelfHostedAccountWithXmlrpc:xmlRPCUrl username:username andPassword:password]; } diff --git a/WordPress/Classes/WPAccount.h b/WordPress/Classes/WPAccount.h index 4d32e227af92..06860da48f42 100644 --- a/WordPress/Classes/WPAccount.h +++ b/WordPress/Classes/WPAccount.h @@ -9,6 +9,10 @@ #import #import +#import + +#import "WordPressComApi.h" + @class Blog; extern NSString * const WPAccountDefaultWordPressComAccountChangedNotification; @@ -75,9 +79,10 @@ extern NSString * const WPAccountDefaultWordPressComAccountChangedNotification; @param username the WordPress.com account's username @param password the WordPress.com account's password + @param authToken the OAuth2 token returned by signIntoWordPressDotComWithUsername:password:success:failure: @return a WordPress.com `WPAccount` object for the given `username` */ -+ (WPAccount *)createOrUpdateWordPressComAccountWithUsername:(NSString *)username andPassword:(NSString *)password; ++ (WPAccount *)createOrUpdateWordPressComAccountWithUsername:(NSString *)username password:(NSString *)password authToken:(NSString *)authToken; /** Creates a new self hosted account or updates the password if there is a matching account @@ -105,6 +110,22 @@ extern NSString * const WPAccountDefaultWordPressComAccountChangedNotification; */ - (Blog *)findOrCreateBlogFromDictionary:(NSDictionary *)blogInfo withContext:(NSManagedObjectContext*)context; +- (void)syncBlogsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; + +///------------------ +/// @name API Helpers +///------------------ + +/** + A WordPressComApi object if the account is a WordPress.com account. Otherwise, it returns `nil` + */ +@property (nonatomic, readonly) WordPressComApi *restApi; + +/** + A WordPressXMLRPCApi object configured for the XML-RPC endpoint + */ +@property (nonatomic, readonly) WordPressXMLRPCApi *xmlrpcApi; + @end @interface WPAccount (CoreDataGeneratedAccessors) diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index 9dafca024685..56fdf9aba2c7 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -15,6 +15,7 @@ static NSString * const DefaultDotcomAccountDefaultsKey = @"AccountDefaultDotcom"; static NSString * const DotcomXmlrpcKey = @"https://wordpress.com/xmlrpc.php"; +static NSString * const OauthTokenServiceName = @"public-api.wordpress.com"; static WPAccount *__defaultDotcomAccount = nil; NSString * const WPAccountDefaultWordPressComAccountChangedNotification = @"WPAccountDefaultWordPressComAccountChangedNotification"; @@ -22,10 +23,14 @@ @interface WPAccount () @property (nonatomic, retain) NSString *xmlrpc; @property (nonatomic, retain) NSString *username; +@property (nonatomic, retain) NSString *authToken; @property (nonatomic) BOOL isWpcom; @end -@implementation WPAccount +@implementation WPAccount { + WordPressComApi *_restApi; + WordPressXMLRPCApi *_xmlrpcApi; +} @dynamic xmlrpc; @dynamic username; @@ -84,7 +89,9 @@ + (void)removeDefaultWordPressComAccount { - (void)prepareForDeletion { // Invoked automatically by the Core Data framework when the receiver is about to be deleted. if (__defaultDotcomAccount == self) { - [[WordPressComApi sharedApi] cancelAllHTTPOperationsWithMethod:nil path:nil]; + [[self restApi] cancelAllHTTPOperationsWithMethod:nil path:nil]; + // FIXME: this is temporary until we move all the cleanup out of WordPressComApi + [[self restApi] signOut]; __defaultDotcomAccount = nil; [[NSUserDefaults standardUserDefaults] removeObjectForKey:DefaultDotcomAccountDefaultsKey]; [[NSNotificationCenter defaultCenter] postNotificationName:WPAccountDefaultWordPressComAccountChangedNotification object:nil]; @@ -93,9 +100,10 @@ - (void)prepareForDeletion { #pragma mark - Account creation -+ (WPAccount *)createOrUpdateWordPressComAccountWithUsername:(NSString *)username andPassword:(NSString *)password { ++ (WPAccount *)createOrUpdateWordPressComAccountWithUsername:(NSString *)username password:(NSString *)password authToken:(NSString *)authToken { WPAccount *account = [self createOrUpdateSelfHostedAccountWithXmlrpc:DotcomXmlrpcKey username:username andPassword:password]; account.isWpcom = YES; + account.authToken = authToken; if (__defaultDotcomAccount == nil) { [self setDefaultWordPressComAccount:account]; } @@ -156,6 +164,31 @@ - (Blog *)findOrCreateBlogFromDictionary:(NSDictionary *)blogInfo withContext:(N return blog; } +- (void)syncBlogsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { + [self.xmlrpcApi getBlogsWithSuccess:^(NSArray *blogs) { + [self mergeBlogs:blogs withCompletion:success]; + } failure:failure]; +} + +- (void)mergeBlogs:(NSArray *)blogs withCompletion:(void (^)())completion { + NSManagedObjectContext *backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; + backgroundMOC.parentContext = self.managedObjectContext; + + NSManagedObjectID *accountID = self.objectID; + [backgroundMOC performBlock:^{ + WPAccount *account = (WPAccount *)[backgroundMOC objectWithID:accountID]; + for (NSDictionary *blog in blogs) { + [account findOrCreateBlogFromDictionary:blog withContext:backgroundMOC]; + } + NSError *error; + if (![backgroundMOC save:&error]) { + DDLogError(@"Unresolved core data save error: %@", error); + } + + dispatch_async(dispatch_get_main_queue(), completion); + }]; +} + #pragma mark - Custom accessors - (NSString *)password { @@ -169,7 +202,50 @@ - (void)setPassword:(NSString *)password { forServiceName:self.xmlrpc updateExisting:YES error:nil]; + } else { + [SFHFKeychainUtils deleteItemForUsername:self.username + andServiceName:self.xmlrpc + error:nil]; + } +} + +- (NSString *)authToken { + return [SFHFKeychainUtils getPasswordForUsername:self.username andServiceName:OauthTokenServiceName error:nil]; +} + +- (void)setAuthToken:(NSString *)authToken { + if (authToken) { + [SFHFKeychainUtils storeUsername:self.username + andPassword:authToken + forServiceName:OauthTokenServiceName + updateExisting:YES + error:nil]; + } else { + [SFHFKeychainUtils deleteItemForUsername:self.username + andServiceName:OauthTokenServiceName + error:nil]; + } +} + +#pragma mark - API Helpers + +- (WordPressComApi *)restApi +{ + if (!self.isWpcom) { + return nil; + } + + if (!_restApi) { + _restApi = [[WordPressComApi alloc] initWithOAuthToken:self.authToken]; + } + return _restApi; +} + +- (WordPressXMLRPCApi *)xmlrpcApi { + if (!_xmlrpcApi) { + _xmlrpcApi = [WordPressXMLRPCApi apiWithXMLRPCEndpoint:[NSURL URLWithString:self.xmlrpc] username:self.username password:self.password]; } + return _xmlrpcApi; } @end diff --git a/WordPress/Classes/WPcomLoginViewController.m b/WordPress/Classes/WPcomLoginViewController.m index 6db8f0657fa0..6d4c1fa871b2 100644 --- a/WordPress/Classes/WPcomLoginViewController.m +++ b/WordPress/Classes/WPcomLoginViewController.m @@ -342,7 +342,7 @@ - (void)signIn:(id)sender { [self.wpComApi signInWithUsername:username password:password success:^{ - WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username andPassword:password]; + WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:nil]; [WPAccount setDefaultWordPressComAccount:account]; [loginController.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:1]] withRowAnimation:UITableViewRowAnimationNone]; if (loginController.delegate) { diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 134980fe2046..3a13e4153d9c 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -847,6 +847,7 @@ E15618FF16DBA983006532C4 /* xmlrpc-response-newpost.xml in Resources */ = {isa = PBXBuildFile; fileRef = E15618FE16DBA983006532C4 /* xmlrpc-response-newpost.xml */; }; E156190116DBABDE006532C4 /* xmlrpc-response-getpost.xml in Resources */ = {isa = PBXBuildFile; fileRef = E156190016DBABDE006532C4 /* xmlrpc-response-getpost.xml */; }; E159D1051309AB0D00F498E2 /* MigrateBlogsFromFiles.m in Sources */ = {isa = PBXBuildFile; fileRef = E159D1041309AB0D00F498E2 /* MigrateBlogsFromFiles.m */; }; + E1634519183B733B005E967F /* WordPressComOAuthClient.m in Sources */ = {isa = PBXBuildFile; fileRef = E1634518183B733B005E967F /* WordPressComOAuthClient.m */; }; E16A0C3212E769A10049EA80 /* table_sep.png in Resources */ = {isa = PBXBuildFile; fileRef = E16A0C3012E769A10049EA80 /* table_sep.png */; }; E16A0C3312E769A10049EA80 /* table_sep@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E16A0C3112E769A10049EA80 /* table_sep@2x.png */; }; E16AB92C14D978240047A2E5 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E16AB92B14D978240047A2E5 /* SenTestingKit.framework */; }; @@ -2028,6 +2029,8 @@ E156190016DBABDE006532C4 /* xmlrpc-response-getpost.xml */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xml; path = "xmlrpc-response-getpost.xml"; sourceTree = ""; }; E159D1031309AB0D00F498E2 /* MigrateBlogsFromFiles.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = MigrateBlogsFromFiles.h; sourceTree = ""; }; E159D1041309AB0D00F498E2 /* MigrateBlogsFromFiles.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = MigrateBlogsFromFiles.m; sourceTree = ""; }; + E1634517183B733B005E967F /* WordPressComOAuthClient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WordPressComOAuthClient.h; sourceTree = ""; }; + E1634518183B733B005E967F /* WordPressComOAuthClient.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WordPressComOAuthClient.m; sourceTree = ""; }; E167745A1377F24300EE44DD /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Localizable.strings; sourceTree = ""; }; E167745B1377F25500EE44DD /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = ""; }; E167745C1377F26400EE44DD /* de */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/Localizable.strings; sourceTree = ""; }; @@ -3919,6 +3922,8 @@ E13EB7A4157D230000885780 /* WordPressComApi.m */, E1756DD41694560100D9EC00 /* WordPressComApiCredentials.h */, E1756DD51694560100D9EC00 /* WordPressComApiCredentials.m */, + E1634517183B733B005E967F /* WordPressComOAuthClient.h */, + E1634518183B733B005E967F /* WordPressComOAuthClient.m */, ); path = WordPressApi; sourceTree = ""; @@ -5130,6 +5135,7 @@ 852F4E8C17BED193005ED539 /* PostSettingsSelectionViewController.m in Sources */, CC6B3BE715A33E16005A4523 /* WPFriendFinderNudgeView.m in Sources */, E1745A9A15AF49C000A3F7C5 /* UIViewController+Styled.m in Sources */, + E1634519183B733B005E967F /* WordPressComOAuthClient.m in Sources */, E1745AA715AF4E5900A3F7C5 /* UIBarButtonItem+Styled.m in Sources */, FD75DDAD15B021C80043F12C /* UIViewController+Rotation.m in Sources */, 5DEB6EF515B471B3004E81F3 /* WPPopoverBackgroundView.m in Sources */, diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 3c04dc66cd93..e1a681a28881 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -38,7 +38,8 @@ extern NSString *const WordPressComApiErrorMessageKey; @property (nonatomic,readonly,strong) NSString *username; @property (nonatomic,readonly,strong) NSString *password; -+ (WordPressComApi *)sharedApi; ++ (WordPressComApi *)sharedApi DEPRECATED_ATTRIBUTE; +- (id)initWithOAuthToken:(NSString *)authToken; ///------------------------- /// @name Account management diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index e1c9c0800c32..d4e58ea1eadc 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -17,6 +17,7 @@ #import #import #import "UIDevice+WordPressIdentifier.h" +#import "WPAccount.h" NSString *const WordPressComApiClientEndpointURL = @"https://public-api.wordpress.com/rest/v1/"; NSString *const WordPressComApiOauthBaseUrl = @"https://public-api.wordpress.com/oauth2"; @@ -84,47 +85,18 @@ @implementation WordPressComApi { } + (WordPressComApi *)sharedApi { - static WordPressComApi *_sharedApi = nil; - static dispatch_once_t oncePredicate; - dispatch_once(&oncePredicate, ^{ - NSString *username = [[NSUserDefaults standardUserDefaults] objectForKey:@"wpcom_username_preference"]; - DDLogVerbose(@"Initializing API with username '%@'", username); - NSString *password = nil; - NSString *authToken = nil; - if (username) { - NSError *error = nil; - password = [SFHFKeychainUtils getPasswordForUsername:username - andServiceName:kWPcomXMLRPCUrl - error:&error]; - if (error) { - DDLogError(@"Error getting WordPress.com password: %@", error); - } else { - DDLogVerbose(@"Found password for API: %@", password ? @"YES" : @"NO"); - } - authToken = [SFHFKeychainUtils getPasswordForUsername:username - andServiceName:WordPressComApiOauthServiceName - error:&error]; - if (error) { - DDLogError(@"Error getting WordPress.com OAuth token: %@", error); - } else { - DDLogVerbose(@"Found token for API: %@", authToken ? @"YES" : @"NO"); - } - } - _sharedApi = [[self alloc] initWithBaseURL:[NSURL URLWithString:WordPressComApiClientEndpointURL] ]; - _sharedApi.username = username; - _sharedApi.password = password; - [_sharedApi registerHTTPOperationClass:[WPJSONRequestOperation class]]; - [_sharedApi setDefaultHeader:@"User-Agent" value:[[WordPressAppDelegate sharedWordPressApplicationDelegate] applicationUserAgent]]; - if (authToken) { - _sharedApi.authToken = authToken; - } else if (username && password) { - [_sharedApi signInWithUsername:username password:password success:nil failure:nil]; - } - -// [_sharedApi checkForNewUnseenNotifications]; - }); + return [[WPAccount defaultWordPressComAccount] restApi]; +} - return _sharedApi; +- (id)initWithOAuthToken:(NSString *)authToken { + self = [super initWithBaseURL:[NSURL URLWithString:WordPressComApiClientEndpointURL]]; + if (self) { + _authToken = authToken; + [self setAuthorizationHeaderWithToken:_authToken]; + [self registerHTTPOperationClass:[WPJSONRequestOperation class]]; + [self setDefaultHeader:@"User-Agent" value:[[WordPressAppDelegate sharedWordPressApplicationDelegate] applicationUserAgent]]; + } + return self; } #pragma mark - Account management diff --git a/WordPress/WordPressApi/WordPressComOAuthClient.h b/WordPress/WordPressApi/WordPressComOAuthClient.h new file mode 100644 index 000000000000..0134fceebd69 --- /dev/null +++ b/WordPress/WordPressApi/WordPressComOAuthClient.h @@ -0,0 +1,41 @@ +// +// WordPressComOAuthClient.h +// WordPress +// +// Created by Jorge Bernal on 19/11/13. +// Copyright (c) 2013 WordPress. All rights reserved. +// + +#import "AFHTTPClient.h" + +extern NSString * const WordPressComOAuthErrorDomain; + +typedef NS_ENUM(NSUInteger, WordPressComOAuthError) { + WordPressComOAuthErrorUnknown, + WordPressComOAuthErrorInvalidClient, + WordPressComOAuthErrorUnsupportedGrantType, + WordPressComOAuthErrorInvalidRequest, +}; + +/** + `WordPressComOAuthClient` encapsulates the pattern of authenticating against WordPress.com OAuth2 service. + + Right now it requires a special client id and secret, so this probably won't work for you + + @see https://developer.wordpress.com/docs/oauth2/ + */ +@interface WordPressComOAuthClient : AFHTTPClient + ++ (WordPressComOAuthClient *)client; + +/** + Authenticates on WordPress.com + + @param username the account's username. + @param password the account's password. + @param success block to be called if authentication was successful. The OAuth2 token is passed as a parameter. + @param failure block to be called if authentication failed. The error object is passed as a parameter. + */ +- (void)authenticateWithUsername:(NSString *)username password:(NSString *)password success:(void (^)(NSString *authToken))success failure:(void (^)(NSError *error))failure; + +@end diff --git a/WordPress/WordPressApi/WordPressComOAuthClient.m b/WordPress/WordPressApi/WordPressComOAuthClient.m new file mode 100644 index 000000000000..c4130e734b5b --- /dev/null +++ b/WordPress/WordPressApi/WordPressComOAuthClient.m @@ -0,0 +1,84 @@ +// +// WordPressComOAuthClient.m +// WordPress +// +// Created by Jorge Bernal on 19/11/13. +// Copyright (c) 2013 WordPress. All rights reserved. +// + +#import "WordPressComOAuthClient.h" +#import "WordPressComApiCredentials.h" + +NSString * const WordPressComOAuthErrorDomain = @"WordPressComOAuthError"; + +static NSString * const WordPressComOAuthBaseUrl = @"https://public-api.wordpress.com/oauth2"; +static NSString * const WordPressComOAuthRedirectUrl = @"http://wordpress.com/"; + +@implementation WordPressComOAuthClient + ++ (WordPressComOAuthClient *)client { + WordPressComOAuthClient *client = [[WordPressComOAuthClient alloc] initWithBaseURL:[NSURL URLWithString:WordPressComOAuthBaseUrl]]; + [client registerHTTPOperationClass:[AFJSONRequestOperation class]]; + [client setDefaultHeader:@"Accept" value:@"application/json"]; + return client; +} + +- (void)authenticateWithUsername:(NSString *)username password:(NSString *)password success:(void (^)(NSString *authToken))success failure:(void (^)(NSError *error))failure { + NSDictionary *parameters = @{ + @"username": username, + @"password": password, + @"grant_type": @"password", + @"client_id": [WordPressComApiCredentials client], + @"client_secret": [WordPressComApiCredentials secret], + }; + [self postPath:@"token" + parameters:parameters + success:^(AFHTTPRequestOperation *operation, id responseObject) { + DDLogVerbose(@"Received OAuth2 response: %@", responseObject); + NSString *authToken = [responseObject stringForKey:@"access_token"]; + if (success) { + success(authToken); + } + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + error = [self processError:error forOperation:operation]; + DDLogError(@"Error receiving OAuth2 token: %@", error); + if (failure) { + failure(error); + } + }]; +} + +- (NSError *)processError:(NSError *)error forOperation:(AFHTTPRequestOperation *)operation { + if (operation.response.statusCode >= 400 && operation.response.statusCode < 500) { + // Bad request, look for errors in the JSON response + NSDictionary *response = nil; + if ([operation isKindOfClass:[AFJSONRequestOperation class]]) { + AFJSONRequestOperation *jsonOperation = (AFJSONRequestOperation *)operation; + response = jsonOperation.responseJSON; + } + if (response) { + NSString *errorCode = [response stringForKey:@"error"]; + NSString *errorDescription = [response stringForKey:@"error_description"]; + + NSInteger code = WordPressComOAuthErrorUnknown; + /* + Possible errors: + - invalid_client: client_id is missing or wrong, it shouldn't happen + - unsupported_grant_type: client_id doesn't support password grants + - invalid_request: a required field is missing/malformed + - invalid_request: authentication failed + */ + if ([errorCode isEqualToString:@"invalid_client"]) { + code = WordPressComOAuthErrorInvalidClient; + } else if ([errorCode isEqualToString:@"unsupported_grant_type"]) { + code = WordPressComOAuthErrorUnsupportedGrantType; + } else if ([errorCode isEqualToString:@"invalid_request"]) { + code = WordPressComOAuthErrorInvalidRequest; + } + return [NSError errorWithDomain:WordPressComOAuthErrorDomain code:code userInfo:@{NSLocalizedDescriptionKey: errorDescription}]; + } + } + return error; +} + +@end From 39984d04dd34f4d6766183b7d5a8b4fadba9596a Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Tue, 19 Nov 2013 19:19:50 +0100 Subject: [PATCH 06/64] Check for default account instead of WordPressComApi --- WordPress/Classes/SettingsViewController.m | 15 ++++++--------- WordPress/Classes/WordPressAppDelegate.m | 2 +- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index f1e4c48c3722..70a87557cae5 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -207,15 +207,13 @@ - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger switch (section) { case SettingsSectionWpcom: numWpcomRows = 1; - if ([[WordPressComApi sharedApi] hasCredentials]) { + + // Show a Sign Out row? + if ([WPAccount defaultWordPressComAccount]) { // Allow notifications management? if ([self supportsNotifications]) { numWpcomRows += 1; } - } - - // Show a Sign Out row? - if ([[WPAccount defaultWordPressComAccount] username]) { numWpcomRows += 1; } @@ -265,7 +263,7 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa cell.accessoryView = nil; if (indexPath.section == SettingsSectionWpcom) { - if ([[WordPressComApi sharedApi] hasCredentials]) { + if ([WPAccount defaultWordPressComAccount]) { if (indexPath.row == 0) { cell.textLabel.text = NSLocalizedString(@"Username", @""); cell.detailTextLabel.text = [[WPAccount defaultWordPressComAccount] username]; @@ -328,7 +326,7 @@ - (UITableViewCell *)cellForIndexPath:(NSIndexPath *)indexPath { switch (indexPath.section) { case SettingsSectionWpcom: - if ([[WordPressComApi sharedApi] hasCredentials] && indexPath.row == 0) { + if ([WPAccount defaultWordPressComAccount] && indexPath.row == 0) { cellIdentifier = @"WpcomUsernameCell"; cellStyle = UITableViewCellStyleValue1; } else { @@ -386,7 +384,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath [tableView deselectRowAtIndexPath:indexPath animated:YES]; if (indexPath.section == SettingsSectionWpcom) { - if ([[WordPressComApi sharedApi] hasCredentials]) { + if ([WPAccount defaultWordPressComAccount]) { if (indexPath.row == [self rowForSignOut]) { [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedSignOutOfDotCom]; @@ -466,7 +464,6 @@ - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger [WPMobileStats trackEventForWPCom:StatsEventSettingsSignedOutOfDotCom]; // Sign out - [[WordPressComApi sharedApi] signOut]; //Signout first, then remove the account [WPAccount removeDefaultWordPressComAccount]; [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:SettingsSectionWpcom] withRowAnimation:UITableViewRowAnimationFade]; diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index 50c572041e44..d63a2e8ab2c5 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -220,7 +220,7 @@ - (void)configureCrashlytics { [Crashlytics startWithAPIKey:[WordPressComApiCredentials crashlyticsApiKey]]; [[Crashlytics sharedInstance] setDelegate:self]; - BOOL hasCredentials = [[WordPressComApi sharedApi] hasCredentials]; + BOOL hasCredentials = ([WPAccount defaultWordPressComAccount] != nil); [self setCommonCrashlyticsParameters]; if (hasCredentials && [[WPAccount defaultWordPressComAccount] username] != nil) { From bc03462abe05107a05a04962aea7de4cda583577 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Tue, 19 Nov 2013 19:20:19 +0100 Subject: [PATCH 07/64] Register for the right sign in/out notification --- WordPress/Classes/WordPressAppDelegate.m | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index d63a2e8ab2c5..f6c7f27c8e27 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -227,22 +227,18 @@ - (void)configureCrashlytics { [Crashlytics setUserName:[[WPAccount defaultWordPressComAccount] username]]; } - void (^wpcomLoggedInBlock)(NSNotification *) = ^(NSNotification *note) { + void (^accountChangedBlock)(NSNotification *) = ^(NSNotification *note) { [Crashlytics setUserName:[[WPAccount defaultWordPressComAccount] username]]; [self setCommonCrashlyticsParameters]; }; - void (^wpcomLoggedOutBlock)(NSNotification *) = ^(NSNotification *note) { - [Crashlytics setUserName:nil]; - [self setCommonCrashlyticsParameters]; - }; - [[NSNotificationCenter defaultCenter] addObserverForName:WordPressComApiDidLoginNotification object:nil queue:nil usingBlock:wpcomLoggedInBlock]; - [[NSNotificationCenter defaultCenter] addObserverForName:WordPressComApiDidLogoutNotification object:nil queue:nil usingBlock:wpcomLoggedOutBlock]; + [[NSNotificationCenter defaultCenter] addObserverForName:WPAccountDefaultWordPressComAccountChangedNotification object:nil queue:nil usingBlock:accountChangedBlock]; } - (void)setCommonCrashlyticsParameters { - [Crashlytics setObjectValue:[NSNumber numberWithBool:[[WordPressComApi sharedApi] hasCredentials]] forKey:@"logged_in"]; - [Crashlytics setObjectValue:@([[WordPressComApi sharedApi] hasCredentials]) forKey:@"connected_to_dotcom"]; + BOOL loggedIn = [WPAccount defaultWordPressComAccount] != nil; + [Crashlytics setObjectValue:@(loggedIn) forKey:@"logged_in"]; + [Crashlytics setObjectValue:@(loggedIn) forKey:@"connected_to_dotcom"]; [Crashlytics setObjectValue:@([Blog countWithContext:[self managedObjectContext]]) forKey:@"number_of_blogs"]; } From c4c379ddd2c76dc428c63ea76d937f8f69077e2d Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 20 Nov 2013 12:43:58 +0100 Subject: [PATCH 08/64] Fixed login dismissal without Walkthrough --- WordPress/Classes/LoginViewController.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 4ecf124dd15f..b17a234fcd43 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -684,7 +684,7 @@ - (void)signInForSelfHostedForUsername:(NSString *)username password:(NSString * [api getBlogsWithSuccess:^(NSArray *blogs) { _blogs = blogs; - + [self handleGetBlogsSuccess:api.xmlrpc.absoluteString]; } failure:^(NSError *error) { [SVProgressHUD dismiss]; [self displayRemoteError:error]; @@ -697,8 +697,7 @@ - (void)createWordPressComAccountForUsername:(NSString *)username password:(NSSt WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:authToken]; [account syncBlogsWithSuccess:^{ [SVProgressHUD dismiss]; - [self.navigationController popViewControllerAnimated:NO]; - [self showCompletionWalkthrough]; + [self dismiss]; } failure:^(NSError *error) { [SVProgressHUD dismiss]; [self displayRemoteError:error]; From 095b6c3f189b7e720fddbbc09af940f9fec8a8ef Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 13:40:57 +0100 Subject: [PATCH 09/64] Offer suggestion for deprecated sharedApi --- WordPress/WordPressApi/WordPressComApi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index e1a681a28881..646da3714f6b 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -38,7 +38,7 @@ extern NSString *const WordPressComApiErrorMessageKey; @property (nonatomic,readonly,strong) NSString *username; @property (nonatomic,readonly,strong) NSString *password; -+ (WordPressComApi *)sharedApi DEPRECATED_ATTRIBUTE; ++ (WordPressComApi *)sharedApi DEPRECATED_MSG_ATTRIBUTE("Use [[WPAccount defaultWordPressComAccount] restApi] instead"); - (id)initWithOAuthToken:(NSString *)authToken; ///------------------------- From 6a49522394c9b717477d0b957f1917e623155a57 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 14:18:27 +0100 Subject: [PATCH 10/64] Removed Blog isAdmin --- WordPress/Classes/Blog.h | 2 +- WordPress/Classes/Blog.m | 2 +- .../Classes/CreateWPComBlogViewController.m | 1 - WordPress/Classes/MigrateBlogsFromFiles.m | 1 - WordPress/Classes/WPAccount.h | 2 +- WordPress/Classes/WPAccount.m | 1 - .../WordPress 13.xcdatamodel/contents | 37 ++++++++----------- .../EditPostViewControllerTest.m | 1 - 8 files changed, 18 insertions(+), 29 deletions(-) diff --git a/WordPress/Classes/Blog.h b/WordPress/Classes/Blog.h index c4521794b24a..a3f1ce1267db 100644 --- a/WordPress/Classes/Blog.h +++ b/WordPress/Classes/Blog.h @@ -19,7 +19,7 @@ @property (nonatomic, strong) NSNumber *blogID; @property (nonatomic, strong) NSString *blogName, *xmlrpc, *apiKey; @property (weak, readonly) NSString *blavatarUrl; -@property (nonatomic, strong) NSNumber *isAdmin, *hasOlderPosts, *hasOlderPages; +@property (nonatomic, strong) NSNumber *hasOlderPosts, *hasOlderPages; @property (nonatomic, strong) NSSet *posts; @property (nonatomic, strong) NSSet *categories; @property (nonatomic, strong) NSSet *comments; diff --git a/WordPress/Classes/Blog.m b/WordPress/Classes/Blog.m index 441b864d3d78..bad5ce0396d2 100644 --- a/WordPress/Classes/Blog.m +++ b/WordPress/Classes/Blog.m @@ -41,7 +41,7 @@ @implementation Blog { } @dynamic blogID, blogName, url, xmlrpc, apiKey; -@dynamic isAdmin, hasOlderPosts, hasOlderPages; +@dynamic hasOlderPosts, hasOlderPages; @dynamic posts, categories, comments; @dynamic lastPostsSync, lastStatsSync, lastPagesSync, lastCommentsSync, lastUpdateWarning; @synthesize isSyncingPosts, isSyncingPages, isSyncingComments; diff --git a/WordPress/Classes/CreateWPComBlogViewController.m b/WordPress/Classes/CreateWPComBlogViewController.m index 7470dee0ebb0..a644c4fef4d9 100644 --- a/WordPress/Classes/CreateWPComBlogViewController.m +++ b/WordPress/Classes/CreateWPComBlogViewController.m @@ -349,7 +349,6 @@ - (void)createBlog:(NSDictionary *)blogInfo { [newBlog setObject:[blogInfo objectForKey:@"blogid"] forKey:@"blogid"]; [newBlog setObject:[blogInfo objectForKey:@"url"] forKey:@"url"]; [newBlog setObject:[blogInfo objectForKey:@"xmlrpc"] forKey:@"xmlrpc"]; - [newBlog setObject:@(YES) forKey:@"isAdmin"]; WPAccount *account = [WPAccount defaultWordPressComAccount]; diff --git a/WordPress/Classes/MigrateBlogsFromFiles.m b/WordPress/Classes/MigrateBlogsFromFiles.m index a834202450c9..fa0521a0283b 100644 --- a/WordPress/Classes/MigrateBlogsFromFiles.m +++ b/WordPress/Classes/MigrateBlogsFromFiles.m @@ -51,7 +51,6 @@ - (BOOL)forceBlogsMigrationInContext:(NSManagedObjectContext *)destMOC error:(NS [blog setValue:blogUrl forKey:@"url"]; [blog setValue:[blogInfo valueForKey:@"username"] forKey:@"username"]; [blog setValue:[blogInfo valueForKey:@"xmlrpc"] forKey:@"xmlrpc"]; - [blog setValue:[NSNumber numberWithBool:YES] forKey:@"isAdmin"]; if ([[blogInfo valueForKey:@"GeolocationSetting"] isKindOfClass:[NSString class]]) { BOOL geo = [[blogInfo valueForKey:@"GeolocationSetting"] isEqualToString:@"YES"]; [blog setValue:[NSNumber numberWithBool:geo] forKey:@"geolocationEnabled"]; diff --git a/WordPress/Classes/WPAccount.h b/WordPress/Classes/WPAccount.h index 06860da48f42..3b515f18e1df 100644 --- a/WordPress/Classes/WPAccount.h +++ b/WordPress/Classes/WPAccount.h @@ -105,7 +105,7 @@ extern NSString * const WPAccountDefaultWordPressComAccountChangedNotification; If a there is an existing blog with the same `url`, it is returned as-is. - @param blogInfo a dictionary containing `url`, `blogName`, `xmlrpc`, `blogid`, and `isAdmin`; as returned by `wp.getUsersBlogs` + @param blogInfo a dictionary containing `url`, `blogName`, `xmlrpc`, and `blogid`; as returned by `wp.getUsersBlogs` @return the newly created blog */ - (Blog *)findOrCreateBlogFromDictionary:(NSDictionary *)blogInfo withContext:(NSManagedObjectContext*)context; diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index 56fdf9aba2c7..ec26bb35e59e 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -159,7 +159,6 @@ - (Blog *)findOrCreateBlogFromDictionary:(NSDictionary *)blogInfo withContext:(N blog.blogID = [NSNumber numberWithInt:[[blogInfo objectForKey:@"blogid"] intValue]]; blog.blogName = [[blogInfo objectForKey:@"blogName"] stringByDecodingXMLCharacters]; blog.xmlrpc = [blogInfo objectForKey:@"xmlrpc"]; - blog.isAdmin = [NSNumber numberWithInt:[[blogInfo objectForKey:@"isAdmin"] intValue]]; return blog; } diff --git a/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents b/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents index ac42bc9f63ae..70efdcb971bc 100644 --- a/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents +++ b/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents @@ -79,9 +79,7 @@ - - - + @@ -118,12 +116,7 @@ - - - - - - + @@ -332,18 +325,18 @@ - - - - - - - - - - - - - + + + + + + + + + + + + + \ No newline at end of file diff --git a/WordPress/WordPressTest/EditPostViewControllerTest.m b/WordPress/WordPressTest/EditPostViewControllerTest.m index 0292014e939e..b206746ac420 100644 --- a/WordPress/WordPressTest/EditPostViewControllerTest.m +++ b/WordPress/WordPressTest/EditPostViewControllerTest.m @@ -31,7 +31,6 @@ - (void)setUp { @"url": @"http://test.blog/", @"xmlrpc": @"http://test.blog/xmlrpc.php", @"blogName": @"A test blog", - @"isAdmin": @YES }; [[CoreDataTestHelper sharedHelper] registerDefaultContext]; _account = [WPAccount createOrUpdateSelfHostedAccountWithXmlrpc:blogDict[@"xmlrpc"] username:@"test" andPassword:@"test"]; From 31e8da731792e0a182e77dd8b4c821f81ef60175 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 16:19:05 +0100 Subject: [PATCH 11/64] Create self hosted blogs right away Previously we'd call wp.getUsersBlogs even if we have all we need from the first wp.getOptions call Also did some cleanup and removed unused methods --- WordPress/Classes/LoginViewController.m | 132 +++++------------------- 1 file changed, 27 insertions(+), 105 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index b17a234fcd43..465b5c40e854 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -488,7 +488,6 @@ - (void)showCreateAccountView _passwordText.text = password; _userIsDotCom = YES; [self.navigationController popViewControllerAnimated:NO]; - [self showAddUsersBlogsForWPCom]; }; [self.navigationController pushViewController:createAccountViewController animated:YES]; } @@ -642,7 +641,8 @@ - (void)signIn _dotComSiteUrl = [siteUrl objectForKey:@"value"]; [self signInForWPComForUsername:username andPassword:password]; } else { - [self signInForSelfHostedForUsername:username password:password options:options andApi:api]; + NSString *xmlrpc = [xmlRPCURL absoluteString]; + [self createSelfHostedAccountAndBlogWithUsername:username password:password xmlrpc:xmlrpc options:options]; } } failure:^(NSError *error){ [SVProgressHUD dismiss]; @@ -676,21 +676,6 @@ - (void)signInForWPComForUsername:(NSString *)username andPassword:(NSString *)p }]; } -- (void)signInForSelfHostedForUsername:(NSString *)username password:(NSString *)password options:(NSDictionary *)options andApi:(WordPressXMLRPCApi *)api -{ - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXFirstWalkthroughSignedInForSelfHosted]; - - [SVProgressHUD showWithStatus:NSLocalizedString(@"Reading blog options", nil) maskType:SVProgressHUDMaskTypeBlack]; - - [api getBlogsWithSuccess:^(NSArray *blogs) { - _blogs = blogs; - [self handleGetBlogsSuccess:api.xmlrpc.absoluteString]; - } failure:^(NSError *error) { - [SVProgressHUD dismiss]; - [self displayRemoteError:error]; - }]; -} - - (void)createWordPressComAccountForUsername:(NSString *)username password:(NSString *)password authToken:(NSString *)authToken { [SVProgressHUD showWithStatus:NSLocalizedString(@"Getting account information", @"") maskType:SVProgressHUDMaskTypeBlack]; @@ -706,6 +691,31 @@ - (void)createWordPressComAccountForUsername:(NSString *)username password:(NSSt [account.restApi getNotificationsSince:nil success:nil failure:nil]; } +- (void)createSelfHostedAccountAndBlogWithUsername:(NSString *)username password:(NSString *)password xmlrpc:(NSString *)xmlrpc options:(NSDictionary *)options +{ + WPAccount *account = [self createAccountWithUsername:username andPassword:password isWPCom:NO xmlRPCUrl:xmlrpc]; + NSString *blogName = [options stringForKeyPath:@"blog_title.value"]; + NSString *url = [options stringForKeyPath:@"home_url.value"]; + NSMutableDictionary *blogDetails = [NSMutableDictionary dictionaryWithObject:xmlrpc forKey:@"xmlrpc"]; + if (blogName) { + [blogDetails setObject:blogName forKey:@"blogName"]; + } + if (url) { + [blogDetails setObject:url forKey:@"url"]; + } + _blog = [account findOrCreateBlogFromDictionary:blogDetails withContext:account.managedObjectContext]; + _blog.options = options; + [_blog dataSave]; + [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXFirstWalkthroughUserSignedInToBlogWithJetpack]; + [_blog syncBlogWithSuccess:nil failure:nil]; + + if ([_blog hasJetpack]) { + [self showJetpackAuthentication]; + } else { + [self dismiss]; + } +} + - (void)handleGuessXMLRPCURLFailure:(NSError *)error { [SVProgressHUD dismiss]; @@ -729,32 +739,6 @@ - (void)handleGuessXMLRPCURLFailure:(NSError *)error } } -- (void)handleGetBlogsSuccess:(NSString *)xmlRPCUrl { - if ([_blogs count] > 0) { - // If the user has entered the URL of a site they own on a MultiSite install, - // assume they want to add that specific site. - NSDictionary *subsite = nil; - if ([_blogs count] > 1) { - subsite = [[_blogs filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"xmlrpc = %@", xmlRPCUrl]] lastObject]; - } - - if (subsite == nil) { - subsite = [_blogs objectAtIndex:0]; - } - - if ([_blogs count] > 1 && [[subsite objectForKey:@"blogid"] isEqualToString:@"1"]) { - [SVProgressHUD dismiss]; - [self showAddUsersBlogsForSelfHosted:xmlRPCUrl]; - } else { - [self createBlogWithXmlRpc:xmlRPCUrl andBlogDetails:subsite]; - [self synchronizeNewlyAddedBlog]; - } - } else { - NSError *error = [NSError errorWithDomain:@"WordPress" code:0 userInfo:@{NSLocalizedDescriptionKey: NSLocalizedString(@"Sorry, you credentials were good but you don't seem to have access to any blogs", nil)}]; - [self displayRemoteError:error]; - } -} - - (void)displayRemoteError:(NSError *)error { DDLogError(@"%@", error); NSString *message = [error localizedDescription]; @@ -781,49 +765,6 @@ - (void)displayRemoteError:(NSError *)error { } } -- (NewAddUsersBlogViewController *)addUsersBlogViewController:(NSString *)xmlRPCUrl -{ - BOOL isWPCom = (xmlRPCUrl == nil); - NewAddUsersBlogViewController *vc = [[NewAddUsersBlogViewController alloc] init]; - vc.account = [self createAccountWithUsername:_usernameText.text andPassword:_passwordText.text isWPCom:isWPCom xmlRPCUrl:xmlRPCUrl]; - vc.blogAdditionCompleted = ^(NewAddUsersBlogViewController * viewController){ - [self.navigationController popViewControllerAnimated:NO]; - [self dismiss]; - }; - vc.onNoBlogsLoaded = ^(NewAddUsersBlogViewController *viewController) { - [self.navigationController popViewControllerAnimated:NO]; - [self dismiss]; - }; - vc.onErrorLoading = ^(NewAddUsersBlogViewController *viewController, NSError *error) { - DDLogError(@"There was an error loading blogs after sign in"); - [self.navigationController popViewControllerAnimated:YES]; - [self displayGenericErrorMessage:[error localizedDescription]]; - }; - - return vc; -} - -- (void)showAddUsersBlogsForSelfHosted:(NSString *)xmlRPCUrl -{ - NewAddUsersBlogViewController *vc = [self addUsersBlogViewController:xmlRPCUrl]; - - [self.navigationController pushViewController:vc animated:YES]; -} - -- (void)showAddUsersBlogsForWPCom -{ - NewAddUsersBlogViewController *vc = [self addUsersBlogViewController:nil]; - - NSString *siteUrl = [_siteUrlText.text trim]; - if ([siteUrl length] != 0) { - vc.siteUrl = siteUrl; - } else if ([_dotComSiteUrl length] != 0) { - vc.siteUrl = _dotComSiteUrl; - } - - [self.navigationController pushViewController:vc animated:YES]; -} - - (void)createBlogWithXmlRpc:(NSString *)xmlRPCUrl andBlogDetails:(NSDictionary *)blogDetails { NSParameterAssert(blogDetails != nil); @@ -848,25 +789,6 @@ - (WPAccount *)createAccountWithUsername:(NSString *)username andPassword:(NSStr return account; } -- (void)synchronizeNewlyAddedBlog -{ - [SVProgressHUD setStatus:NSLocalizedString(@"Synchronizing Blog", nil)]; - void (^successBlock)() = ^{ - [[WordPressComApi sharedApi] syncPushNotificationInfo]; - [SVProgressHUD dismiss]; - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXFirstWalkthroughUserSignedInToBlogWithJetpack]; - if ([_blog hasJetpack]) { - [self showJetpackAuthentication]; - } else { - [self dismiss]; - } - }; - void (^failureBlock)(NSError*) = ^(NSError * error) { - [SVProgressHUD dismiss]; - }; - [_blog syncBlogWithSuccess:successBlock failure:failureBlock]; -} - - (void)keyboardWillShow:(NSNotification *)notification { NSDictionary *keyboardInfo = notification.userInfo; From 54be9d2f1e98264523b4cf45df54410b9ef46cd5 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 18:21:13 +0100 Subject: [PATCH 12/64] Don't pop Jetpack auth when skipped Since the view controller is about to be dismissed, if we pop the jetpack controller it'll go back to login for a moment while it animates out. Since the background switches from green to blue, it was a very annoying glitch. --- WordPress/Classes/LoginViewController.m | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 465b5c40e854..ef1339c2ac27 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -506,7 +506,6 @@ - (void)showJetpackAuthentication [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXFirstWalkthroughUserSkippedConnectingToJetpack]; } - [self.navigationController popViewControllerAnimated:NO]; [self dismiss]; }]; [self.navigationController pushViewController:jetpackSettingsViewController animated:YES]; From f0c91d9b54b17c9a8e2a213cfaac40d42144fd15 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 18:35:32 +0100 Subject: [PATCH 13/64] Don't set wp.com account as default when jetpack --- WordPress/Classes/LoginViewController.m | 19 ++++++------------- WordPress/Classes/WPAccount.m | 3 --- 2 files changed, 6 insertions(+), 16 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index ef1339c2ac27..3d9e992d4cbe 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -679,6 +679,9 @@ - (void)createWordPressComAccountForUsername:(NSString *)username password:(NSSt { [SVProgressHUD showWithStatus:NSLocalizedString(@"Getting account information", @"") maskType:SVProgressHUDMaskTypeBlack]; WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:authToken]; + if (![WPAccount defaultWordPressComAccount]) { + [WPAccount setDefaultWordPressComAccount:account]; + } [account syncBlogsWithSuccess:^{ [SVProgressHUD dismiss]; [self dismiss]; @@ -692,7 +695,7 @@ - (void)createWordPressComAccountForUsername:(NSString *)username password:(NSSt - (void)createSelfHostedAccountAndBlogWithUsername:(NSString *)username password:(NSString *)password xmlrpc:(NSString *)xmlrpc options:(NSDictionary *)options { - WPAccount *account = [self createAccountWithUsername:username andPassword:password isWPCom:NO xmlRPCUrl:xmlrpc]; + WPAccount *account = [WPAccount createOrUpdateSelfHostedAccountWithXmlrpc:xmlrpc username:username andPassword:password]; NSString *blogName = [options stringForKeyPath:@"blog_title.value"]; NSString *url = [options stringForKeyPath:@"home_url.value"]; NSMutableDictionary *blogDetails = [NSMutableDictionary dictionaryWithObject:xmlrpc forKey:@"xmlrpc"]; @@ -768,8 +771,8 @@ - (void)createBlogWithXmlRpc:(NSString *)xmlRPCUrl andBlogDetails:(NSDictionary { NSParameterAssert(blogDetails != nil); - WPAccount *account = [self createAccountWithUsername:_usernameText.text andPassword:_passwordText.text isWPCom:NO xmlRPCUrl:xmlRPCUrl]; - + WPAccount *account = [WPAccount createOrUpdateSelfHostedAccountWithXmlrpc:xmlRPCUrl username:_usernameText.text andPassword:_passwordText.text]; + NSMutableDictionary *newBlog = [NSMutableDictionary dictionaryWithDictionary:blogDetails]; [newBlog setObject:xmlRPCUrl forKey:@"xmlrpc"]; @@ -778,16 +781,6 @@ - (void)createBlogWithXmlRpc:(NSString *)xmlRPCUrl andBlogDetails:(NSDictionary } -- (WPAccount *)createAccountWithUsername:(NSString *)username andPassword:(NSString *)password isWPCom:(BOOL)isWPCom xmlRPCUrl:(NSString *)xmlRPCUrl { - WPAccount *account; - if (isWPCom) { - account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:nil]; - } else { - account = [WPAccount createOrUpdateSelfHostedAccountWithXmlrpc:xmlRPCUrl username:username andPassword:password]; - } - return account; -} - - (void)keyboardWillShow:(NSNotification *)notification { NSDictionary *keyboardInfo = notification.userInfo; diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index ec26bb35e59e..cd59e6486c61 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -104,9 +104,6 @@ + (WPAccount *)createOrUpdateWordPressComAccountWithUsername:(NSString *)usernam WPAccount *account = [self createOrUpdateSelfHostedAccountWithXmlrpc:DotcomXmlrpcKey username:username andPassword:password]; account.isWpcom = YES; account.authToken = authToken; - if (__defaultDotcomAccount == nil) { - [self setDefaultWordPressComAccount:account]; - } return account; } From 35fb8f3e3cf704fdd3696ea049e9831e8cc83ece Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 18:36:01 +0100 Subject: [PATCH 14/64] Fixed account tests --- WordPress/WordPressTest/AccountTest.m | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/WordPress/WordPressTest/AccountTest.m b/WordPress/WordPressTest/AccountTest.m index 61245e9b4784..4abd48cde3e8 100644 --- a/WordPress/WordPressTest/AccountTest.m +++ b/WordPress/WordPressTest/AccountTest.m @@ -31,13 +31,15 @@ - (void)tearDown [[CoreDataTestHelper sharedHelper] reset]; } -- (void)testNewAccountSetsDefaultAccount +- (void)testNewAccountDoesntSetDefaultAccount { STAssertNil([WPAccount defaultWordPressComAccount], nil); - WPAccount *_account = [WPAccount createOrUpdateWordPressComAccountWithUsername:@"user" andPassword:@"pass"]; + WPAccount *_account = [WPAccount createOrUpdateWordPressComAccountWithUsername:@"user" password:@"pass" authToken:@"token"]; + STAssertNil([WPAccount defaultWordPressComAccount], nil); + [WPAccount setDefaultWordPressComAccount:_account]; STAssertNotNil([WPAccount defaultWordPressComAccount], nil); STAssertEqualObjects([WPAccount defaultWordPressComAccount], _account, nil); - WPAccount *_account2 = [WPAccount createOrUpdateWordPressComAccountWithUsername:@"user" andPassword:@"pass"]; + WPAccount *_account2 = [WPAccount createOrUpdateWordPressComAccountWithUsername:@"user" password:@"pass" authToken:@"token"]; STAssertNotNil(_account2, nil); STAssertEqualObjects([WPAccount defaultWordPressComAccount], _account, nil); } From 45060e5d84c499c7b074eb555b9391c06239b2e3 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 18:52:47 +0100 Subject: [PATCH 15/64] LoginViewController cleanup --- WordPress/Classes/LoginViewController.m | 22 ---------------------- 1 file changed, 22 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 3d9e992d4cbe..e992387a3469 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -258,12 +258,6 @@ - (void)helpButtonAction:(id)sender } - (void)clickedSkipToCreate:(id)sender -{ - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXFirstWalkthroughClickedSkipToCreateAccount]; - [self showCreateAccountView]; -} - -- (void)clickedCreateAccount:(UITapGestureRecognizer *)tapGestureRecognizer { [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXFirstWalkthroughClickedCreateAccount]; [self showCreateAccountView]; @@ -271,7 +265,6 @@ - (void)clickedCreateAccount:(UITapGestureRecognizer *)tapGestureRecognizer - (void)clickedBackground:(UITapGestureRecognizer *)tapGestureRecognizer { - [self.view endEditing:YES]; // The info button is a little hard to hit so this adds a little buffer around it @@ -302,7 +295,6 @@ - (void)signInButtonAction:(id)sender } - (void)toggleSignInformAction:(id)sender { - _userIsDotCom = !_userIsDotCom; // Controls are layed out in initializeView. Calling this method in an animation block will animate the controls to their new positions. @@ -767,20 +759,6 @@ - (void)displayRemoteError:(NSError *)error { } } -- (void)createBlogWithXmlRpc:(NSString *)xmlRPCUrl andBlogDetails:(NSDictionary *)blogDetails -{ - NSParameterAssert(blogDetails != nil); - - WPAccount *account = [WPAccount createOrUpdateSelfHostedAccountWithXmlrpc:xmlRPCUrl username:_usernameText.text andPassword:_passwordText.text]; - - NSMutableDictionary *newBlog = [NSMutableDictionary dictionaryWithDictionary:blogDetails]; - [newBlog setObject:xmlRPCUrl forKey:@"xmlrpc"]; - - _blog = [account findOrCreateBlogFromDictionary:newBlog withContext:account.managedObjectContext]; - [_blog dataSave]; - -} - - (void)keyboardWillShow:(NSNotification *)notification { NSDictionary *keyboardInfo = notification.userInfo; From 6bae44c8b958eb3dee2541a1eae5ee103f1b016a Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 18:55:18 +0100 Subject: [PATCH 16/64] Added missing translation --- WordPress/Classes/LoginViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index e992387a3469..542accba3e8b 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -402,7 +402,7 @@ - (void)addControls [_toggleSignInForm addTarget:self action:@selector(toggleSignInformAction:) forControlEvents:UIControlEventTouchUpInside]; [_mainView addSubview:_toggleSignInForm]; } - NSString *toggleTitle = _userIsDotCom ? @"Add Self-Hosted Site" : @"Sign in to WordPress.com"; + NSString *toggleTitle = _userIsDotCom ? NSLocalizedString(@"Add Self-Hosted Site", nil) : NSLocalizedString(@"Sign in to WordPress.com", nil); [_toggleSignInForm setTitle:toggleTitle forState:UIControlStateNormal]; // Add Skip to Create Account Button From 3fd38fc0120a017f9951fe2bb3b0cd3b612d4b6d Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 20:54:40 +0100 Subject: [PATCH 17/64] Fixed account creation - Use a dedicated anonymous REST API object for unauthenticated calls. Refs #22 - We get all we need to create the blog from /sites/new, don't make any extra calls - Auto login the user if registration is successful --- .../CreateAccountAndBlogViewController.h | 2 - .../CreateAccountAndBlogViewController.m | 76 ++++++++++++------- WordPress/Classes/LoginViewController.m | 6 -- WordPress/WordPressApi/WordPressComApi.h | 6 ++ WordPress/WordPressApi/WordPressComApi.m | 14 ++++ 5 files changed, 68 insertions(+), 36 deletions(-) diff --git a/WordPress/Classes/CreateAccountAndBlogViewController.h b/WordPress/Classes/CreateAccountAndBlogViewController.h index 3417a85e50a0..ced56dabebfe 100644 --- a/WordPress/Classes/CreateAccountAndBlogViewController.h +++ b/WordPress/Classes/CreateAccountAndBlogViewController.h @@ -10,6 +10,4 @@ @interface CreateAccountAndBlogViewController : UIViewController -@property (nonatomic, copy) void(^onCreatedUser)(NSString *, NSString *); - @end diff --git a/WordPress/Classes/CreateAccountAndBlogViewController.m b/WordPress/Classes/CreateAccountAndBlogViewController.m index 736ad7c6c0b8..a0461d4fc9c2 100644 --- a/WordPress/Classes/CreateAccountAndBlogViewController.m +++ b/WordPress/Classes/CreateAccountAndBlogViewController.m @@ -24,6 +24,9 @@ #import "WPWebViewController.h" #import "WPStyleGuide.h" #import "UILabel+SuggestSize.h" +#import "WPAccount.h" +#import "Blog.h" +#import "WordPressComOAuthClient.h" @interface CreateAccountAndBlogViewController ()< UITextFieldDelegate, @@ -53,6 +56,8 @@ @interface CreateAccountAndBlogViewController ()< CGFloat _viewHeight; NSDictionary *_currentLanguage; + + WPAccount *_account; } @end @@ -631,66 +636,81 @@ - (void)createUserAndSite [operation didSucceed]; }; void (^createUserFailure)(NSError *) = ^(NSError *error) { + DDLogError(@"Failed creating user: %@", error); [operation didFail]; [SVProgressHUD dismiss]; [self displayRemoteError:error]; }; - - [[WordPressComApi sharedApi] createWPComAccountWithEmail:_emailField.text - andUsername:_usernameField.text - andPassword:_passwordField.text - success:createUserSuccess - failure:createUserFailure]; - + + [[WordPressComApi anonymousApi] createWPComAccountWithEmail:_emailField.text + andUsername:_usernameField.text + andPassword:_passwordField.text + success:createUserSuccess + failure:createUserFailure]; + }]; WPAsyncBlockOperation *userSignIn = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ - void (^signInSuccess)(void) = ^{ + void (^signInSuccess)(NSString *authToken) = ^(NSString *authToken){ + _account = [WPAccount createOrUpdateWordPressComAccountWithUsername:_usernameField.text password:_passwordField.text authToken:authToken]; + if (![WPAccount defaultWordPressComAccount]) { + [WPAccount setDefaultWordPressComAccount:_account]; + } [operation didSucceed]; }; void (^signInFailure)(NSError *) = ^(NSError *error) { + DDLogError(@"Failed signing in user: %@", error); // We've hit a strange failure at this point, the user has been created successfully but for some reason // we are unable to sign in and proceed [operation didFail]; [SVProgressHUD dismiss]; [self displayRemoteError:error]; }; - - [[WordPressComApi sharedApi] signInWithUsername:_usernameField.text - password:_passwordField.text - success:signInSuccess - failure:signInFailure]; + + + WordPressComOAuthClient *client = [WordPressComOAuthClient client]; + [client authenticateWithUsername:_usernameField.text + password:_passwordField.text + success:signInSuccess + failure:signInFailure]; }]; - + WPAsyncBlockOperation *blogCreation = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ void (^createBlogSuccess)(id) = ^(id responseObject){ [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXCreateAccountCreatedAccount]; [operation didSucceed]; - [SVProgressHUD dismiss]; - if (self.onCreatedUser) { - self.onCreatedUser(_usernameField.text, _passwordField.text); + + NSMutableDictionary *blogOptions = [[responseObject dictionaryForKey:@"blog_details"] mutableCopy]; + if ([blogOptions objectForKey:@"blogname"]) { + [blogOptions setObject:[blogOptions objectForKey:@"blogname"] forKey:@"blogName"]; + [blogOptions removeObjectForKey:@"blogname"]; } + Blog *blog = [_account findOrCreateBlogFromDictionary:blogOptions withContext:_account.managedObjectContext]; + [blog dataSave]; + [blog syncBlogWithSuccess:nil failure:nil]; + [SVProgressHUD dismiss]; + [self dismissViewControllerAnimated:YES completion:nil]; }; void (^createBlogFailure)(NSError *error) = ^(NSError *error) { + DDLogError(@"Failed creating blog: %@", error); [SVProgressHUD dismiss]; [operation didFail]; [self displayRemoteError:error]; }; - - NSNumber *languageId = [_currentLanguage objectForKey:@"lang_id"]; - [[WordPressComApi sharedApi] createWPComBlogWithUrl:[self getSiteAddressWithoutWordPressDotCom] - andBlogTitle:[self generateSiteTitleFromUsername:_usernameField.text] - andLanguageId:languageId - andBlogVisibility:WordPressComApiBlogVisibilityPublic - success:createBlogSuccess - failure:createBlogFailure]; + NSNumber *languageId = [_currentLanguage objectForKey:@"lang_id"]; + [[_account restApi] createWPComBlogWithUrl:[self getSiteAddressWithoutWordPressDotCom] + andBlogTitle:[self generateSiteTitleFromUsername:_usernameField.text] + andLanguageId:languageId + andBlogVisibility:WordPressComApiBlogVisibilityPublic + success:createBlogSuccess + failure:createBlogFailure]; }]; - + [blogCreation addDependency:userSignIn]; [userSignIn addDependency:userCreation]; - + [SVProgressHUD showWithStatus:NSLocalizedString(@"Creating User and Site", nil) maskType:SVProgressHUDMaskTypeBlack]; - + [_operationQueue addOperation:userCreation]; [_operationQueue addOperation:userSignIn]; [_operationQueue addOperation:blogCreation]; diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 542accba3e8b..a49ece7e1c3d 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -475,12 +475,6 @@ - (void)dismiss - (void)showCreateAccountView { CreateAccountAndBlogViewController *createAccountViewController = [[CreateAccountAndBlogViewController alloc] init]; - createAccountViewController.onCreatedUser = ^(NSString *username, NSString *password) { - _usernameText.text = username; - _passwordText.text = password; - _userIsDotCom = YES; - [self.navigationController popViewControllerAnimated:NO]; - }; [self.navigationController pushViewController:createAccountViewController animated:YES]; } diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 646da3714f6b..36aa9b23768f 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -39,6 +39,12 @@ extern NSString *const WordPressComApiErrorMessageKey; @property (nonatomic,readonly,strong) NSString *password; + (WordPressComApi *)sharedApi DEPRECATED_MSG_ATTRIBUTE("Use [[WPAccount defaultWordPressComAccount] restApi] instead"); +/** + Returns an API without an associated user + + Use this only for things that don't require an account, like signup or logged out reader + */ ++ (WordPressComApi *)anonymousApi; - (id)initWithOAuthToken:(NSString *)authToken; ///------------------------- diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index d4e58ea1eadc..b62bfd461b06 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -85,9 +85,23 @@ @implementation WordPressComApi { } + (WordPressComApi *)sharedApi { + DDLogWarn(@"Called obsolete [WordPressComApi sharedApi]"); return [[WPAccount defaultWordPressComAccount] restApi]; } ++ (WordPressComApi *)anonymousApi { + static WordPressComApi *_anonymousApi = nil; + static dispatch_once_t oncePredicate; + dispatch_once(&oncePredicate, ^{ + DDLogVerbose(@"Initializing anonymous API"); + _anonymousApi = [[self alloc] initWithBaseURL:[NSURL URLWithString:WordPressComApiClientEndpointURL] ]; + [_anonymousApi registerHTTPOperationClass:[WPJSONRequestOperation class]]; + [_anonymousApi setDefaultHeader:@"User-Agent" value:[[WordPressAppDelegate sharedWordPressApplicationDelegate] applicationUserAgent]]; + }); + + return _anonymousApi; +} + - (id)initWithOAuthToken:(NSString *)authToken { self = [super initWithBaseURL:[NSURL URLWithString:WordPressComApiClientEndpointURL]]; if (self) { From 9cdff98f92179d78e7281f7237b5e0ba267b0eef Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 21 Nov 2013 20:56:48 +0100 Subject: [PATCH 18/64] Show NUX when removing the last site --- WordPress/Classes/BlogListViewController.m | 6 ++++++ WordPress/Classes/WordPressAppDelegate.h | 1 + WordPress/Classes/WordPressAppDelegate.m | 10 +++++----- 3 files changed, 12 insertions(+), 5 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 987b27671802..721278635670 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -14,6 +14,7 @@ #import "WelcomeViewController.h" #import "BlogDetailsViewController.h" #import "WPTableViewCell.h" +#import "WPAccount.h" CGFloat const blavatarImageSize = 50.f; @@ -175,6 +176,11 @@ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEd dispatch_async(dispatch_get_main_queue(), ^{ self.editButtonItem.enabled = NO; [self setEditing:NO animated:YES]; + + // No blogs and signed out, show NUX + if (![WPAccount defaultWordPressComAccount]) { + [[WordPressAppDelegate sharedWordPressApplicationDelegate] showWelcomeScreenIfNeededAnimated:YES]; + } }); } } diff --git a/WordPress/Classes/WordPressAppDelegate.h b/WordPress/Classes/WordPressAppDelegate.h index 88eef362ce34..30d30981f444 100644 --- a/WordPress/Classes/WordPressAppDelegate.h +++ b/WordPress/Classes/WordPressAppDelegate.h @@ -79,5 +79,6 @@ - (void)openNotificationScreenWithOptions:(NSDictionary *)remoteNotif; - (void)useDefaultUserAgent; - (void)useAppUserAgent; +- (void)showWelcomeScreenIfNeededAnimated:(BOOL)animated; @end diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index d4040cb2e20d..a848f3f73ec0 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -254,7 +254,7 @@ - (BOOL)noBlogsAndNoWordPressDotComAccount { return [blogs count] == 0 && ![WPAccount defaultWordPressComAccount]; } -- (void)showWelcomeScreenIfNeeded { +- (void)showWelcomeScreenIfNeededAnimated:(BOOL)animated { if ([self noBlogsAndNoWordPressDotComAccount]) { [WordPressAppDelegate wipeAllKeychainItems]; @@ -266,9 +266,9 @@ - (void)showWelcomeScreenIfNeeded { UIViewController *presenter = window.rootViewController; if (presenter.presentedViewController) { - [presenter dismissViewControllerAnimated:NO completion:nil]; + [presenter dismissViewControllerAnimated:animated completion:nil]; } - [window.rootViewController presentViewController:aNavigationController animated:NO completion:nil]; + [window.rootViewController presentViewController:aNavigationController animated:animated completion:nil]; } } @@ -385,7 +385,7 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:( window.backgroundColor = [UIColor blackColor]; window.rootViewController = [self createTabBarController]; - [self showWelcomeScreenIfNeeded]; + [self showWelcomeScreenIfNeededAnimated:NO]; //listener for XML-RPC errors //in the future we could put the errors message in a dedicated screen that users can bring to front when samething went wrong, and can take a look at the error msg. @@ -1095,7 +1095,7 @@ - (void)toggleExtraDebuggingIfNeeded { - (void)handleDefaultAccountChangedNotification:(NSNotification *)notification { [self toggleExtraDebuggingIfNeeded]; - [self showWelcomeScreenIfNeeded]; + [self showWelcomeScreenIfNeededAnimated:NO]; } - (void)showNotificationsTab { From 8ea6128d79d26f44e99fcae3c63b386b77ef18fb Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 22 Nov 2013 00:04:17 +0100 Subject: [PATCH 19/64] Reuse Login Controller for settings and add site --- WordPress/Classes/BlogListViewController.m | 34 ++++-- .../Classes/FakePushTransitionAnimator.h | 13 +++ .../Classes/FakePushTransitionAnimator.m | 60 +++++++++++ WordPress/Classes/LoginViewController.h | 4 +- WordPress/Classes/LoginViewController.m | 100 +++++++++++++----- WordPress/Classes/SettingsViewController.m | 30 ++---- WordPress/WordPress.xcodeproj/project.pbxproj | 6 ++ 7 files changed, 190 insertions(+), 57 deletions(-) create mode 100644 WordPress/Classes/FakePushTransitionAnimator.h create mode 100644 WordPress/Classes/FakePushTransitionAnimator.m diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 721278635670..a6e5733e3b00 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -11,14 +11,15 @@ #import "UIImageView+Gravatar.h" #import "WordPressComApi.h" #import "SettingsViewController.h" -#import "WelcomeViewController.h" +#import "LoginViewController.h" #import "BlogDetailsViewController.h" #import "WPTableViewCell.h" #import "WPAccount.h" +#import "FakePushTransitionAnimator.h" CGFloat const blavatarImageSize = 50.f; -@interface BlogListViewController () +@interface BlogListViewController () @property (nonatomic, strong) NSFetchedResultsController *resultsController; @property (nonatomic, strong) UIBarButtonItem *settingsButton; @@ -71,6 +72,7 @@ - (void)viewDidLoad - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + [self.navigationController setNavigationBarHidden:NO animated:animated]; self.resultsController.delegate = self; [self.resultsController performFetch:nil]; [self.tableView reloadData]; @@ -247,10 +249,18 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath [self.navigationController pushViewController:blogDetailsViewController animated:YES]; } else { [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedAddBlog]; - - WelcomeViewController *welcomeViewController = [[WelcomeViewController alloc] initWithStyle:UITableViewStyleGrouped]; - welcomeViewController.title = NSLocalizedString(@"Add a Site", nil); - [self.navigationController pushViewController:welcomeViewController animated:YES]; + + LoginViewController *loginViewController = [[LoginViewController alloc] init]; + if (![WPAccount defaultWordPressComAccount]) { + loginViewController.prefersSelfHosted = YES; + } + loginViewController.dismissBlock = ^{ + [self dismissViewControllerAnimated:YES completion:nil]; + }; + UINavigationController *loginNavigationController = [[UINavigationController alloc] initWithRootViewController:loginViewController]; + loginNavigationController.transitioningDelegate = self; + loginNavigationController.modalTransitionStyle = UIModalPresentationCustom; + [self presentViewController:loginNavigationController animated:YES completion:nil]; } } @@ -330,5 +340,17 @@ - (void)controller:(NSFetchedResultsController *)controller } } +#pragma mark - UIViewControllerTransitioningDelegate + +- (id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { + FakePushTransitionAnimator *animator = [FakePushTransitionAnimator new]; + animator.presenting = YES; + return animator; +} + +- (id )animationControllerForDismissedController:(UIViewController *)dismissed { + FakePushTransitionAnimator *animator = [FakePushTransitionAnimator new]; + return animator; +} @end diff --git a/WordPress/Classes/FakePushTransitionAnimator.h b/WordPress/Classes/FakePushTransitionAnimator.h new file mode 100644 index 000000000000..7db11813ac16 --- /dev/null +++ b/WordPress/Classes/FakePushTransitionAnimator.h @@ -0,0 +1,13 @@ +// +// FakePushTransitionAnimator.h +// WordPress +// +// Created by Jorge Bernal on 21/11/13. +// Copyright (c) 2013 WordPress. All rights reserved. +// + +#import + +@interface FakePushTransitionAnimator : NSObject +@property (nonatomic, assign, getter = isPresenting) BOOL presenting; +@end diff --git a/WordPress/Classes/FakePushTransitionAnimator.m b/WordPress/Classes/FakePushTransitionAnimator.m new file mode 100644 index 000000000000..c47dffe3dd2a --- /dev/null +++ b/WordPress/Classes/FakePushTransitionAnimator.m @@ -0,0 +1,60 @@ +// +// FakePushTransitionAnimator.m +// WordPress +// +// Created by Jorge Bernal on 21/11/13. +// Copyright (c) 2013 WordPress. All rights reserved. +// + +#import "FakePushTransitionAnimator.h" + +@implementation FakePushTransitionAnimator + +- (NSTimeInterval)transitionDuration:(id )transitionContext { + return 0.3; +} + +- (void)animateTransition:(id )transitionContext { + // Grab the from and to view controllers from the context + UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; + UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; + + // Set our ending frame. We'll modify this later if we have to + CGRect endFrame = fromViewController.view.frame; + + if (self.presenting) { + fromViewController.view.userInteractionEnabled = NO; + + [transitionContext.containerView addSubview:fromViewController.view]; + [transitionContext.containerView addSubview:toViewController.view]; + + CGRect startFrame = endFrame; + startFrame.origin.x += endFrame.size.width; + + toViewController.view.frame = startFrame; + + [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ + fromViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed; + toViewController.view.frame = endFrame; + } completion:^(BOOL finished) { + [transitionContext completeTransition:YES]; + }]; + } + else { + toViewController.view.userInteractionEnabled = YES; + + [transitionContext.containerView addSubview:toViewController.view]; + [transitionContext.containerView addSubview:fromViewController.view]; + + endFrame.origin.x += endFrame.size.width; + + [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ + toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic; + fromViewController.view.frame = endFrame; + } completion:^(BOOL finished) { + [transitionContext completeTransition:YES]; + }]; + } +} + +@end diff --git a/WordPress/Classes/LoginViewController.h b/WordPress/Classes/LoginViewController.h index 9b9efdb699bc..d819ea3d1e9b 100644 --- a/WordPress/Classes/LoginViewController.h +++ b/WordPress/Classes/LoginViewController.h @@ -9,5 +9,7 @@ #import @interface LoginViewController : UIViewController - +@property (nonatomic, assign) BOOL onlyDotComAllowed; +@property (nonatomic, assign) BOOL prefersSelfHosted; +@property (nonatomic, copy) void (^dismissBlock)(); @end diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index a49ece7e1c3d..857c8e79c241 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -26,6 +26,7 @@ #import "WPWalkthroughOverlayView.h" #import "ReachabilityUtils.h" #import "WPNUXUtility.h" +#import "WPNUXBackButton.h" #import "WPAccount.h" #import "ReaderPost.h" #import "Note.h" @@ -43,7 +44,8 @@ @interface LoginViewController () < WPWalkthroughTextField *_passwordText; WPWalkthroughTextField *_siteUrlText; WPNUXMainButton *_signInButton; - + WPNUXBackButton *_cancelButton; + // Measurements CGFloat _viewWidth; CGFloat _viewHeight; @@ -83,7 +85,10 @@ - (void)viewDidLoad _viewHeight = [self.view formSheetViewHeight]; self.view.backgroundColor = [WPNUXUtility backgroundColor]; - _userIsDotCom = YES; + _userIsDotCom = self.onlyDotComAllowed || !self.prefersSelfHosted; + if ([WPAccount defaultWordPressComAccount]) { + _userIsDotCom = NO; + } [self addMainView]; [self initializeView]; @@ -129,13 +134,13 @@ - (BOOL)textFieldShouldReturn:(UITextField *)textField { - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { - _signInButton.enabled = [self areDotComFieldsFilled]; + _signInButton.enabled = [self isSignInEnabled]; return YES; } - (BOOL)textFieldShouldEndEditing:(UITextField *)textField { - _signInButton.enabled = [self areDotComFieldsFilled]; + _signInButton.enabled = [self isSignInEnabled]; return YES; } @@ -143,6 +148,7 @@ - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRang { BOOL isUsernameFilled = [self isUsernameFilled]; BOOL isPasswordFilled = [self isPasswordFilled]; + BOOL isSiteUrlFilled = [self isSiteUrlFilled]; NSMutableString *updatedString = [[NSMutableString alloc] initWithString:textField.text]; [updatedString replaceCharactersInRange:range withString:string]; @@ -151,8 +157,10 @@ - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRang isUsernameFilled = updatedStringHasContent; } else if (textField == _passwordText) { isPasswordFilled = updatedStringHasContent; + } else if (textField == _siteUrlText) { + isSiteUrlFilled = updatedStringHasContent; } - _signInButton.enabled = isUsernameFilled && isPasswordFilled; + _signInButton.enabled = isUsernameFilled && isPasswordFilled && (_userIsDotCom || isSiteUrlFilled); return YES; } @@ -304,6 +312,12 @@ - (void)toggleSignInformAction:(id)sender { }]; } +- (void)cancelButtonAction:(id)sender { + if (self.dismissBlock) { + self.dismissBlock(); + } +} + #pragma mark - Private Methods - (void)addMainView @@ -390,27 +404,41 @@ - (void)addControls // Add Sign In Button if (_signInButton == nil) { _signInButton = [[WPNUXMainButton alloc] init]; - [_signInButton setTitle:NSLocalizedString(@"Sign In", nil) forState:UIControlStateNormal]; [_signInButton addTarget:self action:@selector(signInButtonAction:) forControlEvents:UIControlEventTouchUpInside]; [_mainView addSubview:_signInButton]; _signInButton.enabled = NO; } - - // Add Account type toggle - if (_toggleSignInForm == nil) { - _toggleSignInForm = [[WPNUXSecondaryButton alloc] init]; - [_toggleSignInForm addTarget:self action:@selector(toggleSignInformAction:) forControlEvents:UIControlEventTouchUpInside]; - [_mainView addSubview:_toggleSignInForm]; + NSString *signInTitle = _userIsDotCom ? NSLocalizedString(@"Sign In", nil) : NSLocalizedString(@"Add Site", nil); + [_signInButton setTitle:signInTitle forState:UIControlStateNormal]; + + // Add Cancel Button + if (self.dismissBlock && _cancelButton == nil) { + _cancelButton = [[WPNUXBackButton alloc] init]; + [_cancelButton setTitle:NSLocalizedString(@"Cancel", nil) forState:UIControlStateNormal]; + [_cancelButton addTarget:self action:@selector(cancelButtonAction:) forControlEvents:UIControlEventTouchUpInside]; + [_cancelButton sizeToFit]; + [self.view addSubview:_cancelButton]; } - NSString *toggleTitle = _userIsDotCom ? NSLocalizedString(@"Add Self-Hosted Site", nil) : NSLocalizedString(@"Sign in to WordPress.com", nil); - [_toggleSignInForm setTitle:toggleTitle forState:UIControlStateNormal]; - - // Add Skip to Create Account Button - if (_skipToCreateAccount == nil) { - _skipToCreateAccount = [[WPNUXSecondaryButton alloc] init]; - [_skipToCreateAccount setTitle:NSLocalizedString(@"Create Account", nil) forState:UIControlStateNormal]; - [_skipToCreateAccount addTarget:self action:@selector(clickedSkipToCreate:) forControlEvents:UIControlEventTouchUpInside]; - [_mainView addSubview:_skipToCreateAccount]; + + if (!self.onlyDotComAllowed && ![WPAccount defaultWordPressComAccount]) { + // Add Account type toggle + if (_toggleSignInForm == nil) { + _toggleSignInForm = [[WPNUXSecondaryButton alloc] init]; + [_toggleSignInForm addTarget:self action:@selector(toggleSignInformAction:) forControlEvents:UIControlEventTouchUpInside]; + [_mainView addSubview:_toggleSignInForm]; + } + NSString *toggleTitle = _userIsDotCom ? NSLocalizedString(@"Add Self-Hosted Site", nil) : NSLocalizedString(@"Sign in to WordPress.com", nil); + [_toggleSignInForm setTitle:toggleTitle forState:UIControlStateNormal]; + } + + if (![WPAccount defaultWordPressComAccount]) { + // Add Skip to Create Account Button + if (_skipToCreateAccount == nil) { + _skipToCreateAccount = [[WPNUXSecondaryButton alloc] init]; + [_skipToCreateAccount setTitle:NSLocalizedString(@"Create Account", nil) forState:UIControlStateNormal]; + [_skipToCreateAccount addTarget:self action:@selector(clickedSkipToCreate:) forControlEvents:UIControlEventTouchUpInside]; + [_mainView addSubview:_skipToCreateAccount]; + } } } @@ -425,7 +453,14 @@ - (void)layoutControls } _helpButton.frame = CGRectMake(_viewWidth - infoButtonImage.size.width, y, infoButtonImage.size.width, infoButtonImage.size.height); - + // Layout Cancel Button + x = 0; + y = 0.5 * GeneralWalkthroughStandardOffset; + if (IS_IOS7 && IS_IPHONE) { + y += GeneralWalkthroughiOS7StatusBarOffset; + } + _cancelButton.frame = CGRectMake(x, y, CGRectGetWidth(_cancelButton.frame), CGRectGetHeight(_cancelButton.frame)); + CGFloat heightOfControls = CGRectGetHeight(_icon.frame) + GeneralWalkthroughStandardOffset + (_userIsDotCom ? 2 : 3) * GeneralWalkthroughTextFieldHeight + GeneralWalkthroughStandardOffset + GeneralWalkthroughButtonHeight; CGFloat startingYForCenteredControls = floorf((_viewHeight - 2 * GeneralWalkthroughSecondaryButtonHeight - heightOfControls)/2.0); @@ -562,6 +597,20 @@ - (BOOL)isPasswordFilled return [[_passwordText.text trim] length] != 0; } +- (BOOL)isSiteUrlFilled +{ + return [[_siteUrlText.text trim] length] != 0; +} + +- (BOOL)isSignInEnabled +{ + if (_userIsDotCom) { + return [self areDotComFieldsFilled]; + } else { + return [self areSelfHostedFieldsFilled]; + } +} + - (BOOL)areDotComFieldsFilled { return [self isUsernameFilled] && [self isPasswordFilled]; @@ -569,7 +618,7 @@ - (BOOL)areDotComFieldsFilled - (BOOL)areSelfHostedFieldsFilled { - return [self areDotComFieldsFilled] && [[_siteUrlText.text trim] length] != 0; + return [self areDotComFieldsFilled] && [self isSiteUrlFilled]; } - (BOOL)hasUserOnlyEnteredValuesForDotCom @@ -577,11 +626,6 @@ - (BOOL)hasUserOnlyEnteredValuesForDotCom return [self areDotComFieldsFilled] && ![self areSelfHostedFieldsFilled]; } -- (BOOL)areFieldsFilled -{ - return [[_usernameText.text trim] length] != 0 && [[_passwordText.text trim] length] != 0 && [[_siteUrlText.text trim] length] != 0; -} - - (BOOL)isUrlValid { NSURL *siteURL = [NSURL URLWithString:_siteUrlText.text]; diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index 70a87557cae5..d05178513d46 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -32,7 +32,6 @@ #import "WordPressAppDelegate.h" #import "EditSiteViewController.h" #import "WelcomeViewController.h" -#import "WPcomLoginViewController.h" #import "UIImageView+Gravatar.h" #import "WordPressComApi.h" #import "AboutViewController.h" @@ -55,7 +54,7 @@ CGFloat const blavatarImageViewSize = 43.f; -@interface SettingsViewController () +@interface SettingsViewController () @property (nonatomic, strong) NSArray *mediaSettingsArray; @property (nonatomic, strong) UIBarButtonItem *doneButton; @@ -111,6 +110,7 @@ - (void)viewWillDisappear:(BOOL)animated { - (void)viewWillAppear:(BOOL)animated { [super viewWillAppear:animated]; + [self.navigationController setNavigationBarHidden:NO animated:animated]; [self.tableView reloadData]; } @@ -406,9 +406,12 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } } else { [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedSignIntoDotCom]; - - WPcomLoginViewController *loginViewController = [[WPcomLoginViewController alloc] initWithStyle:UITableViewStyleGrouped]; - loginViewController.delegate = self; + + LoginViewController *loginViewController = [[LoginViewController alloc] init]; + loginViewController.onlyDotComAllowed = YES; + loginViewController.dismissBlock = ^{ + [self.navigationController popToViewController:self animated:YES]; + }; [self.navigationController pushViewController:loginViewController animated:YES]; } @@ -439,23 +442,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath } } - -#pragma mark - -#pragma mark WPComLoginViewControllerDelegate - -- (void)loginController:(WPcomLoginViewController *)loginController didAuthenticateWithAccount:(WPAccount *)account { - [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:SettingsSectionWpcom] withRowAnimation:UITableViewRowAnimationFade]; - AddUsersBlogsViewController *addUsersBlogsView = [[AddUsersBlogsViewController alloc] initWithAccount:[WPAccount defaultWordPressComAccount]]; - addUsersBlogsView.isWPcom = YES; - [self.navigationController pushViewController:addUsersBlogsView animated:YES]; -} - - -- (void)loginControllerDidDismiss:(WPcomLoginViewController *)loginController { - [self.navigationController popToRootViewControllerAnimated:YES]; -} - - #pragma mark - #pragma mark Action Sheet Delegate Methods diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 92200870d8c3..6a1920d035ff 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -891,6 +891,7 @@ E19DF741141F7BDD000002F3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E19DF740141F7BDD000002F3 /* libz.dylib */; }; E1A03EE217422DCF0085D192 /* BlogToAccount.m in Sources */ = {isa = PBXBuildFile; fileRef = E1A03EE117422DCE0085D192 /* BlogToAccount.m */; }; E1A03F48174283E10085D192 /* BlogToJetpackAccount.m in Sources */ = {isa = PBXBuildFile; fileRef = E1A03F47174283E00085D192 /* BlogToJetpackAccount.m */; }; + E1A0E3C9183EC0FE005E911E /* FakePushTransitionAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = E1A0E3C8183EC0FE005E911E /* FakePushTransitionAnimator.m */; }; E1A0FAE7162F11CF0063B098 /* UIDevice+WordPressIdentifier.m in Sources */ = {isa = PBXBuildFile; fileRef = E1A0FAE6162F11CE0063B098 /* UIDevice+WordPressIdentifier.m */; }; E1A386C814DB05C300954CF8 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1A386C714DB05C300954CF8 /* AVFoundation.framework */; }; E1A386CA14DB05F700954CF8 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1A386C914DB05F700954CF8 /* CoreMedia.framework */; }; @@ -2071,6 +2072,8 @@ E1A03EE117422DCE0085D192 /* BlogToAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlogToAccount.m; sourceTree = ""; }; E1A03F46174283DF0085D192 /* BlogToJetpackAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlogToJetpackAccount.h; sourceTree = ""; }; E1A03F47174283E00085D192 /* BlogToJetpackAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlogToJetpackAccount.m; sourceTree = ""; }; + E1A0E3C7183EC0FE005E911E /* FakePushTransitionAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FakePushTransitionAnimator.h; sourceTree = ""; }; + E1A0E3C8183EC0FE005E911E /* FakePushTransitionAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FakePushTransitionAnimator.m; sourceTree = ""; }; E1A0FAE5162F11CE0063B098 /* UIDevice+WordPressIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIDevice+WordPressIdentifier.h"; sourceTree = ""; }; E1A0FAE6162F11CE0063B098 /* UIDevice+WordPressIdentifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+WordPressIdentifier.m"; sourceTree = ""; }; E1A386C714DB05C300954CF8 /* AVFoundation.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; @@ -3070,6 +3073,8 @@ 857F961417D950AB0071D9D1 /* WPTableViewSectionHeaderView.m */, 857F961617D95F530071D9D1 /* WPTableViewSectionFooterView.h */, 857F961717D95F530071D9D1 /* WPTableViewSectionFooterView.m */, + E1A0E3C7183EC0FE005E911E /* FakePushTransitionAnimator.h */, + E1A0E3C8183EC0FE005E911E /* FakePushTransitionAnimator.m */, ); name = "iOS 7"; sourceTree = ""; @@ -5192,6 +5197,7 @@ 5D2A8FF2175EC15800263144 /* ReaderTextFormView.m in Sources */, 5D477099175F73CA0086C6A3 /* ReaderCommentFormView.m in Sources */, 5D5A953B1760DDE0000F7A1E /* ReaderReblogFormView.m in Sources */, + E1A0E3C9183EC0FE005E911E /* FakePushTransitionAnimator.m in Sources */, 857F961817D95F530071D9D1 /* WPTableViewSectionFooterView.m in Sources */, 5D8572BA17611B36004CC20D /* ReaderUsersBlogsViewController.m in Sources */, E174F6E6172A73960004F23A /* WPAccount.m in Sources */, From b374dd74e718ead9ad1b6eb8b3ffe83919f93690 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 22 Nov 2013 01:08:32 +0100 Subject: [PATCH 20/64] Removed WelcomeViewController --- WordPress/Classes/SettingsViewController.m | 1 - WordPress/Classes/WPMobileStats.h | 5 - WordPress/Classes/WPMobileStats.m | 5 - WordPress/Classes/WelcomeViewController.h | 13 -- WordPress/Classes/WelcomeViewController.m | 205 ------------------ WordPress/WordPress.xcodeproj/project.pbxproj | 6 - 6 files changed, 235 deletions(-) delete mode 100644 WordPress/Classes/WelcomeViewController.h delete mode 100644 WordPress/Classes/WelcomeViewController.m diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index d05178513d46..3037f0341980 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -31,7 +31,6 @@ #import "SettingsViewController.h" #import "WordPressAppDelegate.h" #import "EditSiteViewController.h" -#import "WelcomeViewController.h" #import "UIImageView+Gravatar.h" #import "WordPressComApi.h" #import "AboutViewController.h" diff --git a/WordPress/Classes/WPMobileStats.h b/WordPress/Classes/WPMobileStats.h index cbdc5bb027c0..2d3100dec5a7 100644 --- a/WordPress/Classes/WPMobileStats.h +++ b/WordPress/Classes/WPMobileStats.h @@ -169,11 +169,6 @@ extern NSString *const StatsEventManageNotificationsDisabledBlogNotifications; extern NSString *const StatsEventQuickPhotoOpened; extern NSString *const StatsEventQuickPhotoPosted; -// Welcome View Controller -extern NSString *const StatsEventWelcomeViewControllerClickedAddSelfHostedBlog; -extern NSString *const StatsEventWelcomeViewControllerClickedAddWordpressDotComBlog; -extern NSString *const StatsEventWelcomeViewControllerClickedCreateWordpressDotComBlog; - // NUX Related extern NSString *const StatsEventNUXFirstWalkthroughOpened; extern NSString *const StatsEventNUXFirstWalkthroughClickedSkipToCreateAccount; diff --git a/WordPress/Classes/WPMobileStats.m b/WordPress/Classes/WPMobileStats.m index 73a6856a4757..3211575d05ba 100644 --- a/WordPress/Classes/WPMobileStats.m +++ b/WordPress/Classes/WPMobileStats.m @@ -174,11 +174,6 @@ NSString *const StatsEventQuickPhotoOpened = @"Quick Photo - Opened"; NSString *const StatsEventQuickPhotoPosted = @"Quick Photo - Posted"; -// Welcome View Controller -NSString *const StatsEventWelcomeViewControllerClickedAddSelfHostedBlog = @"Welcome View Controller - Add Self Hosted Blog"; -NSString *const StatsEventWelcomeViewControllerClickedAddWordpressDotComBlog = @"Welcome View Controller - Add Wordpress.com Blog"; -NSString *const StatsEventWelcomeViewControllerClickedCreateWordpressDotComBlog = @"Welcome View Controller - Create Wordpress.com Blog"; - // NUX First Walkthrough NSString *const StatsEventNUXFirstWalkthroughOpened = @"NUX - First Walkthrough - Opened"; NSString *const StatsEventNUXFirstWalkthroughClickedSkipToCreateAccount = @"NUX - First Walkthrough - Skipped to Create Account"; diff --git a/WordPress/Classes/WelcomeViewController.h b/WordPress/Classes/WelcomeViewController.h deleted file mode 100644 index a6255d0b7104..000000000000 --- a/WordPress/Classes/WelcomeViewController.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// WelcomeViewController.h -// WordPress -// -// Created by Sendhil Panchadsaram on 9/4/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import - -@interface WelcomeViewController : UITableViewController - -@end diff --git a/WordPress/Classes/WelcomeViewController.m b/WordPress/Classes/WelcomeViewController.m deleted file mode 100644 index e692a6d39679..000000000000 --- a/WordPress/Classes/WelcomeViewController.m +++ /dev/null @@ -1,205 +0,0 @@ -// -// WelcomeViewController.m -// WordPress -// -// Created by Sendhil Panchadsaram on 9/4/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import "WelcomeViewController.h" -#import "WordPressAppDelegate.h" -#import "AddSiteViewController.h" -#import "WPcomLoginViewController.h" -#import "CreateWPComAccountViewController.h" -#import "CreateWPComBlogViewController.h" -#import "AddUsersBlogsViewController.h" -#import "WordPressComApi.h" -#import "WPAccount.h" -#import "WPTableViewSectionHeaderView.h" - -@interface WelcomeViewController () < - WPcomLoginViewControllerDelegate, - CreateWPComAccountViewControllerDelegate, - CreateWPComBlogViewControllerDelegate> { - NSArray *_buttonTitles; - NSArray *_sectionHeaderTitles; - WordPressAppDelegate *__weak _appDelegate; -} - -@end - -@implementation WelcomeViewController - -- (id)initWithStyle:(UITableViewStyle)style -{ - self = [super initWithStyle:style]; - if (self) { - _buttonTitles = @[@[NSLocalizedString(@"Add Self-Hosted Site", nil), NSLocalizedString(@"Add WordPress.com Site", nil)], @[NSLocalizedString(@"Create WordPress.com Site", nil)]]; - _sectionHeaderTitles = @[NSLocalizedString(@"Add an existing Site:", nil), NSLocalizedString(@"Start a new Site:", nil)]; - } - return self; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - _appDelegate = (WordPressAppDelegate *)[[UIApplication sharedApplication] delegate]; - - [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; - - [self.tableView registerClass:[WPTableViewCell class] forCellReuseIdentifier:@"Cell"]; -} - -#pragma mark - Table view data source - -- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { - WPTableViewSectionHeaderView *header = [[WPTableViewSectionHeaderView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 0)]; - header.title = [self titleForHeaderInSection:section]; - return header; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section -{ - NSString *title = [self titleForHeaderInSection:section]; - return [WPTableViewSectionHeaderView heightForTitle:title andWidth:CGRectGetWidth(self.view.bounds)]; -} - -- (NSString *)titleForHeaderInSection:(NSInteger)section -{ - return _sectionHeaderTitles[section]; -} - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView -{ - // Return the number of sections. - return [_buttonTitles count]; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - // Return the number of rows in the section. - return [_buttonTitles[section] count]; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - static NSString *CellIdentifier = @"Cell"; - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; - - cell.textLabel.text = _buttonTitles[indexPath.section][indexPath.row]; - cell.textLabel.textAlignment = NSTextAlignmentCenter; - cell.textLabel.font = [WPStyleGuide tableviewTextFont]; - cell.textLabel.textColor = [WPStyleGuide tableViewActionColor]; - - return cell; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - if ([self isIndexPathForAddSelfHostedBlog:indexPath]) { - [self handleAddSelfHostedBlog]; - } else if ([self isIndexPathForAddWordPressDotComBlog:indexPath]) { - [self handleAddWordPressDotComBlog]; - } else if ([self isIndexPathForCreateWordPressDotComBlog:indexPath]) { - [self handleCreateWordPressDotComBlog]; - } -} - -#pragma mark - Private Methods - -- (BOOL)isIndexPathForAddSelfHostedBlog:(NSIndexPath *)indexPath -{ - return indexPath.section == 0 && indexPath.row == 0; -} - -- (BOOL)isIndexPathForAddWordPressDotComBlog:(NSIndexPath *)indexPath -{ - return indexPath.section == 0 && indexPath.row == 1; -} - -- (BOOL)isIndexPathForCreateWordPressDotComBlog:(NSIndexPath *)indexPath -{ - return indexPath.section == 1 && indexPath.row == 0; -} - -- (void)handleAddSelfHostedBlog -{ - [WPMobileStats trackEventForWPCom:StatsEventWelcomeViewControllerClickedAddSelfHostedBlog]; - - AddSiteViewController *addSiteView = [[AddSiteViewController alloc] initWithNibName:nil bundle:nil]; - [self.navigationController pushViewController:addSiteView animated:YES]; -} - - -- (void)handleAddWordPressDotComBlog -{ - [WPMobileStats trackEventForWPCom:StatsEventWelcomeViewControllerClickedAddWordpressDotComBlog]; - - if(_appDelegate.isWPcomAuthenticated) { - AddUsersBlogsViewController *addUsersBlogsView = [[AddUsersBlogsViewController alloc] initWithAccount:[WPAccount defaultWordPressComAccount]]; - addUsersBlogsView.isWPcom = YES; - [self.navigationController pushViewController:addUsersBlogsView animated:YES]; - } - else { - WPcomLoginViewController *wpLoginView = [[WPcomLoginViewController alloc] initWithStyle:UITableViewStyleGrouped]; - wpLoginView.delegate = self; - [self.navigationController pushViewController:wpLoginView animated:YES]; - } -} - -- (void)handleCreateWordPressDotComBlog -{ - [WPMobileStats trackEventForWPCom:StatsEventWelcomeViewControllerClickedCreateWordpressDotComBlog]; - - if ([WordPressComApi sharedApi].hasCredentials) { - CreateWPComBlogViewController *viewController = [[CreateWPComBlogViewController alloc] initWithStyle:UITableViewStyleGrouped]; - viewController.delegate = self; - [self.navigationController pushViewController:viewController animated:YES]; - } else { - CreateWPComAccountViewController *viewController = [[CreateWPComAccountViewController alloc] initWithStyle:UITableViewStyleGrouped]; - viewController.delegate = self; - [self.navigationController pushViewController:viewController animated:YES]; - } -} - -#pragma mark - WPcomLoginViewControllerDelegate - -- (void)loginControllerDidDismiss:(WPcomLoginViewController *)loginController { - [self.navigationController popViewControllerAnimated:YES]; -} - - -- (void)loginController:(WPcomLoginViewController *)loginController didAuthenticateWithAccount:(WPAccount *)account { - [self.navigationController popViewControllerAnimated:NO]; - [self handleAddWordPressDotComBlog]; -} - -#pragma mark - CreateWPComAccountViewControllerDelegate - -- (void)createdAndSignedInAccountWithUserName:(NSString *)userName -{ - [self.navigationController popViewControllerAnimated:NO]; - [self handleAddWordPressDotComBlog]; -} - -- (void)createdAccountWithUserName:(NSString *)userName -{ - // In this case the user was able to create an account but for some reason was unable to sign in. - // Just present the login controller in this case with the data prefilled and give the user the chance to sign in again - [self.navigationController popViewControllerAnimated:NO]; - WPcomLoginViewController *wpLoginView = [[WPcomLoginViewController alloc] initWithStyle:UITableViewStyleGrouped]; - wpLoginView.delegate = self; - wpLoginView.predefinedUsername = userName; - [self.navigationController pushViewController:wpLoginView animated:YES]; -} - -#pragma mark - CreateWPComBlogViewControllerDelegate - -- (void)createdBlogWithDetails:(NSDictionary *)blogDetails -{ - [self.navigationController popToRootViewControllerAnimated:YES]; -} - - -@end diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 6a1920d035ff..f0ca06b18d4b 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -645,7 +645,6 @@ 85495F6717C6FACF00871A7A /* icon-comments-edit.png in Resources */ = {isa = PBXBuildFile; fileRef = 85495F5717C6FACF00871A7A /* icon-comments-edit.png */; }; 85495F6817C6FACF00871A7A /* icon-comments-edit-active@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 85495F5817C6FACF00871A7A /* icon-comments-edit-active@2x.png */; }; 85495F6917C6FACF00871A7A /* icon-comments-edit-active.png in Resources */ = {isa = PBXBuildFile; fileRef = 85495F5917C6FACF00871A7A /* icon-comments-edit-active.png */; }; - 854E6B8D17D7BEBC00CCCFDD /* WelcomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 854E6B8C17D7BEBC00CCCFDD /* WelcomeViewController.m */; }; 8566BC95170F84BC003C6BCF /* CreateWPComAccountViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8566BC93170F84BC003C6BCF /* CreateWPComAccountViewController.m */; }; 857F55B517CEA01A00E154E1 /* WPKeyboardToolbarBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 857F55B417CEA01A00E154E1 /* WPKeyboardToolbarBase.m */; }; 857F55B817CEA2B200E154E1 /* WPKeyboardToolbarWithoutGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 857F55B717CEA2B200E154E1 /* WPKeyboardToolbarWithoutGradient.m */; }; @@ -1730,8 +1729,6 @@ 85495F5717C6FACF00871A7A /* icon-comments-edit.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-comments-edit.png"; sourceTree = ""; }; 85495F5817C6FACF00871A7A /* icon-comments-edit-active@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-comments-edit-active@2x.png"; sourceTree = ""; }; 85495F5917C6FACF00871A7A /* icon-comments-edit-active.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-comments-edit-active.png"; sourceTree = ""; }; - 854E6B8B17D7BEBC00CCCFDD /* WelcomeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WelcomeViewController.h; sourceTree = ""; }; - 854E6B8C17D7BEBC00CCCFDD /* WelcomeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WelcomeViewController.m; sourceTree = ""; }; 8566BC92170F84BC003C6BCF /* CreateWPComAccountViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CreateWPComAccountViewController.h; sourceTree = ""; }; 8566BC93170F84BC003C6BCF /* CreateWPComAccountViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CreateWPComAccountViewController.m; sourceTree = ""; }; 857F55B317CEA01900E154E1 /* WPKeyboardToolbarBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPKeyboardToolbarBase.h; sourceTree = ""; }; @@ -3327,8 +3324,6 @@ 85D8055C171631F10075EEAC /* SelectWPComLanguageViewController.m */, 85149745171E671000B87F3F /* SelectWPComBlogVisibilityViewController.h */, 85149746171E671000B87F3F /* SelectWPComBlogVisibilityViewController.m */, - 854E6B8B17D7BEBC00CCCFDD /* WelcomeViewController.h */, - 854E6B8C17D7BEBC00CCCFDD /* WelcomeViewController.m */, ); name = Blog; sourceTree = ""; @@ -5126,7 +5121,6 @@ CC0199E9165C17020073A966 /* NotificationsCommentDetailViewController.m in Sources */, 372AD15516682BA100F21BC1 /* NotificationsFollowDetailViewController.m in Sources */, 379DA051166E938E001A43CC /* NotificationsFollowTableViewCell.m in Sources */, - 854E6B8D17D7BEBC00CCCFDD /* WelcomeViewController.m in Sources */, CC669B1F1672C305009E16F8 /* FollowButton.m in Sources */, CC669B231672C328009E16F8 /* NoteCommentCell.m in Sources */, 93740DCB17D8F86700C41B2F /* WPAlertView.m in Sources */, From 10b88ea8226121dd2daf305fa1626d7b10619467 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 22 Nov 2013 01:16:18 +0100 Subject: [PATCH 21/64] Deleted unused controllers --- WordPress/Classes/AddSiteViewController.h | 12 - WordPress/Classes/AddSiteViewController.m | 172 ----- .../Classes/AddUsersBlogsViewController.h | 42 -- .../Classes/AddUsersBlogsViewController.m | 609 ------------------ .../CreateWPComAccountViewController.h | 23 - .../CreateWPComAccountViewController.m | 506 --------------- .../Classes/CreateWPComBlogViewController.h | 22 - .../Classes/CreateWPComBlogViewController.m | 392 ----------- WordPress/Classes/LoginViewController.m | 1 - .../Classes/NewAddUsersBlogViewController.h | 22 - .../Classes/NewAddUsersBlogViewController.m | 459 ------------- .../SelectWPComBlogVisibilityViewController.h | 24 - .../SelectWPComBlogVisibilityViewController.m | 109 ---- WordPress/Classes/SettingsViewController.m | 1 - WordPress/WordPress.xcodeproj/project.pbxproj | 36 -- 15 files changed, 2430 deletions(-) delete mode 100644 WordPress/Classes/AddSiteViewController.h delete mode 100644 WordPress/Classes/AddSiteViewController.m delete mode 100644 WordPress/Classes/AddUsersBlogsViewController.h delete mode 100644 WordPress/Classes/AddUsersBlogsViewController.m delete mode 100644 WordPress/Classes/CreateWPComAccountViewController.h delete mode 100644 WordPress/Classes/CreateWPComAccountViewController.m delete mode 100644 WordPress/Classes/CreateWPComBlogViewController.h delete mode 100644 WordPress/Classes/CreateWPComBlogViewController.m delete mode 100644 WordPress/Classes/NewAddUsersBlogViewController.h delete mode 100644 WordPress/Classes/NewAddUsersBlogViewController.m delete mode 100644 WordPress/Classes/SelectWPComBlogVisibilityViewController.h delete mode 100644 WordPress/Classes/SelectWPComBlogVisibilityViewController.m diff --git a/WordPress/Classes/AddSiteViewController.h b/WordPress/Classes/AddSiteViewController.h deleted file mode 100644 index 58671b1b12a1..000000000000 --- a/WordPress/Classes/AddSiteViewController.h +++ /dev/null @@ -1,12 +0,0 @@ -// -// AddSiteViewController.h -// WordPress -// -// Created by Chris Boyd on 7/23/10. -// - -#import -#import "EditSiteViewController.h" - -@interface AddSiteViewController : EditSiteViewController -@end diff --git a/WordPress/Classes/AddSiteViewController.m b/WordPress/Classes/AddSiteViewController.m deleted file mode 100644 index 9914d24c004d..000000000000 --- a/WordPress/Classes/AddSiteViewController.m +++ /dev/null @@ -1,172 +0,0 @@ -// -// AddSiteViewController.m -// WordPress -// -// Created by Chris Boyd on 7/23/10. - -#import "AddSiteViewController.h" -#import "AddUsersBlogsViewController.h" -#import "WordPressComApi.h" -#import "JetpackSettingsViewController.h" -#import "WPAccount.h" -#import - -@interface EditSiteViewController (PrivateMethods) -- (void)validationDidFail:(id)wrong; -@end - -@implementation AddSiteViewController - -CGSize const AddSiteLogoSize = { 320.0, 70.0 }; - -- (void)viewDidLoad { - [super viewDidLoad]; - - [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; - - UIImageView *logoImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logo_wporg"]]; - logoImage.frame = CGRectMake(0.0f, 0.0f, AddSiteLogoSize.width, AddSiteLogoSize.height); - logoImage.autoresizingMask = UIViewAutoresizingFlexibleWidth; - logoImage.contentMode = UIViewContentModeCenter; - tableView.tableHeaderView = logoImage; - - saveButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Add", @"Add button to add a site from Settings.") style:[WPStyleGuide barButtonStyleForDone] target:self action:@selector(save:)]; - self.navigationItem.rightBarButtonItem = saveButton; - - self.navigationItem.title = NSLocalizedString(@"Add Blog", @""); -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - return nil; -} - -- (void)validationSuccess:(NSString *)xmlrpc { - DDLogInfo(@"hasSubsites: %@", subsites); - - if ([subsites count] > 0) { - // If the user has entered the URL of a site they own on a MultiSite install, - // assume they want to add that specific site. - NSDictionary *subsite = nil; - if ([subsites count] > 1) { - if (_blogId) { - subsite = [[subsites filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"blogid = %@", _blogId]] lastObject]; - } - if (!subsite) { - subsite = [[subsites filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"xmlrpc = %@", xmlrpc]] lastObject]; - } - } - - if (subsite == nil) { - subsite = [subsites objectAtIndex:0]; - } - - if ([subsites count] > 1 && [[subsite objectForKey:@"blogid"] isEqualToString:@"1"]) { - [self displayAddUsersBlogsForXmlRpc:xmlrpc]; - } else { - if (_isSiteDotCom) { - xmlrpc = [subsite objectForKey:@"xmlrpc"]; - } - [self createBlogWithXmlRpc:xmlrpc andBlogDetails:subsite]; - [self synchronizeNewlyAddedBlog]; - } - } else { - NSError *error = [NSError errorWithDomain:@"WordPress" code:0 userInfo:@{NSLocalizedDescriptionKey: NSLocalizedString(@"Sorry, you credentials were good but you don't seem to have access to any blogs", @"")}]; - [self validationDidFail:error]; - } - [self.navigationItem setHidesBackButton:NO animated:NO]; - saveButton.enabled = YES; -} - -- (void)displayAddUsersBlogsForXmlRpc:(NSString *)xmlrpc -{ - WPAccount *account = [WPAccount createOrUpdateSelfHostedAccountWithXmlrpc:xmlrpc username:self.username andPassword:self.password]; - - AddUsersBlogsViewController *addUsersBlogsView = [[AddUsersBlogsViewController alloc] initWithAccount:account]; - addUsersBlogsView.isWPcom = NO; - addUsersBlogsView.usersBlogs = subsites; - addUsersBlogsView.url = xmlrpc; - addUsersBlogsView.username = self.username; - addUsersBlogsView.password = self.password; - addUsersBlogsView.geolocationEnabled = self.geolocationEnabled; - [self.navigationController pushViewController:addUsersBlogsView animated:YES]; -} - -- (void)createBlogWithXmlRpc:(NSString *)xmlrpc andBlogDetails:(NSDictionary *)blogDetails -{ - NSAssert(blogDetails != nil, nil); - - WPAccount *account = [WPAccount createOrUpdateSelfHostedAccountWithXmlrpc:xmlrpc username:self.username andPassword:self.password]; - - NSMutableDictionary *newBlog = [NSMutableDictionary dictionaryWithDictionary:blogDetails]; - [newBlog setObject:xmlrpc forKey:@"xmlrpc"]; - - self.blog = [account findOrCreateBlogFromDictionary:newBlog withContext:[WordPressAppDelegate sharedWordPressApplicationDelegate].managedObjectContext]; - self.blog.geolocationEnabled = self.geolocationEnabled; - [self.blog dataSave]; -} - -- (void)synchronizeNewlyAddedBlog -{ - void (^successBlock)() = ^{ - [[WordPressComApi sharedApi] syncPushNotificationInfo]; - if (![self.blog isWPcom] && [self.blog hasJetpack]) { - [self connectToJetpack]; - } else { - [self dismiss]; - } - }; - void (^failureBlock)(NSError*) = ^(NSError * error) { - [SVProgressHUD dismiss]; - }; - [SVProgressHUD showWithStatus:NSLocalizedString(@"Reading blog options", @"") maskType:SVProgressHUDMaskTypeBlack]; - [self.blog syncBlogWithSuccess:successBlock failure:failureBlock]; -} - -- (void)connectToJetpack -{ - NSString *wpcomUsername = [[WPAccount defaultWordPressComAccount] username]; - NSString *wpcomPassword = [[WPAccount defaultWordPressComAccount] password]; - if ((wpcomUsername != nil) && (wpcomPassword != nil)) { - // Try with a known WordPress.com username first - [SVProgressHUD showWithStatus:NSLocalizedString(@"Connecting to Jetpack", @"") maskType:SVProgressHUDMaskTypeBlack]; - [self.blog validateJetpackUsername:wpcomUsername - password:wpcomPassword - success:^{ [self dismiss]; } - failure:^(NSError *error) { [self showJetpackAuthentication]; } - ]; - } else { - [self showJetpackAuthentication]; - } -} - -- (void)dismiss { - [SVProgressHUD dismiss]; - if (IS_IPAD) { - [self dismissViewControllerAnimated:YES completion:nil]; - } - else { - [self.navigationController popToRootViewControllerAnimated:YES]; - } - [[NSNotificationCenter defaultCenter] postNotificationName:@"BlogsRefreshNotification" object:nil]; -} - -- (void)showJetpackAuthentication { - [SVProgressHUD dismiss]; - JetpackSettingsViewController *jetpackSettingsViewController = [[JetpackSettingsViewController alloc] initWithBlog:self.blog]; - jetpackSettingsViewController.canBeSkipped = YES; - jetpackSettingsViewController.showFullScreen = YES; - [jetpackSettingsViewController setCompletionBlock:^(BOOL didAuthenticate) { - [self.navigationController dismissViewControllerAnimated:YES completion:^{ - [self dismiss]; - }]; - }]; - [self.navigationController presentViewController:jetpackSettingsViewController animated:YES completion:nil]; -} - -- (BOOL)canEditUsernameAndURL -{ - return YES; -} - -@end - diff --git a/WordPress/Classes/AddUsersBlogsViewController.h b/WordPress/Classes/AddUsersBlogsViewController.h deleted file mode 100644 index 32c2a752ffff..000000000000 --- a/WordPress/Classes/AddUsersBlogsViewController.h +++ /dev/null @@ -1,42 +0,0 @@ -// -// AddUsersBlogsViewController.h -// WordPress -// -// Created by Chris Boyd on 7/19/10. -// - -#import -#import "WordPressAppDelegate.h" -#import "Blog.h" -#import "WPcomLoginViewController.h" - -@class WPAccount; - -@interface AddUsersBlogsViewController : UIViewController { - WordPressAppDelegate *appDelegate; - BOOL hasCompletedGetUsersBlogs, isWPcom; - NSArray *usersBlogs; - NSMutableArray *selectedBlogs; - IBOutlet UITableView *tableView; - IBOutlet UIBarButtonItem *buttonAddSelected, *buttonSelectAll, *topAddSelectedButton; -} - -@property (nonatomic, assign) BOOL hideBackButton; -@property (nonatomic, assign) BOOL hasCompletedGetUsersBlogs, isWPcom; -@property (nonatomic, strong) NSArray *usersBlogs; -@property (nonatomic, strong) NSMutableArray *selectedBlogs; -@property (nonatomic, strong) NSString *username, *url, *password; -@property (nonatomic, strong) IBOutlet UITableView *tableView; -@property (nonatomic, strong) IBOutlet UIBarButtonItem *buttonAddSelected, *buttonSelectAll, *topAddSelectedButton; -@property (nonatomic, assign) BOOL geolocationEnabled; - -- (AddUsersBlogsViewController *)initWithAccount:(WPAccount *)account; - -- (IBAction)selectAllBlogs:(id)sender; -- (IBAction)deselectAllBlogs:(id)sender; -- (void)refreshBlogs; -- (IBAction)saveSelectedBlogs:(id)sender; -- (void)saveSelectedBlogs; -- (void)checkAddSelectedButtonStatus; - -@end diff --git a/WordPress/Classes/AddUsersBlogsViewController.m b/WordPress/Classes/AddUsersBlogsViewController.m deleted file mode 100644 index 92cc5bb73c5c..000000000000 --- a/WordPress/Classes/AddUsersBlogsViewController.m +++ /dev/null @@ -1,609 +0,0 @@ -// -// AddUsersBlogsViewController.m -// WordPress -// -// Created by Chris Boyd on 7/19/10. -// - -#import -#import "AddUsersBlogsViewController.h" -#import "CreateWPComBlogViewController.h" -#import "NSString+XMLExtensions.h" -#import "WordPressComApi.h" -#import "ReachabilityUtils.h" -#import "UIImageView+Gravatar.h" -#import "WPAccount.h" -#import "SupportViewController.h" -#import "WPTableViewCell.h" - -@interface AddUsersBlogsViewController() - -@property (nonatomic, strong) UIView *noblogsView; -@property (nonatomic, strong) IBOutlet UIToolbar *toolbar; - -- (void)showNoBlogsView; -- (void)hideNoBlogsView; -- (void)maskImageView:(UIImageView *)imageView corner:(UIRectCorner)corner; - -@end - -@implementation AddUsersBlogsViewController { - UIAlertView *failureAlertView; - BOOL _hideSignInButton; - WPAccount *_account; -} - -@synthesize usersBlogs, isWPcom, selectedBlogs, tableView, buttonAddSelected, buttonSelectAll, hasCompletedGetUsersBlogs; -@synthesize topAddSelectedButton, geolocationEnabled; -@synthesize username = _username, password = _password, url = _url; -@synthesize noblogsView; - -#pragma mark - -#pragma mark View lifecycle - -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; - failureAlertView.delegate = nil; -} - -- (AddUsersBlogsViewController *)initWithAccount:(WPAccount *)account { - self = [super init]; - if (self) { - _account = account; - } - return self; -} - -- (void)viewDidLoad { - DDLogInfo(@"%@ %@", self, NSStringFromSelector(_cmd)); - [super viewDidLoad]; - - self.navigationItem.title = NSLocalizedString(@"Select Blogs", @""); - self.selectedBlogs = [NSMutableArray array]; - - appDelegate = (WordPressAppDelegate *)[[UIApplication sharedApplication] delegate]; - - [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; - - if (IS_IOS7) { - self.toolbar.barTintColor = [WPStyleGuide littleEddieGrey]; - } - NSShadow *shadow = [[NSShadow alloc] init]; - [buttonSelectAll setTitleTextAttributes:@{ - NSFontAttributeName: [WPStyleGuide regularTextFont], - NSForegroundColorAttributeName : [UIColor whiteColor], - NSShadowAttributeName: shadow} - forState:UIControlStateNormal]; - - [buttonAddSelected setTitleTextAttributes:@{ - NSFontAttributeName: [WPStyleGuide regularTextFont], - NSForegroundColorAttributeName : [UIColor whiteColor], - NSShadowAttributeName: shadow} - forState:UIControlStateNormal]; - [buttonAddSelected setTitleTextAttributes:@{ - NSFontAttributeName: [WPStyleGuide regularTextFont], - NSForegroundColorAttributeName : [UIColor grayColor], - NSShadowAttributeName: shadow} - forState:UIControlStateDisabled]; - - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cancelAddWPcomBlogs) - name:@"didCancelWPcomLogin" object:nil]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self.navigationController setNavigationBarHidden:NO animated:animated]; - - if (self.hideBackButton) { - [self.navigationItem setHidesBackButton:YES animated:NO]; - } - - if (usersBlogs.count == 0) { - buttonSelectAll.enabled = NO; - } - - if((isWPcom) && (!appDelegate.isWPcomAuthenticated)) { - WPcomLoginViewController *wpComLogin = [[WPcomLoginViewController alloc] initWithStyle:UITableViewStyleGrouped]; - [self.navigationController presentViewController:wpComLogin animated:YES completion:nil]; - } - - if(IS_IPAD) { - topAddSelectedButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Add Selected", @"") - style:[WPStyleGuide barButtonStyleForDone] - target:self - action:@selector(saveSelectedBlogs:)]; - self.navigationItem.rightBarButtonItem = topAddSelectedButton; - topAddSelectedButton.enabled = NO; - } - - buttonAddSelected.title = NSLocalizedString(@"Add Selected", @""); - buttonSelectAll.title = NSLocalizedString(@"Select All", @""); - buttonAddSelected.enabled = NO; - - [self checkAddSelectedButtonStatus]; -} - -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - if(isWPcom) { - if((usersBlogs == nil) && ([[NSUserDefaults standardUserDefaults] objectForKey:@"WPcomUsersBlogs"] != nil)) { - usersBlogs = [[NSUserDefaults standardUserDefaults] objectForKey:@"WPcomUsersBlogs"]; - } - else if(usersBlogs == nil) { - [self refreshBlogs]; - } else if([usersBlogs count] == 0){ - [self refreshBlogs]; //Maybe just returning from creating a blog - [self hideNoBlogsView]; - } - } - else { - if (usersBlogs == nil) { - [self refreshBlogs]; - } - } -} - -- (void)viewDidUnload { - [super viewDidUnload]; - - self.tableView = nil; - self.buttonAddSelected = nil; - self.buttonSelectAll = nil; - self.topAddSelectedButton = nil; - self.noblogsView = nil; -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -{ - return [super shouldAutorotateToInterfaceOrientation:interfaceOrientation]; -} - -#pragma mark - -#pragma mark Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return usersBlogs.count; -} - -- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section { - CGRect footerFrame = CGRectMake(0, 0, self.view.frame.size.width, 50); - UIView *footerView = [[UIView alloc] initWithFrame:footerFrame]; - CGRect footerSpinnerFrame = CGRectMake(0, 26.0f, 20, 20); - CGRect footerTextFrame = CGRectMake(0, 0, self.view.frame.size.width, 20); - if((usersBlogs.count == 0) && (!hasCompletedGetUsersBlogs)) { - UIActivityIndicatorView *footerSpinner = [[UIActivityIndicatorView alloc] initWithFrame:footerSpinnerFrame]; - footerSpinner.activityIndicatorViewStyle = UIActivityIndicatorViewStyleGray; - [footerSpinner startAnimating]; - footerSpinner.center = CGPointMake(self.view.center.x, footerSpinner.center.y); - [footerView addSubview:footerSpinner]; - - UILabel *footerText = [[UILabel alloc] initWithFrame:footerTextFrame]; - footerText.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin|UIViewAutoresizingFlexibleRightMargin; - footerText.textAlignment = NSTextAlignmentCenter; - footerText.backgroundColor = [UIColor clearColor]; - footerText.textColor = [UIColor darkGrayColor]; - footerText.text = NSLocalizedString(@"Loading blogs...", @""); - [footerView addSubview:footerText]; - } - else if((usersBlogs.count == 0) && (hasCompletedGetUsersBlogs)) { - if (!isWPcom) { - UILabel *footerText = [[UILabel alloc] initWithFrame:CGRectMake(110, 0, 200, 20)]; - footerText.backgroundColor = [UIColor clearColor]; - footerText.textColor = [UIColor darkGrayColor]; - footerText.text = NSLocalizedString(@"No blogs found.", @""); - [footerView addSubview:footerText]; - } else { - //User has no blogs at WPCom but has signed in successfully, lets finish and take them to the reader - [[NSNotificationCenter defaultCenter] postNotificationName:@"BlogsRefreshNotification" object:nil]; - } - } - return footerView; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { - if((section == 0) && (usersBlogs.count == 0)) - return 60; - else - return 0; -} - -- (UITableViewCell *)tableView:(UITableView *)tv cellForRowAtIndexPath:(NSIndexPath *)indexPath { - static NSString *CellIdentifier = @"Cell"; - - UITableViewCell *cell = [tv dequeueReusableCellWithIdentifier:CellIdentifier]; - if (cell == nil) { - cell = [[WPTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; - } - - switch (indexPath.section) { - case 0: - { - cell.textLabel.textAlignment = NSTextAlignmentLeft; - - NSDictionary *blog = [usersBlogs objectAtIndex:indexPath.row]; - if([selectedBlogs containsObject:[blog valueForKey:@"blogid"]]) - cell.accessoryType = UITableViewCellAccessoryCheckmark; - else - cell.accessoryType = UITableViewCellAccessoryNone; - cell.textLabel.text = [blog valueForKey:@"blogName"]; - if (!cell.textLabel.text || [cell.textLabel.text isEqualToString:@""]) { - cell.textLabel.text = [blog valueForKey:@"url"]; - } - NSURL *blogURL = [NSURL URLWithString:[blog valueForKey:@"url"]]; - [cell.imageView setImageWithBlavatarUrl:[blogURL host] isWPcom:isWPcom]; - - if (indexPath.row == 0) { - [self maskImageView:cell.imageView corner:UIRectCornerTopLeft]; - } else if (indexPath.row == ([self.tableView numberOfRowsInSection:indexPath.section] -1)) { - [self maskImageView:cell.imageView corner:UIRectCornerBottomLeft]; - } else { - cell.imageView.layer.mask = nil; - } - [WPStyleGuide configureTableViewCell:cell]; - break; - } - default: - { - break; - } - } - - return cell; -} - -#pragma mark - -#pragma mark Table view delegate - -- (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section == 0) { - - NSDictionary *selectedBlog = [usersBlogs objectAtIndex:indexPath.row]; - - if(![selectedBlogs containsObject:[selectedBlog valueForKey:@"blogid"]]) { - [selectedBlogs addObject:[selectedBlog valueForKey:@"blogid"]]; - } - else { - int indexToRemove = -1; - int count = 0; - for (NSString *blogID in selectedBlogs) { - if([blogID isEqual:[selectedBlog valueForKey:@"blogid"]]) { - indexToRemove = count; - break; - } - count++; - } - if(indexToRemove > -1) - [selectedBlogs removeObjectAtIndex:indexToRemove]; - } - [tv reloadData]; - - if(selectedBlogs.count == usersBlogs.count) - [self selectAllBlogs:self]; - else if(selectedBlogs.count == 0) - [self deselectAllBlogs:self]; - } - - [self checkAddSelectedButtonStatus]; - - [tv deselectRowAtIndexPath:indexPath animated:YES]; -} - -#pragma mark - -#pragma mark Custom methods - -- (void)maskImageView:(UIImageView *)imageView corner:(UIRectCorner)corner { - CGRect frame = CGRectMake(0.0, 0.0, 43.0, 43.0); - UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:frame - byRoundingCorners:corner cornerRadii:CGSizeMake(7.0f, 7.0f)]; - CAShapeLayer *maskLayer = [CAShapeLayer layer]; - maskLayer.frame = frame; - maskLayer.path = path.CGPath; - imageView.layer.mask = maskLayer; -} - -- (NSArray *)usersBlogs { - return [usersBlogs filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { - NSNumber *hidden = [evaluatedObject objectForKey:@"hidden"]; - return ((hidden == nil) || [hidden boolValue]); - }]]; -} - -- (void)selectAllBlogs:(id)sender { - [selectedBlogs removeAllObjects]; - for(NSDictionary *blog in usersBlogs) { - [selectedBlogs addObject:[blog valueForKey:@"blogid"]]; - } - [self.tableView reloadData]; - buttonSelectAll.title = NSLocalizedString(@"Deselect All", @""); - buttonSelectAll.action = @selector(deselectAllBlogs:); - [self checkAddSelectedButtonStatus]; -} - -- (void)deselectAllBlogs:(id)sender { - [selectedBlogs removeAllObjects]; - [self.tableView reloadData]; - buttonSelectAll.title = NSLocalizedString(@"Select All", @""); - buttonSelectAll.action = @selector(selectAllBlogs:); - [self checkAddSelectedButtonStatus]; -} - -- (void)refreshBlogs { - - if (![ReachabilityUtils isInternetReachable]) { - __weak AddUsersBlogsViewController *weakSelf = self; - [ReachabilityUtils showAlertNoInternetConnectionWithRetryBlock:^{ - [weakSelf refreshBlogs]; - }]; - hasCompletedGetUsersBlogs = YES; - [self.tableView reloadData]; - return; - } - - NSURL *xmlrpc; - NSString *username, *password; - if (isWPcom) { - xmlrpc = [NSURL URLWithString:@"https://wordpress.com/xmlrpc.php"]; - WPAccount *account = [WPAccount defaultWordPressComAccount]; - username = account.username; - password = account.password; - } else { - xmlrpc = [NSURL URLWithString:_url]; - username = self.username; - password = self.password; - } - WPXMLRPCClient *api = [WPXMLRPCClient clientWithXMLRPCEndpoint:xmlrpc]; - [api callMethod:@"wp.getUsersBlogs" - parameters:[NSArray arrayWithObjects:username, password, nil] - success:^(AFHTTPRequestOperation *operation, id responseObject) { - usersBlogs = responseObject; - hasCompletedGetUsersBlogs = YES; - if(usersBlogs.count > 0) { - buttonSelectAll.enabled = YES; - [usersBlogs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - NSString *title = [obj valueForKey:@"blogName"]; - title = [title stringByDecodingXMLCharacters]; - [obj setValue:title forKey:@"blogName"]; - }]; - usersBlogs = [usersBlogs sortedArrayUsingComparator:^(id obj1, id obj2){ - NSString *title1 = [obj1 valueForKey:@"blogName"]; - NSString *title2 = [obj2 valueForKey:@"blogName"]; - return [title1 localizedCaseInsensitiveCompare:title2]; - }]; - - if(usersBlogs.count > 1) { - [self hideNoBlogsView]; - [self.tableView reloadData]; - } else { - [selectedBlogs removeAllObjects]; - for(NSDictionary *blog in usersBlogs) { - [selectedBlogs addObject:[blog valueForKey:@"blogid"]]; - } - [self saveSelectedBlogs]; - } - } else { - - // User blogs count == 0. Prompt the user to create a blog. - [self showNoBlogsView]; - [self.tableView reloadData]; - - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"Failed getting user blogs: %@", [error localizedDescription]); - [self hideNoBlogsView]; - hasCompletedGetUsersBlogs = YES; - [self.tableView reloadData]; - if (failureAlertView == nil) { - failureAlertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Sorry, can't log in", @"") - message:[error localizedDescription] - delegate:self - cancelButtonTitle:NSLocalizedString(@"Need Help?", @"") - otherButtonTitles:NSLocalizedString(@"OK", @""), nil]; - failureAlertView.tag = 1; - [failureAlertView show]; - } - }]; -} - - -- (void)showNoBlogsView { - if(!self.noblogsView) { - CGFloat width = 282.0f; - CGFloat height = 160.0f; - CGFloat x = (self.view.frame.size.width / 2.0f) - (width / 2.0f); - CGFloat y = (self.view.frame.size.height / 2.0f) - (height / 2.0f); - self.noblogsView = [[UIView alloc] initWithFrame:CGRectMake(x, y, width, height)]; - self.noblogsView.backgroundColor = [UIColor clearColor]; - - self.noblogsView.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | - UIViewAutoresizingFlexibleRightMargin | - UIViewAutoresizingFlexibleTopMargin | - UIViewAutoresizingFlexibleBottomMargin; - - UIColor *textColor = [UIColor colorWithRed:33.0f/255.0f green:33.0f/255.0f blue:33.0f/255.0f alpha:1.0]; - UILabel *label = [[UILabel alloc] initWithFrame:CGRectZero]; - label.backgroundColor = [UIColor clearColor]; - label.numberOfLines = 0; - label.lineBreakMode = NSLineBreakByWordWrapping; - label.font = [UIFont fontWithName:@"Georgia" size:16.0f]; - label.shadowOffset = CGSizeMake(0.0f, 1.0f); - label.textColor = textColor; - label.shadowColor = [UIColor whiteColor]; - label.textAlignment = NSTextAlignmentCenter; - - if ([[WPAccount defaultWordPressComAccount] username]) { - label.text = NSLocalizedString(@"You do not seem to have any blogs. Would you like to create one now?", @""); - } else { - label.text = NSLocalizedString(@"You do not seem to have any blogs.", @""); - } - - label.frame = CGRectMake(0.0, 0.0, width, 38.0); - [self.noblogsView addSubview:label]; - - if ([[WPAccount defaultWordPressComAccount] username]) { - width = 282.0f; - height = 44.0f; - x = (noblogsView.frame.size.width / 2.0f) - (width / 2.0f); - y = label.frame.size.height + 10.0f; - - UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; - button.frame = CGRectMake(x, y, width, height); - button.titleLabel.font = [UIFont fontWithName:@"Helvetica-Bold" size:15.0]; - [button setTitleColor:textColor forState:UIControlStateNormal]; - [button setTitleShadowColor:[UIColor whiteColor] forState:UIControlStateNormal]; - button.titleLabel.shadowOffset = CGSizeMake(0.0f, 1.0f); - [button setImage:[UIImage imageNamed:@"welcome_button_asterisk.png"] forState:UIControlStateNormal]; - [button setContentEdgeInsets:UIEdgeInsetsMake(0.0f, 15.0f, 0.0f, 0.0f)]; - [button setTitleEdgeInsets:UIEdgeInsetsMake(0.0f, 10.0f, 0.0f, 0.0f)]; - [button setContentHorizontalAlignment:UIControlContentHorizontalAlignmentLeft]; - [button setBackgroundImage:[UIImage imageNamed:@"welcome_button_bg_full"] forState:UIControlStateNormal]; - [button setBackgroundImage:[UIImage imageNamed:@"welcome_button_bg_full_highlighted.png"] forState:UIControlStateHighlighted]; - [button setTitle:NSLocalizedString(@"Create WordPress.com Blog", @"") forState:UIControlStateNormal]; - [button addTarget:self action:@selector(handleCreateBlogTapped:) forControlEvents:UIControlEventTouchUpInside]; - - [self.noblogsView addSubview:button]; - } - - [self.view addSubview:noblogsView]; - } - self.buttonSelectAll.enabled = NO; - self.noblogsView.alpha = 0.0; - self.noblogsView.hidden = NO; - _hideSignInButton = YES; - [self.tableView reloadData]; - - [UIView animateWithDuration:0.3f animations:^{ - self.noblogsView.alpha = 1.0f; - }]; -} - - -- (void)hideNoBlogsView { - _hideSignInButton = NO; - [self.tableView reloadData]; - if(!self.noblogsView) return; - self.noblogsView.hidden = YES; - self.buttonSelectAll.enabled = YES; -} - -- (void)handleCreateBlogTapped:(id)sender { - CreateWPComBlogViewController *viewController = [[CreateWPComBlogViewController alloc] initWithStyle:UITableViewStyleGrouped]; - viewController.delegate = self; - [self.navigationController pushViewController:viewController animated:YES]; -} - -#pragma mark - -#pragma mark UIAlertViewDelegate - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { - if (buttonIndex == 0) { - SupportViewController *supportViewController = [[SupportViewController alloc] init]; - - if (IS_IPAD) { - [self.navigationController pushViewController:supportViewController animated:YES]; - } else { - UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:supportViewController]; - navController.modalPresentationStyle = UIModalPresentationFormSheet; - navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical; - navController.navigationBar.translucent = NO; - [self presentViewController:navController animated:YES completion:nil]; - } - } - - if (failureAlertView == alertView) { - failureAlertView = nil; - } -} - -- (IBAction)saveSelectedBlogs:(id)sender { - [self saveSelectedBlogs]; -} - -- (void)saveSelectedBlogs { - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"refreshCommentsRequired"]; - - NSManagedObjectContext *backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; - backgroundMOC.parentContext = [WordPressAppDelegate sharedWordPressApplicationDelegate].managedObjectContext; - - [backgroundMOC performBlock:^{ - for (NSDictionary *blog in usersBlogs) { - if([selectedBlogs containsObject:[blog valueForKey:@"blogid"]]) { - [self createBlog:blog withContext:backgroundMOC]; - } - } - - NSError *error; - if(![backgroundMOC save:&error]) { - WPFLog(@"Core data context save error on adding blogs: %@", error); - #if DEBUG - exit(-1); - #endif - } - - dispatch_async(dispatch_get_main_queue(), ^{ - [self.navigationController popToRootViewControllerAnimated:YES]; - [[WordPressComApi sharedApi] syncPushNotificationInfo]; - }); - }]; -} - -- (void)createBlog:(NSDictionary *)blogInfo withContext:(NSManagedObjectContext *)context { - DDLogInfo(@"creating blog: %@", blogInfo); - - Blog *blog = [_account findOrCreateBlogFromDictionary:blogInfo withContext:context]; - blog.geolocationEnabled = self.geolocationEnabled; - - dispatch_async(dispatch_get_main_queue(), ^{ - [blog syncBlogWithSuccess:^{ - if( ![blog isWPcom] ) - [[WordPressComApi sharedApi] syncPushNotificationInfo]; - } - failure:nil]; - }); -} - -- (void)checkAddSelectedButtonStatus { - //disable the 'Add Selected' button if they have selected 0 blogs, trac #521 - if (selectedBlogs.count == 0) { - buttonAddSelected.enabled = NO; - if (IS_IPAD) { - topAddSelectedButton.enabled = NO; - } - // iOS 7 Beta 6 doesn't seem to be respecting the title text attributes for UIControlStateDisabled - // so we have to engage in this hack until apple fixes it. - [buttonAddSelected setTitleTextAttributes:@{ - NSFontAttributeName: [WPStyleGuide regularTextFont], - NSForegroundColorAttributeName : [WPStyleGuide whisperGrey ], - NSShadowAttributeName: [[NSShadow alloc] init]} - forState:UIControlStateNormal]; - } - else { - buttonAddSelected.enabled = YES; - if (IS_IPAD) { - topAddSelectedButton.enabled = YES; - } - // iOS 7 Beta 6 doesn't seem to be respecting the title text attributes for UIControlStateDisabled - // so we have to engage in this hack until apple fixes it. - [buttonAddSelected setTitleTextAttributes:@{ - NSFontAttributeName: [WPStyleGuide regularTextFont], - NSForegroundColorAttributeName : [UIColor whiteColor], - NSShadowAttributeName: [[NSShadow alloc] init]} - forState:UIControlStateNormal]; - } - -} - -#pragma mark - CreateWPComBlogViewControllerDelegate - -- (void)createdBlogWithDetails:(NSDictionary *)blogDetails -{ - [self.navigationController popToRootViewControllerAnimated:YES]; -} - -@end diff --git a/WordPress/Classes/CreateWPComAccountViewController.h b/WordPress/Classes/CreateWPComAccountViewController.h deleted file mode 100644 index ec364ceb1834..000000000000 --- a/WordPress/Classes/CreateWPComAccountViewController.h +++ /dev/null @@ -1,23 +0,0 @@ -// -// CreateWPComAccountViewController.h -// WordPress -// -// Created by Sendhil Panchadsaram on 4/5/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import - -@protocol CreateWPComAccountViewControllerDelegate; -@interface CreateWPComAccountViewController : UITableViewController - -@property (nonatomic, weak) id delegate; - -@end - -@protocol CreateWPComAccountViewControllerDelegate - -- (void)createdAndSignedInAccountWithUserName:(NSString *)userName; -- (void)createdAccountWithUserName:(NSString *)userName; - -@end diff --git a/WordPress/Classes/CreateWPComAccountViewController.m b/WordPress/Classes/CreateWPComAccountViewController.m deleted file mode 100644 index e51af5c39c8b..000000000000 --- a/WordPress/Classes/CreateWPComAccountViewController.m +++ /dev/null @@ -1,506 +0,0 @@ -// -// CreateWPComAccountViewController.m -// WordPress -// -// Created by Sendhil Panchadsaram on 4/5/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import "CreateWPComAccountViewController.h" -#import "WordPressComApi.h" -#import "ReachabilityUtils.h" -#import "UITableViewActivityCell.h" -#import "UITableViewTextFieldCell.h" -#import "WPComLanguages.h" -#import "SelectWPComLanguageViewController.h" -#import "WPAsyncBlockOperation.h" -#import "WPTableViewSectionFooterView.h" - -@interface CreateWPComAccountViewController () < - UITextFieldDelegate> { - - UITableViewTextFieldCell *_usernameCell; - UITableViewTextFieldCell *_passwordCell; - UITableViewTextFieldCell *_emailCell; - UITableViewTextFieldCell *_blogUrlCell; - UITableViewCell *_localeCell; - - UITextField *_usernameTextField; - UITextField *_passwordTextField; - UITextField *_emailTextField; - UITextField *_blogUrlTextField; - - NSString *_buttonText; - NSString *_footerText; - - BOOL _isCreatingAccount; - BOOL _userPressedBackButton; - - NSDictionary *_currentLanguage; - - NSOperationQueue *_operationQueue; -} - -@end - -@implementation CreateWPComAccountViewController - -NSUInteger const CreateAccountEmailTextFieldTag = 1; -NSUInteger const CreateAccountUserNameTextFieldTag = 2; -NSUInteger const CreateAccountPasswordTextFieldTag = 3; -NSUInteger const CreateAccountBlogUrlTextFieldTag = 4; - -CGSize const CreateAccountHeaderSize = { 320.0, 70.0 }; - -- (id)initWithStyle:(UITableViewStyle)style -{ - self = [super initWithStyle:style]; - - if (self) { - _currentLanguage = [WPComLanguages currentLanguage]; - _operationQueue = [[NSOperationQueue alloc] init]; - } - - return self; -} - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - [self.navigationController setNavigationBarHidden:NO animated:NO]; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; - - _footerText = @" "; - _buttonText = NSLocalizedString(@"Create WordPress.com Site", @"Button to complete creating a new WordPress.com site"); - self.navigationItem.title = NSLocalizedString(@"Create Account", @"Label to create a new WordPress.com account."); - - UIImageView *logoImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logo_wpcom"]]; - logoImage.frame = CGRectMake(0.0f, 0.0f, CreateAccountHeaderSize.width, CreateAccountHeaderSize.height); - logoImage.autoresizingMask = UIViewAutoresizingFlexibleWidth; - logoImage.contentMode = UIViewContentModeCenter; - self.tableView.tableHeaderView = logoImage; -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { - return [super shouldAutorotateToInterfaceOrientation:interfaceOrientation]; -} - -#pragma mark - Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView -{ - return 2; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - if (section == 0) - return 5; - else - return 1; -} - -- (NSString *)titleForFooterInSection:(NSInteger)section { - if(section == 0) - return _footerText; - else - return @""; -} - -- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section -{ - WPTableViewSectionFooterView *header = [[WPTableViewSectionFooterView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 0)]; - header.title = [self titleForFooterInSection:section]; - return header; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section -{ - NSString *title = [self titleForFooterInSection:section]; - return [WPTableViewSectionFooterView heightForTitle:title andWidth:CGRectGetWidth(self.view.bounds)]; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - UITableViewCell *cell = nil; - - if(indexPath.section == 1) { - UITableViewActivityCell *activityCell = nil; - NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"UITableViewActivityCell" owner:nil options:nil]; - for(id currentObject in topLevelObjects) - { - if([currentObject isKindOfClass:[UITableViewActivityCell class]]) - { - activityCell = (UITableViewActivityCell *)currentObject; - break; - } - } - - if(_isCreatingAccount) { - [activityCell.spinner startAnimating]; - _buttonText = NSLocalizedString(@"Creating Account...", @""); - } else { - [activityCell.spinner stopAnimating]; - _buttonText = NSLocalizedString(@"Create WordPress.com Blog", @""); - } - - activityCell.textLabel.text = _buttonText; - if (_isCreatingAccount) { - activityCell.selectionStyle = UITableViewCellSelectionStyleNone; - } else { - activityCell.selectionStyle = UITableViewCellSelectionStyleBlue; - } - - [WPStyleGuide configureTableViewActionCell:activityCell]; - cell = activityCell; - } else { - if (indexPath.row == 0) { - if (_emailCell == nil) { - _emailCell = [[UITableViewTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"TextCell"]; - } - _emailCell.textLabel.text = NSLocalizedString(@"Email", @""); - _emailTextField = _emailCell.textField; - _emailTextField.tag = CreateAccountEmailTextFieldTag; - _emailTextField.placeholder = NSLocalizedString(@"user@example.com", @""); - _emailTextField.keyboardType = UIKeyboardTypeEmailAddress; - _emailTextField.returnKeyType = UIReturnKeyNext; - _emailTextField.delegate = self; - [WPStyleGuide configureTableViewTextCell:_emailCell]; - cell = _emailCell; - } - else if (indexPath.row == 1) { - if (_usernameCell == nil) { - _usernameCell = [[UITableViewTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"TextCell"]; - } - _usernameCell.textLabel.text = NSLocalizedString(@"Username", @"Label for username field"); - _usernameTextField = _usernameCell.textField; - _usernameTextField.tag = CreateAccountUserNameTextFieldTag; - _usernameTextField.placeholder = NSLocalizedString(@"Enter username", @"Help user enter username for log in"); - _usernameTextField.keyboardType = UIKeyboardTypeEmailAddress; - _usernameTextField.returnKeyType = UIReturnKeyNext; - _usernameTextField.delegate = self; - [WPStyleGuide configureTableViewTextCell:_usernameCell]; - cell = _usernameCell; - } else if (indexPath.row == 2) { - if (_passwordCell == nil) { - _passwordCell = [[UITableViewTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"TextCell"]; - } - _passwordCell.textLabel.text = NSLocalizedString(@"Password", @"Label for password field"); - _passwordTextField = _passwordCell.textField; - _passwordTextField.tag = CreateAccountPasswordTextFieldTag; - _passwordTextField.placeholder = NSLocalizedString(@"Enter password", @"Help user enter password for log in"); - _passwordTextField.keyboardType = UIKeyboardTypeDefault; - _passwordTextField.returnKeyType = UIReturnKeyNext; - _passwordTextField.secureTextEntry = YES; - _passwordTextField.delegate = self; - [WPStyleGuide configureTableViewTextCell:_passwordCell]; - - cell = _passwordCell; - } else if (indexPath.row == 3) { - if (_blogUrlCell == nil) { - _blogUrlCell = [[UITableViewTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"TextCell"]; - } - _blogUrlCell.textLabel.text = NSLocalizedString(@"Site URL", @"Label for Site URL field in the Create a site window"); - _blogUrlTextField = _blogUrlCell.textField; - _blogUrlTextField.tag = CreateAccountBlogUrlTextFieldTag; - _blogUrlTextField.placeholder = NSLocalizedString(@"http://(choose-address).wordpress.com", @"Help user enter a URL for their new site"); - _blogUrlTextField.keyboardType = UIKeyboardTypeURL; - _blogUrlTextField.delegate = self; - [WPStyleGuide configureTableViewTextCell:_blogUrlCell]; - cell = _blogUrlCell; - } else if (indexPath.row == 4) { - if (_localeCell == nil) { - _localeCell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 - reuseIdentifier:@"LocaleCell"]; - } - _localeCell.textLabel.text = @"Language"; - _localeCell.detailTextLabel.text = [_currentLanguage objectForKey:@"name"]; - _localeCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - [WPStyleGuide configureTableViewCell:_localeCell]; - cell = _localeCell; - } - } - - return cell; -} - -#pragma mark - -#pragma mark Table view delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - - if (_isCreatingAccount) - return; - - if (indexPath.section == 0) { - if (indexPath.row == 4) { - SelectWPComLanguageViewController *selectLanguageViewController = [[SelectWPComLanguageViewController alloc] initWithStyle:UITableViewStylePlain]; - selectLanguageViewController.currentlySelectedLanguageId = [[_currentLanguage objectForKey:@"lang_id"] intValue]; - selectLanguageViewController.didSelectLanguage = ^(NSDictionary *language){ - _currentLanguage = language; - [self.tableView reloadData]; - }; - [self.navigationController pushViewController:selectLanguageViewController animated:YES]; - } - } else { - [self createAccount]; - } -} - -#pragma mark - UITextField delegate methods - -- (BOOL)textFieldShouldReturn:(UITextField *)textField { - [textField resignFirstResponder]; - - switch (textField.tag) { - case CreateAccountEmailTextFieldTag: - [_usernameTextField becomeFirstResponder]; - break; - case CreateAccountUserNameTextFieldTag: - [_passwordTextField becomeFirstResponder]; - break; - case CreateAccountPasswordTextFieldTag: - [_blogUrlTextField becomeFirstResponder]; - break; - default: - break; - } - - return YES; -} - -#pragma mark - Private Methods - -- (BOOL)areFieldsValid -{ - return [self areInputFieldsFilled] && ![self doesUrlHavePeriod] && [self isUsernameLessThanFiftyCharacters]; -} - -- (BOOL)areInputFieldsFilled -{ - return [[_usernameTextField.text trim] length] != 0 && [[_passwordTextField.text trim] length] != 0 && [[_emailTextField.text trim] length] != 0 && [[_blogUrlTextField.text trim] length] != 0;; -} - -- (BOOL)doesUrlHavePeriod -{ - return [_blogUrlTextField.text rangeOfString:@"."].location != NSNotFound; -} - -- (BOOL)isUsernameLessThanFiftyCharacters -{ - return [[_usernameTextField.text trim] length] <= 50; -} - -- (void)showErrorMessage -{ - NSString *errorMessage; - - if ([[_emailTextField.text trim] length] == 0) { - errorMessage = NSLocalizedString(@"Email address is required.", nil); - } else if ([[_usernameTextField.text trim] length] == 0) { - errorMessage = NSLocalizedString(@"Username is required.", nil); - } else if ([[_passwordTextField.text trim] length] == 0) { - errorMessage = NSLocalizedString(@"Password is required.", nil); - } else if ([[_blogUrlTextField.text trim] length] == 0) { - errorMessage = NSLocalizedString(@"Blog address is required.", nil); - } else if ([self doesUrlHavePeriod]) { - errorMessage = NSLocalizedString(@"Blog url cannot contain a period", nil); - } else if (![self isUsernameLessThanFiftyCharacters]) { - errorMessage = NSLocalizedString(@"Username must be less than fifty characters.", nil); - } - - if (errorMessage != nil) { - _footerText = errorMessage; - [self.tableView reloadData]; - } -} - -- (void)displayCreationErrorMessage:(NSError *)error -{ - NSString *errorMessage = [error.userInfo objectForKey:WordPressComApiErrorMessageKey]; - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:errorMessage delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil, nil]; - [alertView show]; -} - -- (void)createAccount -{ - [self.view endEditing:YES]; - - if ([self areFieldsValid]) { - if (![ReachabilityUtils isInternetReachable]) { - [ReachabilityUtils showAlertNoInternetConnection]; - return; - } - - _footerText = @""; - _isCreatingAccount = YES; - [self.tableView reloadData]; - - [self disableTextFields]; - [self createUserAndBlog]; - } else { - [self showErrorMessage]; - } -} - -- (void)didMoveToParentViewController:(UIViewController *)parent -{ - // User has pressed back button so make sure the user does not see a strange message - // or encounters strange behavior as a result of a failed or successful attempt to create an account. - if (parent == nil) { - self.delegate = nil; - _userPressedBackButton = YES; - [_operationQueue cancelAllOperations]; - } -} - -#pragma mark - Private Methods - -- (void)createUserAndBlog -{ - // As there are 5 API requests to do this successfully, using WPAsyncBlockOperation to create dependencies - // on previous required API requests so if one fails along the way the rest won't continue executing. - - WPAsyncBlockOperation *userValidation = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ - void (^userValidationSuccess)(id) = ^(id responseObject) { - [operation didSucceed]; - }; - - void (^userValidationFailure)(NSError *) = ^(NSError *error){ - [operation didFail]; - [self processErrorDuringRemoteConnection:error]; - }; - - [[WordPressComApi sharedApi] validateWPComAccountWithEmail:_emailTextField.text - andUsername:_usernameTextField.text - andPassword:_passwordTextField.text - success:userValidationSuccess - failure:userValidationFailure]; - }]; - WPAsyncBlockOperation *blogValidation = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ - void (^blogValidationSuccess)(id) = ^(id responseObject) { - [operation didSucceed]; - }; - void (^blogValidationFailure)(NSError *) = ^(NSError *error) { - [self processErrorDuringRemoteConnection:error]; - [operation didFail]; - }; - - [[WordPressComApi sharedApi] validateWPComBlogWithUrl:_blogUrlTextField.text - andBlogTitle:nil - andLanguageId:[_currentLanguage objectForKey:@"lang_id"] - success:blogValidationSuccess - failure:blogValidationFailure]; - }]; - WPAsyncBlockOperation *userCreation = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ - void (^createUserSuccess)(id) = ^(id responseObject){ - [operation didSucceed]; - }; - void (^createUserFailure)(NSError *) = ^(NSError *error) { - [operation didFail]; - [self processErrorDuringRemoteConnection:error]; - }; - - [[WordPressComApi sharedApi] createWPComAccountWithEmail:_emailTextField.text - andUsername:_usernameTextField.text - andPassword:_passwordTextField.text - success:createUserSuccess - failure:createUserFailure]; - - }]; - WPAsyncBlockOperation *userSignIn = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ - void (^signInSuccess)(void) = ^{ - [operation didSucceed]; - }; - void (^signInFailure)(NSError *) = ^(NSError *error) { - // We've hit a strange failure at this point, the user has been created successfully but for some reason - // we are unable to sign in and proceed - [operation didFail]; - [self processErrorDuringRemoteConnection:error]; - }; - - [[WordPressComApi sharedApi] signInWithUsername:_usernameTextField.text - password:_passwordTextField.text - success:signInSuccess - failure:signInFailure]; - }]; - - WPAsyncBlockOperation *blogCreation = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ - void (^createBlogSuccess)(id) = ^(id responseObject){ - [operation didSucceed]; - if (self.delegate != nil) { - [self.delegate createdAndSignedInAccountWithUserName:_usernameTextField.text]; - } - }; - void (^createBlogFailure)(NSError *error) = ^(NSError *error) { - [operation didFail]; - [self processErrorDuringRemoteConnection:error]; - }; - NSNumber *languageId = [_currentLanguage objectForKey:@"lang_id"]; - - [[WordPressComApi sharedApi] createWPComBlogWithUrl:_blogUrlTextField.text - andBlogTitle:nil - andLanguageId:languageId - andBlogVisibility:WordPressComApiBlogVisibilityPublic - success:createBlogSuccess - failure:createBlogFailure]; - }]; - - // The order of API Requests is - // 1. Validate User - // 2. Validate Blog - // 3. Create User - // 4. Sign In User - // 5. Create Blog - - [blogCreation addDependency:userSignIn]; - [userSignIn addDependency:userCreation]; - [userCreation addDependency:blogValidation]; - [userCreation addDependency:userValidation]; - [blogValidation addDependency:userValidation]; - - [_operationQueue addOperation:userValidation]; - [_operationQueue addOperation:blogValidation]; - [_operationQueue addOperation:userCreation]; - [_operationQueue addOperation:userSignIn]; - [_operationQueue addOperation:blogCreation]; -} - -- (void)processErrorDuringRemoteConnection:(NSError *)error -{ - if (!_userPressedBackButton) { - _isCreatingAccount = NO; - [self enableTextFields]; - [self.tableView reloadData]; - [self displayCreationErrorMessage:error]; - } -} - -- (void)disableTextFields -{ - NSArray *textFields = @[_usernameTextField, _emailTextField, _passwordTextField, _blogUrlTextField]; - for (UITextField *textField in textFields) { - textField.enabled = NO; - } -} - -- (void)enableTextFields -{ - NSArray *textFields = @[_usernameTextField, _emailTextField, _passwordTextField, _blogUrlTextField]; - for (UITextField *textField in textFields) { - textField.enabled = YES; - } -} - -@end diff --git a/WordPress/Classes/CreateWPComBlogViewController.h b/WordPress/Classes/CreateWPComBlogViewController.h deleted file mode 100644 index 08378436c68e..000000000000 --- a/WordPress/Classes/CreateWPComBlogViewController.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// CreateWPComBlogViewController.h -// WordPress -// -// Created by Sendhil Panchadsaram on 4/10/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import - -@protocol CreateWPComBlogViewControllerDelegate; -@interface CreateWPComBlogViewController : UITableViewController - -@property (nonatomic, weak) id delegate; - -@end - -@protocol CreateWPComBlogViewControllerDelegate - -- (void)createdBlogWithDetails:(NSDictionary *)blogDetails; - -@end \ No newline at end of file diff --git a/WordPress/Classes/CreateWPComBlogViewController.m b/WordPress/Classes/CreateWPComBlogViewController.m deleted file mode 100644 index a644c4fef4d9..000000000000 --- a/WordPress/Classes/CreateWPComBlogViewController.m +++ /dev/null @@ -1,392 +0,0 @@ -// -// CreateWPComBlogViewController.m -// WordPress -// -// Created by Sendhil Panchadsaram on 4/10/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import "CreateWPComBlogViewController.h" -#import "SelectWPComLanguageViewController.h" -#import "SelectWPComBlogVisibilityViewController.h" -#import "UITableViewTextFieldCell.h" -#import "UITableViewActivityCell.h" -#import "WordPressComApi.h" -#import "WPComLanguages.h" -#import "WordPressAppDelegate.h" -#import "ReachabilityUtils.h" -#import "WPAccount.h" -#import "WPTableViewSectionFooterView.h" - -@interface CreateWPComBlogViewController () < - SelectWPComBlogVisibilityViewControllerDelegate, - UITextFieldDelegate> { - - UITableViewTextFieldCell *_blogUrlCell; - UITableViewTextFieldCell *_blogTitleCell; - UITableViewCell *_blogVisibilityCell; - UITableViewCell *_localeCell; - - UITextField *_blogUrlTextField; - UITextField *_blogTitleTextField; - - NSString *_buttonText; - NSString *_footerText; - - BOOL _geolocationEnabled; - BOOL _isCreatingBlog; - BOOL _userPressedBackButton; - - NSDictionary *_currentLanguage; - WordPressComApiBlogVisibility _blogVisibility; -} - -@end - -@implementation CreateWPComBlogViewController - -CGSize const CreateBlogHeaderSize = { 320.0, 70.0 }; - -NSUInteger const CreateBlogBlogUrlFieldTag = 1; - -- (id)initWithStyle:(UITableViewStyle)style -{ - self = [super initWithStyle:style]; - - if (self) { - _currentLanguage = [WPComLanguages currentLanguage]; - _blogVisibility = WordPressComApiBlogVisibilityPublic; - _geolocationEnabled = YES; - } - - return self; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; - - _footerText = @" "; - _buttonText = NSLocalizedString(@"Create WordPress.com Blog", @""); - self.navigationItem.title = NSLocalizedString(@"Create Blog", @""); - - UIImageView *logoImage = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"logo_wpcom"]]; - logoImage.frame = CGRectMake(0.0f, 0.0f, CreateBlogHeaderSize.width, CreateBlogHeaderSize.height); - logoImage.autoresizingMask = UIViewAutoresizingFlexibleWidth; - logoImage.contentMode = UIViewContentModeCenter; - self.tableView.tableHeaderView = logoImage; -} - -- (void)didMoveToParentViewController:(UIViewController *)parent -{ - // User has pressed back button so make sure the user does not see a strange message - // or encounters strange behavior as a result of a failed or successful attempt to create an account. - if (parent == nil) { - self.delegate = nil; - _userPressedBackButton = YES; - } -} - -#pragma mark - Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView -{ - return 2; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - if (section == 0) - return 5; - else - return 1; -} - -- (NSString *)titleForFooterInSection:(NSInteger)section { - if(section == 0) - return _footerText; - else - return @""; -} - -- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section -{ - WPTableViewSectionFooterView *header = [[WPTableViewSectionFooterView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 0)]; - header.title = [self titleForFooterInSection:section]; - return header; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section -{ - NSString *title = [self titleForFooterInSection:section]; - return [WPTableViewSectionFooterView heightForTitle:title andWidth:CGRectGetWidth(self.view.bounds)]; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - UITableViewCell *cell = nil; - - if(indexPath.section == 1) { - UITableViewActivityCell *activityCell = nil; - NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"UITableViewActivityCell" owner:nil options:nil]; - for(id currentObject in topLevelObjects) - { - if([currentObject isKindOfClass:[UITableViewActivityCell class]]) - { - activityCell = (UITableViewActivityCell *)currentObject; - break; - } - } - - if(_isCreatingBlog) { - [activityCell.spinner startAnimating]; - _buttonText = NSLocalizedString(@"Creating Blog...", nil); - } else { - [activityCell.spinner stopAnimating]; - _buttonText = NSLocalizedString(@"Create WordPress.com Blog", nil); - } - - activityCell.textLabel.text = _buttonText; - if (_isCreatingBlog) { - activityCell.selectionStyle = UITableViewCellSelectionStyleNone; - } else { - activityCell.selectionStyle = UITableViewCellSelectionStyleBlue; - } - - activityCell.textLabel.font = [WPStyleGuide tableviewTextFont]; - activityCell.textLabel.textColor = [WPStyleGuide tableViewActionColor]; - cell = activityCell; - } else { - if (indexPath.row == 0) { - if (_blogUrlCell == nil) { - _blogUrlCell = [[UITableViewTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"TextCell"]; - } - _blogUrlCell.textLabel.text = NSLocalizedString(@"Blog URL", nil); - _blogUrlTextField = _blogUrlCell.textField; - _blogUrlTextField.tag = CreateBlogBlogUrlFieldTag; - _blogUrlTextField.placeholder = NSLocalizedString(@"myblog.wordpress.com", @""); - _blogUrlTextField.leftView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 0, 1)]; - _blogUrlTextField.leftViewMode = UITextFieldViewModeAlways; - _blogUrlTextField.keyboardType = UIKeyboardTypeURL; - _blogUrlTextField.delegate = self; - [self styleTextFieldCell:_blogUrlCell]; - cell = _blogUrlCell; - } else if (indexPath.row == 1) { - if (_blogTitleCell == nil) { - _blogTitleCell = [[UITableViewTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"TextCell"]; - } - _blogTitleCell.textLabel.text = NSLocalizedString(@"Site Title", @"Label for site title field in create an account process"); - _blogTitleTextField = _blogTitleCell.textField; - _blogTitleTextField.placeholder = NSLocalizedString(@"My Site", @"Placeholder for site title field in create an account process"); - _blogTitleTextField.leftViewMode = UITextFieldViewModeAlways; - _blogTitleTextField.delegate = self; - [self styleTextFieldCell:_blogTitleCell]; - cell = _blogTitleCell; - } else if (indexPath.row == 2) { - if (_localeCell == nil) { - _localeCell = [[WPTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 - reuseIdentifier:@"LocaleCell"]; - } - _localeCell.textLabel.text = @"Language"; - _localeCell.detailTextLabel.text = [_currentLanguage objectForKey:@"name"]; - _localeCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - [WPStyleGuide configureTableViewCell:_localeCell]; - cell = _localeCell; - } else if (indexPath.row == 3) { - if (_blogVisibilityCell == nil) { - _blogVisibilityCell = [[WPTableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 - reuseIdentifier:@"VisibilityCell"]; - } - _blogVisibilityCell.textLabel.text = @"Blog Visibility"; - _blogVisibilityCell.detailTextLabel.text = [self textForCurrentBlogVisibility]; - _blogVisibilityCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - [WPStyleGuide configureTableViewCell:_blogVisibilityCell]; - cell = _blogVisibilityCell; - } else if (indexPath.row == 4) { - UITableViewCell *geolocationCell = [tableView dequeueReusableCellWithIdentifier:@"GeolocationCell"]; - if(geolocationCell == nil) { - geolocationCell = [[WPTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"GeolocationCell"]; - geolocationCell.accessoryView = [[UISwitch alloc] init]; - } - UISwitch *geolocationSwitch = (UISwitch *)geolocationCell.accessoryView; - geolocationCell.textLabel.text = NSLocalizedString(@"Geotagging", nil); - geolocationCell.selectionStyle = UITableViewCellSelectionStyleNone; - geolocationSwitch.on = _geolocationEnabled; - [geolocationSwitch addTarget:self action:@selector(toggleGeolocation:) forControlEvents:UIControlEventValueChanged]; - [WPStyleGuide configureTableViewCell:geolocationCell]; - cell = geolocationCell; - } - } - - return cell; - -} - -#pragma mark - Table view delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - - if (_isCreatingBlog) - return; - - if (indexPath.section == 0) { - if (indexPath.row == 2) { - SelectWPComLanguageViewController *selectLanguageViewController = [[SelectWPComLanguageViewController alloc] initWithStyle:UITableViewStyleGrouped]; - selectLanguageViewController.currentlySelectedLanguageId = [[_currentLanguage objectForKey:@"lang_id"] intValue]; - selectLanguageViewController.didSelectLanguage = ^(NSDictionary *language){ - _currentLanguage = language; - [self.tableView reloadData]; - }; - [self.navigationController pushViewController:selectLanguageViewController animated:YES]; - } else if (indexPath.row == 3) { - SelectWPComBlogVisibilityViewController *selectedVisibilityViewController = [[SelectWPComBlogVisibilityViewController alloc] initWithStyle:UITableViewStyleGrouped]; - selectedVisibilityViewController.currentBlogVisibility = _blogVisibility; - selectedVisibilityViewController.delegate = self; - [self.navigationController pushViewController:selectedVisibilityViewController animated:YES]; - } - } else { - [self clickedCreateBlog]; - } -} - -#pragma mark - UITextField delegate methods - -- (BOOL)textFieldShouldReturn:(UITextField *)textField { - [textField resignFirstResponder]; - - switch (textField.tag) { - case CreateBlogBlogUrlFieldTag: - [_blogTitleTextField becomeFirstResponder]; - break; - default: - break; - } - - return YES; -} - -#pragma mark - SelectWPComBlogVisibilityViewControllerDelegate - -- (void)selectWPComBlogVisibilityViewController:(SelectWPComBlogVisibilityViewController *)viewController didSelectBlogVisibilitySetting:(WordPressComApiBlogVisibility)visibility -{ - _blogVisibility = visibility; - [self.tableView reloadData]; -} - -#pragma mark - Private Methods - -- (void)toggleGeolocation:(id)sender -{ - UISwitch *geolocationSwitch = (UISwitch *)sender; - _geolocationEnabled = geolocationSwitch.on; -} - -- (void)clickedCreateBlog -{ - [self.view endEditing:YES]; - - if (![self areFieldsValid]) { - [self displayErrorMessage]; - return; - } - - if (![ReachabilityUtils isInternetReachable]) { - [ReachabilityUtils showAlertNoInternetConnection]; - return; - } - - _isCreatingBlog = YES; - [self.tableView reloadData]; - [[WordPressComApi sharedApi] createWPComBlogWithUrl:_blogUrlTextField.text andBlogTitle:_blogTitleTextField.text andLanguageId:[_currentLanguage objectForKey:@"lang_id"] andBlogVisibility:_blogVisibility success:^(id responseObject){ - NSDictionary *blogDetails = [responseObject dictionaryForKey:@"blog_details"]; - [self createBlog:blogDetails]; - [self.delegate createdBlogWithDetails:blogDetails]; - } failure:^(NSError *error){ - if (!_userPressedBackButton) { - _isCreatingBlog = NO; - [self.tableView reloadData]; - [self displayCreationError:error]; - } - }]; -} - -- (BOOL)areFieldsValid -{ - BOOL areFieldsFilled = [[_blogTitleTextField.text trim] length] != 0 && [[_blogUrlTextField.text trim] length] != 0; - BOOL urlDoesNotHavePeriod = [_blogUrlTextField.text rangeOfString:@"."].location == NSNotFound; - - return areFieldsFilled && urlDoesNotHavePeriod; -} - -- (void)displayErrorMessage -{ - NSString *errorMessage; - - if ([[_blogUrlTextField.text trim] length] == 0) { - errorMessage = NSLocalizedString(@"Blog address is required.", nil); - } else if ([_blogUrlTextField.text rangeOfString:@"."].location != NSNotFound) { - errorMessage = NSLocalizedString(@"Blog url cannot contain a period", nil); - } else if ([[_blogTitleTextField.text trim] length] == 0) { - errorMessage = NSLocalizedString(@"Must set a blog title", nil); - } - - if (errorMessage != nil) { - _footerText = errorMessage; - [self.tableView reloadData]; - } -} - -// TODO : Figure out where to put this so we aren't duplicating code with AddUsersBlogViewController -- (void)createBlog:(NSDictionary *)blogInfo { - NSMutableDictionary *newBlog = [NSMutableDictionary dictionary]; - [newBlog setObject:[blogInfo objectForKey:@"blogname"] forKey:@"blogName"]; - [newBlog setObject:[blogInfo objectForKey:@"blogid"] forKey:@"blogid"]; - [newBlog setObject:[blogInfo objectForKey:@"url"] forKey:@"url"]; - [newBlog setObject:[blogInfo objectForKey:@"xmlrpc"] forKey:@"xmlrpc"]; - - WPAccount *account = [WPAccount defaultWordPressComAccount]; - - Blog *blog = [account findOrCreateBlogFromDictionary:newBlog withContext:account.managedObjectContext]; - blog.geolocationEnabled = _geolocationEnabled; - [blog dataSave]; - [blog syncBlogWithSuccess:^{ - if( ! [blog isWPcom] ) - [[WordPressComApi sharedApi] syncPushNotificationInfo]; - } - failure:nil]; - [[NSNotificationCenter defaultCenter] postNotificationName:@"BlogsRefreshNotification" object:nil]; - - [[WordPressComApi sharedApi] syncPushNotificationInfo]; -} - -- (void)displayCreationError:(NSError *)error -{ - NSString *errorMessage = [error.userInfo objectForKey:WordPressComApiErrorMessageKey]; - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", nil) message:errorMessage delegate:nil cancelButtonTitle:NSLocalizedString(@"OK", nil) otherButtonTitles:nil, nil]; - [alertView show]; -} - -- (NSString *)textForCurrentBlogVisibility -{ - if (_blogVisibility == WordPressComApiBlogVisibilityPublic) { - return NSLocalizedString(@"Public", nil); - } else if (_blogVisibility == WordPressComApiComBlogVisibilityPrivate) { - return NSLocalizedString(@"Private", nil); - } else { - return NSLocalizedString(@"Hidden", nil); - } -} - -- (void)styleTextFieldCell:(UITableViewTextFieldCell *)cell -{ - [WPStyleGuide configureTableViewCell:cell]; - cell.textField.font = [WPStyleGuide tableviewTextFont]; -} - -@end diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 857c8e79c241..d737d93f4041 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -12,7 +12,6 @@ #import "UIView+FormSheetHelpers.h" #import "LoginViewController.h" #import "CreateAccountAndBlogViewController.h" -#import "NewAddUsersBlogViewController.h" #import "AboutViewController.h" #import "SupportViewController.h" #import "WPNUXMainButton.h" diff --git a/WordPress/Classes/NewAddUsersBlogViewController.h b/WordPress/Classes/NewAddUsersBlogViewController.h deleted file mode 100644 index 22f08f762de0..000000000000 --- a/WordPress/Classes/NewAddUsersBlogViewController.h +++ /dev/null @@ -1,22 +0,0 @@ -// -// NewAddUsersBlogViewController.h -// WordPress -// -// Created by Sendhil Panchadsaram on 5/2/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import - -@class WPAccount; -@interface NewAddUsersBlogViewController : UIViewController - -@property (nonatomic, assign) BOOL autoAddSingleBlog; -@property (nonatomic, strong) NSString *siteUrl; -@property (nonatomic, strong) WPAccount *account; - -@property (nonatomic, copy ) void (^blogAdditionCompleted)(NewAddUsersBlogViewController *); -@property (nonatomic, copy ) void (^onNoBlogsLoaded)(NewAddUsersBlogViewController *); -@property (nonatomic, copy ) void (^onErrorLoading)(NewAddUsersBlogViewController *, NSError *); - -@end diff --git a/WordPress/Classes/NewAddUsersBlogViewController.m b/WordPress/Classes/NewAddUsersBlogViewController.m deleted file mode 100644 index 642a0afad2b6..000000000000 --- a/WordPress/Classes/NewAddUsersBlogViewController.m +++ /dev/null @@ -1,459 +0,0 @@ -// -// NewAddUsersBlogViewController.m -// WordPress -// -// Created by Sendhil Panchadsaram on 5/2/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import -#import -#import "WordPressAppDelegate.h" -#import "UIView+FormSheetHelpers.h" -#import "NewAddUsersBlogViewController.h" -#import "WPNUXPrimaryButton.h" -#import "WPNUXSecondaryButton.h" -#import "AddUsersBlogCell.h" -#import "NSString+XMLExtensions.h" -#import "WordPressComApi.h" -#import "Blog.h" -#import "WPNUXUtility.h" -#import "WPAccount.h" -#import "UILabel+SuggestSize.h" - -@interface NewAddUsersBlogViewController () < - UITableViewDelegate, - UITableViewDataSource> { - NSArray *_usersBlogs; - NSMutableArray *_selectedBlogs; - WPNUXSecondaryButton *_selectAllButton; - WPNUXPrimaryButton *_addSelectedButton; - UIView *_mainView; - - CGFloat _viewWidth; - CGFloat _viewHeight; -} - -@property (nonatomic, strong) UITableView *tableView; - -@end - -@implementation NewAddUsersBlogViewController - -CGFloat const AddUsersBlogHeaderHeight = 164.0; -CGFloat const AddUsersBlogStandardOffset = 16.0; -CGFloat const AddUsersBlogTitleVerticalOffset = 23.0; -CGFloat const AddUsersBlogMaxTextWidth = 289.0; -CGFloat const AddUsersBlogBottomBackgroundHeight = 64; - - -- (id)init -{ - self = [super init]; - if (self) { - _selectedBlogs = [[NSMutableArray alloc] init]; - _autoAddSingleBlog = YES; - } - return self; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventAddBlogsOpened]; - - _viewWidth = [self.view formSheetViewWidth]; - _viewHeight = [self.view formSheetViewHeight]; - - [self addMainView]; - [self addTableView]; - [self addBottomPanel]; -} - -- (void)viewDidAppear:(BOOL)animated -{ - [super viewDidAppear:animated]; - [self refreshBlogs]; -} - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -{ - return [super shouldAutorotateToInterfaceOrientation:interfaceOrientation]; -} - -- (NSUInteger)supportedInterfaceOrientations { - if (IS_IPHONE) - return UIInterfaceOrientationMaskPortrait; - - return UIInterfaceOrientationMaskAll; -} - -#pragma mark - Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView -{ - return 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - return [_usersBlogs count]; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - static NSString *CellIdentifier = @"Cell"; - AddUsersBlogCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; - if (cell == nil) { - cell = [[AddUsersBlogCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; - } - - cell.selectionStyle = UITableViewCellSelectionStyleNone; - cell.isWPCom = self.account.isWpcom; - - NSDictionary *blogData = [_usersBlogs objectAtIndex:indexPath.row]; - cell.showTopSeparator = indexPath.row == 0; - cell.title = [self getCellTitleForIndexPath:indexPath]; - cell.blavatarUrl = [blogData objectForKey:@"url"]; - cell.selected = [_selectedBlogs containsObject:[blogData objectForKey:@"blogid"]]; - - return cell; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath -{ - return [AddUsersBlogCell rowHeightWithText:[self getCellTitleForIndexPath:indexPath]]; -} - -#pragma mark - Table view delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - NSDictionary *blogData = [_usersBlogs objectAtIndex:indexPath.row]; - NSString *blogId = [blogData objectForKey:@"blogid"]; - if ([_selectedBlogs containsObject:blogId]) { - [_selectedBlogs removeObject:blogId]; - } else { - [_selectedBlogs addObject:blogId]; - } - [tableView reloadData]; - [self toggleButtons]; -} - -#pragma mark - Private Methods - -- (void)addMainView -{ - _mainView = [[UIView alloc] initWithFrame:self.view.bounds]; - [self.view addSubview:_mainView]; - _mainView.userInteractionEnabled = NO; -} - -- (void)addTableView -{ - CGRect tableViewFrame = CGRectMake(0, 0, _viewWidth, _viewHeight); - tableViewFrame.size.height -= AddUsersBlogBottomBackgroundHeight; - - self.tableView = [[UITableView alloc] initWithFrame:tableViewFrame style:UITableViewStylePlain]; - self.tableView.backgroundColor = [UIColor clearColor]; - self.tableView.delegate = self; - self.tableView.dataSource = self; - self.view.backgroundColor = [WPNUXUtility backgroundColor]; - self.tableView.tableHeaderView = [self headerView]; - self.tableView.separatorStyle = UITableViewCellSeparatorStyleNone; - [self.view addSubview:self.tableView]; -} - -- (void)addBottomPanel -{ - UIView *bottomPanel = [[UIView alloc] init]; - bottomPanel.backgroundColor = [WPNUXUtility bottomPanelBackgroundColor]; - bottomPanel.frame = CGRectMake(0, CGRectGetMaxY(self.tableView.frame), _viewWidth, AddUsersBlogBottomBackgroundHeight); - [self.view addSubview:bottomPanel]; - - UIView *bottomPanelLine = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _viewWidth, 1)]; - bottomPanelLine.backgroundColor = [WPNUXUtility bottomPanelLineColor]; - [bottomPanel addSubview:bottomPanelLine]; - - _selectAllButton = [[WPNUXSecondaryButton alloc] init]; - [_selectAllButton setTitle:NSLocalizedString(@"Select All", nil) forState:UIControlStateNormal]; - _selectAllButton.titleLabel.adjustsFontSizeToFitWidth = YES; - [_selectAllButton sizeToFit]; - [_selectAllButton addTarget:self action:@selector(selectAllBlogs) forControlEvents:UIControlEventTouchUpInside]; - [bottomPanel addSubview:_selectAllButton]; - - CGFloat selectAllWidth = CGRectGetWidth(_selectAllButton.frame); - // This part is to ensure that we have the larger of the two widths for the two text options for this button - // so that regardless of what text is in the button it will fit - [_selectAllButton setTitle:NSLocalizedString(@"Deselect All", nil) forState:UIControlStateNormal]; - [_selectAllButton sizeToFit]; - CGFloat deselectAllWidth = CGRectGetWidth(_selectAllButton.frame); - [_selectAllButton setTitle:NSLocalizedString(@"Select All", nil) forState:UIControlStateNormal]; - CGRect selectAllFrame = _selectAllButton.frame; - selectAllFrame.size.width = selectAllWidth > deselectAllWidth ? selectAllWidth : deselectAllWidth; - - _addSelectedButton = [[WPNUXPrimaryButton alloc] init]; - [_addSelectedButton setTitle:NSLocalizedString(@"Add Selected", nil) forState:UIControlStateNormal]; - _addSelectedButton.titleLabel.adjustsFontSizeToFitWidth = YES; - // Calculate the space with the largest possible text width before setting the text back to normal. We calculate this - // ahead of time so that way we don't have flickering as the text changes result in the button size changing. This also - // ensures we don't have to re-layout the button as the text changes as well. - [_addSelectedButton setTitle:[NSString stringWithFormat:@"%@ (100)", NSLocalizedString(@"Add Selected", nil)] forState:UIControlStateNormal]; - [_addSelectedButton sizeToFit]; - [_addSelectedButton setTitle:[NSString stringWithFormat:@"%@ (1)", NSLocalizedString(@"Add Selected", nil)] forState:UIControlStateNormal]; - [_addSelectedButton addTarget:self action:@selector(createBlogs) forControlEvents:UIControlEventTouchUpInside]; - [bottomPanel addSubview:_addSelectedButton]; - - // For some locales, these strings can be long so we try to balance the widths. - CGFloat availableWidth = _viewWidth - 3 * AddUsersBlogStandardOffset; - CGFloat widthRatio = availableWidth / (CGRectGetWidth(_addSelectedButton.frame) + CGRectGetWidth(selectAllFrame)); - - CGFloat maxWidth = CGRectGetWidth(_selectAllButton.frame) * widthRatio; - CGFloat x,y; - x = AddUsersBlogStandardOffset; - y = AddUsersBlogStandardOffset; - _selectAllButton.frame = CGRectIntegral(CGRectMake(x, y, MIN(CGRectGetWidth(_selectAllButton.frame), maxWidth), CGRectGetHeight(_selectAllButton.frame))); - - maxWidth = CGRectGetWidth(_addSelectedButton.frame) * widthRatio; - CGFloat addSelectedButtonWidth = MIN(CGRectGetWidth(_addSelectedButton.frame), maxWidth); - x = _viewWidth - addSelectedButtonWidth - AddUsersBlogStandardOffset; - y = AddUsersBlogStandardOffset; - _addSelectedButton.frame = CGRectIntegral(CGRectMake(x, y, addSelectedButtonWidth, CGRectGetHeight(_addSelectedButton.frame))); -} - -- (UIView *)headerView -{ - CGFloat x, y; - UIView *headerView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, _viewWidth, AddUsersBlogHeaderHeight)]; - headerView.backgroundColor = [UIColor clearColor]; - - UILabel *title = [[UILabel alloc] init]; - title.backgroundColor = [UIColor clearColor]; - title.textAlignment = NSTextAlignmentCenter; - title.lineBreakMode = NSLineBreakByWordWrapping; - title.font = [UIFont fontWithName:@"OpenSans-Light" size:29.0]; - title.text = NSLocalizedString(@"Select the sites you want to add", nil); - title.textColor = [UIColor whiteColor]; - title.numberOfLines = 0; - CGSize titleSize = [title suggestedSizeForWidth:AddUsersBlogMaxTextWidth]; - x = (_viewWidth - titleSize.width)/2.0; - y = CGRectGetHeight(headerView.frame) - titleSize.height - AddUsersBlogTitleVerticalOffset; - title.frame = CGRectMake(x, y, titleSize.width, titleSize.height); - [headerView addSubview:title]; - - return headerView; -} - -- (UIView *)checkmarkAccessoryView -{ - UIImage *image = [UIImage imageNamed:@"addBlogsSelectedImage"]; - UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; - return imageView; -} - -- (void)refreshBlogs -{ - NSURL *xmlrpc = [NSURL URLWithString:self.account.xmlrpc]; - NSString *username = self.account.username; - NSString *password = self.account.password; - - [self.tableView reloadData]; - [SVProgressHUD showWithStatus:NSLocalizedString(@"Loading sites...", nil) maskType:SVProgressHUDMaskTypeBlack]; - - WPXMLRPCClient *api = [WPXMLRPCClient clientWithXMLRPCEndpoint:xmlrpc]; - [api callMethod:@"wp.getUsersBlogs" - parameters:[NSArray arrayWithObjects:username, password, nil] - success:^(AFHTTPRequestOperation *operation, id responseObject) { - [SVProgressHUD dismiss]; - [self storeUsersVisibleBlogs:responseObject]; - - if (_usersBlogs.count == 0) { - if (self.onNoBlogsLoaded) { - self.onNoBlogsLoaded(self); - } - } else { - [self selectAppropriateBlog]; - - if(_usersBlogs.count == 1 && self.autoAddSingleBlog) { - [self selectAllBlogs]; - [self createBlogs]; - } - } - - [self toggleButtons]; - [self.tableView reloadData]; - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - [SVProgressHUD dismiss]; - [self.tableView reloadData]; - DDLogError(@"Failed getting user blogs: %@", [error localizedDescription]); - if (self.onErrorLoading) { - self.onErrorLoading(self, error); - } - }]; -} - -- (void)selectAppropriateBlog -{ - if (self.siteUrl == nil) { - [self selectFirstBlog]; - } else { - // This strips out any leading http:// or https:// making for an easier string match. - NSString *desiredBlogUrl = [[NSURL URLWithString:self.siteUrl] absoluteString]; - - __block BOOL blogFound = NO; - __block NSUInteger indexOfBlog; - [_usersBlogs enumerateObjectsUsingBlock:^(id blogInfo, NSUInteger index, BOOL *stop){ - NSString *blogUrl = [blogInfo objectForKey:@"url"]; - if ([blogUrl rangeOfString:desiredBlogUrl options:NSCaseInsensitiveSearch].location != NSNotFound) { - blogFound = YES; - [_selectedBlogs addObject:[blogInfo objectForKey:@"blogid"]]; - indexOfBlog = index; - *stop = YES; - } - }]; - - if (!blogFound) { - [self selectFirstBlog]; - } else { - // Let's make sure the blog we selected is at the top of the list the user sees. - NSMutableArray *rearrangedUsersBlogs = [NSMutableArray arrayWithArray:_usersBlogs]; - NSDictionary *selectedBlogInfo = [rearrangedUsersBlogs objectAtIndex:indexOfBlog]; - [rearrangedUsersBlogs removeObjectAtIndex:indexOfBlog]; - [rearrangedUsersBlogs insertObject:selectedBlogInfo atIndex:0]; - _usersBlogs = rearrangedUsersBlogs; - } - } -} - -- (void)selectFirstBlog -{ - NSString *firstBlogId = [[_usersBlogs objectAtIndex:0] objectForKey:@"blogid"]; - if (![_selectedBlogs containsObject:firstBlogId]) { - [_selectedBlogs addObject:firstBlogId]; - } -} - -- (void)storeUsersVisibleBlogs:(NSArray *)blogs -{ - _usersBlogs = [blogs filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { - NSNumber *hidden = [evaluatedObject objectForKey:@"hidden"]; - return ((hidden == nil) || [hidden boolValue]); - }]]; - [_usersBlogs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - NSString *title = [obj valueForKey:@"blogName"]; - title = [title stringByDecodingXMLCharacters]; - [obj setValue:title forKey:@"blogName"]; - }]; - _usersBlogs = [_usersBlogs sortedArrayUsingComparator:^(id obj1, id obj2){ - NSString *title1 = [obj1 valueForKey:@"blogName"]; - NSString *title2 = [obj2 valueForKey:@"blogName"]; - return [title1 localizedCaseInsensitiveCompare:title2]; - }]; -} - -- (void)createBlogs -{ - NSDictionary *properties = @{@"number_of_blogs": [NSNumber numberWithInt:[_selectedBlogs count]]}; - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventAddBlogsClickedAddSelected properties:properties]; - - _addSelectedButton.enabled = NO; - - NSManagedObjectContext *context = [WordPressAppDelegate sharedWordPressApplicationDelegate].managedObjectContext; - NSManagedObjectContext *backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; - backgroundMOC.parentContext = context; - - [backgroundMOC performBlock:^{ - for (NSDictionary *blog in _usersBlogs) { - if([_selectedBlogs containsObject:[blog valueForKey:@"blogid"]]) { - [self createBlog:blog withContext:context]; - } - } - NSError *error; - if (![backgroundMOC save:&error]) { - DDLogError(@"Unresolved core data save error: %@", error); - } - - dispatch_async(dispatch_get_main_queue(), ^{ - if (self.blogAdditionCompleted) { - self.blogAdditionCompleted(self); - } - [[WordPressComApi sharedApi] syncPushNotificationInfo]; - [[NSNotificationCenter defaultCenter] postNotificationName:@"BlogsRefreshNotification" object:nil]; - }); - }]; -} - -- (void)createBlog:(NSDictionary *)blogInfo withContext:(NSManagedObjectContext *)context -{ - DDLogInfo(@"creating blog: %@", blogInfo); - Blog *blog = [_account findOrCreateBlogFromDictionary:blogInfo withContext:context]; - blog.geolocationEnabled = YES; - - [blog syncBlogWithSuccess:nil failure:nil]; -} - -- (void)toggleButtons -{ - _addSelectedButton.enabled = [_selectedBlogs count] > 0; - [_addSelectedButton setTitle:[NSString stringWithFormat:@"%@ (%d)", NSLocalizedString(@"Add Selected", nil), [_selectedBlogs count]] forState:UIControlStateNormal]; - _selectAllButton.enabled = [_usersBlogs count] != 0; - if ([_selectedBlogs count] == [_usersBlogs count]) { - [self setupDeselectAllButton]; - } else { - [self setupSelectAllButton]; - } -} - -- (void)selectAllBlogs -{ - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventAddBlogsClickedSelectAll]; - - [self setupDeselectAllButton]; - - [_selectedBlogs removeAllObjects]; - for (NSDictionary *blogData in _usersBlogs) { - NSString *blogId = [blogData objectForKey:@"blogid"]; - [_selectedBlogs addObject:blogId]; - } - - [self toggleButtons]; - [self.tableView reloadData]; -} - -- (void)deselectAllBlogs -{ - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventAddBlogsClickedDeselectAll]; - - [self setupSelectAllButton]; - - [_selectedBlogs removeAllObjects]; - - [self toggleButtons]; - [self.tableView reloadData]; -} - -- (void)setupSelectAllButton -{ - [_selectAllButton removeTarget:self action:@selector(deselectAllBlogs) forControlEvents:UIControlEventTouchUpInside]; - [_selectAllButton addTarget:self action:@selector(selectAllBlogs) forControlEvents:UIControlEventTouchUpInside]; - [_selectAllButton setTitle:NSLocalizedString(@"Select All", nil) forState:UIControlStateNormal]; -} - -- (void)setupDeselectAllButton -{ - [_selectAllButton removeTarget:self action:@selector(selectAllBlogs) forControlEvents:UIControlEventTouchUpInside]; - [_selectAllButton addTarget:self action:@selector(deselectAllBlogs) forControlEvents:UIControlEventTouchUpInside]; - [_selectAllButton setTitle:NSLocalizedString(@"Deselect All", nil) forState:UIControlStateNormal]; -} - -- (NSString *)getCellTitleForIndexPath:(NSIndexPath *)indexPath -{ - NSDictionary *blogData = [_usersBlogs objectAtIndex:indexPath.row]; - if ([[[blogData objectForKey:@"blogName"] trim] length] == 0) - return [blogData objectForKey:@"url"]; - else - return [blogData objectForKey:@"blogName"]; -} - -@end diff --git a/WordPress/Classes/SelectWPComBlogVisibilityViewController.h b/WordPress/Classes/SelectWPComBlogVisibilityViewController.h deleted file mode 100644 index c0f03f207a4a..000000000000 --- a/WordPress/Classes/SelectWPComBlogVisibilityViewController.h +++ /dev/null @@ -1,24 +0,0 @@ -// -// SelectWPComBlogVisibilityViewController.h -// WordPress -// -// Created by Sendhil Panchadsaram on 4/16/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import -#import "WordPressComApi.h" - -@protocol SelectWPComBlogVisibilityViewControllerDelegate; -@interface SelectWPComBlogVisibilityViewController : UITableViewController - -@property (nonatomic, assign) WordPressComApiBlogVisibility currentBlogVisibility; -@property (nonatomic, weak) id delegate; - -@end - -@protocol SelectWPComBlogVisibilityViewControllerDelegate - -- (void)selectWPComBlogVisibilityViewController:(SelectWPComBlogVisibilityViewController *)viewController didSelectBlogVisibilitySetting:(WordPressComApiBlogVisibility)visibility; - -@end diff --git a/WordPress/Classes/SelectWPComBlogVisibilityViewController.m b/WordPress/Classes/SelectWPComBlogVisibilityViewController.m deleted file mode 100644 index c499c82ebc71..000000000000 --- a/WordPress/Classes/SelectWPComBlogVisibilityViewController.m +++ /dev/null @@ -1,109 +0,0 @@ -// -// SelectWPComBlogVisibilityViewController.m -// WordPress -// -// Created by Sendhil Panchadsaram on 4/16/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import "SelectWPComBlogVisibilityViewController.h" -#import "WPTableViewSectionFooterView.h" - -@interface SelectWPComBlogVisibilityViewController () { - NSArray *_visibilityOptions; -} - -@end - -@implementation SelectWPComBlogVisibilityViewController - -- (id)initWithStyle:(UITableViewStyle)style -{ - self = [super initWithStyle:style]; - - if (self) { - _visibilityOptions = @[ - NSLocalizedString(@"Public", nil), - NSLocalizedString(@"Hidden", nil), - NSLocalizedString(@"Private", nil)]; - _currentBlogVisibility = WordPressComApiBlogVisibilityPublic; - } - - return self; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - self.navigationItem.title = NSLocalizedString(@"Blog Visibility", nil); -} - -#pragma mark - Table view data source - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section -{ - // Return the number of rows in the section. - return [_visibilityOptions count]; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - static NSString *CellIdentifier = @"Cell"; - - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; - if (cell == nil) { - cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; - } - - if (indexPath.row == self.currentBlogVisibility) { - cell.accessoryType = UITableViewCellAccessoryCheckmark; - } else { - cell.accessoryType = UITableViewCellAccessoryNone; - } - cell.textLabel.text = [_visibilityOptions objectAtIndex:indexPath.row]; - - return cell; -} - - -#pragma mark - Table view delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath -{ - WordPressComApiBlogVisibility visibility; - if (indexPath.row == 0) { - visibility = WordPressComApiBlogVisibilityPublic; - } else if (indexPath.row == 1) { - visibility = WordPressComApiBlogVisibilityHidden; - } else { - visibility = WordPressComApiComBlogVisibilityPrivate; - } - [self.delegate selectWPComBlogVisibilityViewController:self didSelectBlogVisibilitySetting:visibility]; - [self.navigationController popViewControllerAnimated:YES]; -} - -#pragma mark - Private Methods - -- (NSString *)titleForFooterInSection:(NSInteger)section { - NSMutableString *text = [[NSMutableString alloc] init]; - [text appendFormat:@"%@ - %@\n\n", NSLocalizedString(@"Public", nil), NSLocalizedString(@"Blog_Visibility_Public_Description", nil)]; - [text appendFormat:@"%@ - %@\n\n", NSLocalizedString(@"Hidden", nil), NSLocalizedString(@"Blog_Visibility_Hidden_Description", nil)]; - [text appendFormat:@"%@ - %@", NSLocalizedString(@"Private", nil), NSLocalizedString(@"Blog_Visibility_Private_Description", nil)]; - - return text; -} - -- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section -{ - WPTableViewSectionFooterView *header = [[WPTableViewSectionFooterView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 0)]; - header.title = [self titleForFooterInSection:section]; - return header; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section -{ - NSString *title = [self titleForFooterInSection:section]; - return [WPTableViewSectionFooterView heightForTitle:title andWidth:CGRectGetWidth(self.view.bounds)]; -} - -@end diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index 3037f0341980..090b0c91093d 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -41,7 +41,6 @@ #import "SupportViewController.h" #import "WPAccount.h" #import "WPTableViewSectionHeaderView.h" -#import "AddUsersBlogsViewController.h" #import "SupportViewController.h" typedef enum { diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index f0ca06b18d4b..53aebd42af93 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -533,7 +533,6 @@ 83610AAA11F4AD2C00421116 /* WPcomLoginViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 83610AA811F4AD2C00421116 /* WPcomLoginViewController.m */; }; 8362C1041201E7CE00599347 /* WebSignupViewController-iPad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8362C1031201E7CE00599347 /* WebSignupViewController-iPad.xib */; }; 8362C54612027BC300599347 /* AddUsersBlogsViewController~ipad.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8362C54512027BC300599347 /* AddUsersBlogsViewController~ipad.xib */; }; - 8369FF9111F4F3BF003106C7 /* AddUsersBlogsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8369FF8F11F4F3BF003106C7 /* AddUsersBlogsViewController.m */; }; 8369FF9211F4F3BF003106C7 /* AddUsersBlogsViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8369FF9011F4F3BF003106C7 /* AddUsersBlogsViewController.xib */; }; 8370D10A11FA499A009D650F /* UITableViewActivityCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 8370D10911FA499A009D650F /* UITableViewActivityCell.m */; }; 8370D10C11FA4A1B009D650F /* UITableViewActivityCell.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8370D10B11FA4A1B009D650F /* UITableViewActivityCell.xib */; }; @@ -543,7 +542,6 @@ 8370D11F11FA4CD5009D650F /* logo_wporg.png in Resources */ = {isa = PBXBuildFile; fileRef = 8370D11B11FA4CD5009D650F /* logo_wporg.png */; }; 8370D12011FA4CD5009D650F /* logo_wpcom@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 8370D11C11FA4CD5009D650F /* logo_wpcom@2x.png */; }; 8370D12111FA4CD5009D650F /* logo_wpcom.png in Resources */ = {isa = PBXBuildFile; fileRef = 8370D11D11FA4CD5009D650F /* logo_wpcom.png */; }; - 8370D1BD11FA6295009D650F /* AddSiteViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8370D1BB11FA6295009D650F /* AddSiteViewController.m */; }; 8370D1BE11FA6295009D650F /* AddSiteViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 8370D1BC11FA6295009D650F /* AddSiteViewController.xib */; }; 837576C511305C67002EAA27 /* hasLocation.png in Resources */ = {isa = PBXBuildFile; fileRef = 837576C211305C67002EAA27 /* hasLocation.png */; }; 8383178812270E980047B476 /* PostMediaViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8383178612270E980047B476 /* PostMediaViewController.m */; }; @@ -571,7 +569,6 @@ 850DE07017CDAF92003A1057 /* icon-comments-approve-active@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 850DE06817CDAF92003A1057 /* icon-comments-approve-active@2x.png */; }; 850DE07117CDAF92003A1057 /* icon-comments-approve-active.png in Resources */ = {isa = PBXBuildFile; fileRef = 850DE06917CDAF92003A1057 /* icon-comments-approve-active.png */; }; 85149741171E13DF00B87F3F /* WPAsyncBlockOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = 85149740171E13DF00B87F3F /* WPAsyncBlockOperation.m */; }; - 85149747171E671000B87F3F /* SelectWPComBlogVisibilityViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 85149746171E671000B87F3F /* SelectWPComBlogVisibilityViewController.m */; }; 8516972C169D42F4006C5DED /* WPToast.m in Sources */ = {isa = PBXBuildFile; fileRef = 8516972B169D42F4006C5DED /* WPToast.m */; }; 851734431798C64700A30E27 /* NSURL+Util.m in Sources */ = {isa = PBXBuildFile; fileRef = 851734421798C64700A30E27 /* NSURL+Util.m */; }; 8524551717DE4DBE00D22F98 /* icon-chevron.png in Resources */ = {isa = PBXBuildFile; fileRef = 8524551517DE4DBE00D22F98 /* icon-chevron.png */; }; @@ -645,7 +642,6 @@ 85495F6717C6FACF00871A7A /* icon-comments-edit.png in Resources */ = {isa = PBXBuildFile; fileRef = 85495F5717C6FACF00871A7A /* icon-comments-edit.png */; }; 85495F6817C6FACF00871A7A /* icon-comments-edit-active@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 85495F5817C6FACF00871A7A /* icon-comments-edit-active@2x.png */; }; 85495F6917C6FACF00871A7A /* icon-comments-edit-active.png in Resources */ = {isa = PBXBuildFile; fileRef = 85495F5917C6FACF00871A7A /* icon-comments-edit-active.png */; }; - 8566BC95170F84BC003C6BCF /* CreateWPComAccountViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 8566BC93170F84BC003C6BCF /* CreateWPComAccountViewController.m */; }; 857F55B517CEA01A00E154E1 /* WPKeyboardToolbarBase.m in Sources */ = {isa = PBXBuildFile; fileRef = 857F55B417CEA01A00E154E1 /* WPKeyboardToolbarBase.m */; }; 857F55B817CEA2B200E154E1 /* WPKeyboardToolbarWithoutGradient.m in Sources */ = {isa = PBXBuildFile; fileRef = 857F55B717CEA2B200E154E1 /* WPKeyboardToolbarWithoutGradient.m */; }; 857F55CB17CEC5E100E154E1 /* toggleButtonMain-ios7@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 857F55C317CEC5E100E154E1 /* toggleButtonMain-ios7@2x.png */; }; @@ -696,10 +692,8 @@ 85C9172717CECAA6001ECEC3 /* icon-reader-topics-active@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 85C9172317CECAA6001ECEC3 /* icon-reader-topics-active@2x.png */; }; 85C9172817CECAA6001ECEC3 /* icon-reader-topics.png in Resources */ = {isa = PBXBuildFile; fileRef = 85C9172417CECAA6001ECEC3 /* icon-reader-topics.png */; }; 85C9172917CECAA6001ECEC3 /* icon-reader-topics@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 85C9172517CECAA6001ECEC3 /* icon-reader-topics@2x.png */; }; - 85D08A5E17332C4A00E2BBCA /* NewAddUsersBlogViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 85D08A5D17332C4A00E2BBCA /* NewAddUsersBlogViewController.m */; }; 85D08A7117342ECE00E2BBCA /* AddUsersBlogCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 85D08A7017342ECE00E2BBCA /* AddUsersBlogCell.m */; }; 85D2415817D0701A00AF090E /* UIViewController+iOS7StyleChanges.m in Sources */ = {isa = PBXBuildFile; fileRef = 85D2415717D0701A00AF090E /* UIViewController+iOS7StyleChanges.m */; }; - 85D805521715F4EA0075EEAC /* CreateWPComBlogViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 85D805511715F4EA0075EEAC /* CreateWPComBlogViewController.m */; }; 85D80558171630B30075EEAC /* DotCom-Languages.plist in Resources */ = {isa = PBXBuildFile; fileRef = 85D80557171630B30075EEAC /* DotCom-Languages.plist */; }; 85D8055D171631F10075EEAC /* SelectWPComLanguageViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 85D8055C171631F10075EEAC /* SelectWPComLanguageViewController.m */; }; 85E105861731A597001071A3 /* WPWalkthroughOverlayView.m in Sources */ = {isa = PBXBuildFile; fileRef = 85E105851731A597001071A3 /* WPWalkthroughOverlayView.m */; }; @@ -1596,8 +1590,6 @@ 83610AA811F4AD2C00421116 /* WPcomLoginViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPcomLoginViewController.m; sourceTree = ""; }; 8362C1031201E7CE00599347 /* WebSignupViewController-iPad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "WebSignupViewController-iPad.xib"; path = "Resources-iPad/WebSignupViewController-iPad.xib"; sourceTree = ""; }; 8362C54512027BC300599347 /* AddUsersBlogsViewController~ipad.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = "AddUsersBlogsViewController~ipad.xib"; path = "Resources-iPad/AddUsersBlogsViewController~ipad.xib"; sourceTree = ""; }; - 8369FF8E11F4F3BF003106C7 /* AddUsersBlogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddUsersBlogsViewController.h; sourceTree = ""; }; - 8369FF8F11F4F3BF003106C7 /* AddUsersBlogsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AddUsersBlogsViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 8369FF9011F4F3BF003106C7 /* AddUsersBlogsViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = AddUsersBlogsViewController.xib; path = Resources/AddUsersBlogsViewController.xib; sourceTree = ""; }; 8370D10811FA499A009D650F /* UITableViewActivityCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = UITableViewActivityCell.h; sourceTree = ""; }; 8370D10911FA499A009D650F /* UITableViewActivityCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = UITableViewActivityCell.m; sourceTree = ""; }; @@ -1608,8 +1600,6 @@ 8370D11B11FA4CD5009D650F /* logo_wporg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logo_wporg.png; path = Resources/Images/logo_wporg.png; sourceTree = ""; }; 8370D11C11FA4CD5009D650F /* logo_wpcom@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "logo_wpcom@2x.png"; path = "Resources/Images/logo_wpcom@2x.png"; sourceTree = ""; }; 8370D11D11FA4CD5009D650F /* logo_wpcom.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = logo_wpcom.png; path = Resources/Images/logo_wpcom.png; sourceTree = ""; }; - 8370D1BA11FA6295009D650F /* AddSiteViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddSiteViewController.h; sourceTree = ""; }; - 8370D1BB11FA6295009D650F /* AddSiteViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; lineEnding = 0; path = AddSiteViewController.m; sourceTree = ""; xcLanguageSpecificationIdentifier = xcode.lang.objc; }; 8370D1BC11FA6295009D650F /* AddSiteViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = AddSiteViewController.xib; path = Resources/AddSiteViewController.xib; sourceTree = ""; }; 837576C211305C67002EAA27 /* hasLocation.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = hasLocation.png; path = Resources/Images/hasLocation.png; sourceTree = ""; }; 8383178512270E980047B476 /* PostMediaViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PostMediaViewController.h; sourceTree = ""; }; @@ -1645,8 +1635,6 @@ 850DE06917CDAF92003A1057 /* icon-comments-approve-active.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-comments-approve-active.png"; sourceTree = ""; }; 8514973F171E13DF00B87F3F /* WPAsyncBlockOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPAsyncBlockOperation.h; sourceTree = ""; }; 85149740171E13DF00B87F3F /* WPAsyncBlockOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPAsyncBlockOperation.m; sourceTree = ""; }; - 85149745171E671000B87F3F /* SelectWPComBlogVisibilityViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectWPComBlogVisibilityViewController.h; sourceTree = ""; }; - 85149746171E671000B87F3F /* SelectWPComBlogVisibilityViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SelectWPComBlogVisibilityViewController.m; sourceTree = ""; }; 8516972A169D42F4006C5DED /* WPToast.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPToast.h; sourceTree = ""; }; 8516972B169D42F4006C5DED /* WPToast.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPToast.m; sourceTree = ""; }; 851734411798C64700A30E27 /* NSURL+Util.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSURL+Util.h"; sourceTree = ""; }; @@ -1729,8 +1717,6 @@ 85495F5717C6FACF00871A7A /* icon-comments-edit.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-comments-edit.png"; sourceTree = ""; }; 85495F5817C6FACF00871A7A /* icon-comments-edit-active@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-comments-edit-active@2x.png"; sourceTree = ""; }; 85495F5917C6FACF00871A7A /* icon-comments-edit-active.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-comments-edit-active.png"; sourceTree = ""; }; - 8566BC92170F84BC003C6BCF /* CreateWPComAccountViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CreateWPComAccountViewController.h; sourceTree = ""; }; - 8566BC93170F84BC003C6BCF /* CreateWPComAccountViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CreateWPComAccountViewController.m; sourceTree = ""; }; 857F55B317CEA01900E154E1 /* WPKeyboardToolbarBase.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPKeyboardToolbarBase.h; sourceTree = ""; }; 857F55B417CEA01A00E154E1 /* WPKeyboardToolbarBase.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPKeyboardToolbarBase.m; sourceTree = ""; }; 857F55B617CEA2B200E154E1 /* WPKeyboardToolbarWithoutGradient.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPKeyboardToolbarWithoutGradient.h; sourceTree = ""; }; @@ -1793,14 +1779,10 @@ 85C9172317CECAA6001ECEC3 /* icon-reader-topics-active@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-reader-topics-active@2x.png"; sourceTree = ""; }; 85C9172417CECAA6001ECEC3 /* icon-reader-topics.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-reader-topics.png"; sourceTree = ""; }; 85C9172517CECAA6001ECEC3 /* icon-reader-topics@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "icon-reader-topics@2x.png"; sourceTree = ""; }; - 85D08A5C17332C4A00E2BBCA /* NewAddUsersBlogViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewAddUsersBlogViewController.h; sourceTree = ""; }; - 85D08A5D17332C4A00E2BBCA /* NewAddUsersBlogViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewAddUsersBlogViewController.m; sourceTree = ""; }; 85D08A6F17342ECE00E2BBCA /* AddUsersBlogCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AddUsersBlogCell.h; sourceTree = ""; }; 85D08A7017342ECE00E2BBCA /* AddUsersBlogCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AddUsersBlogCell.m; sourceTree = ""; }; 85D2415617D0701A00AF090E /* UIViewController+iOS7StyleChanges.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIViewController+iOS7StyleChanges.h"; sourceTree = ""; }; 85D2415717D0701A00AF090E /* UIViewController+iOS7StyleChanges.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIViewController+iOS7StyleChanges.m"; sourceTree = ""; }; - 85D805501715F4EA0075EEAC /* CreateWPComBlogViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CreateWPComBlogViewController.h; sourceTree = ""; }; - 85D805511715F4EA0075EEAC /* CreateWPComBlogViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CreateWPComBlogViewController.m; sourceTree = ""; }; 85D80557171630B30075EEAC /* DotCom-Languages.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = "DotCom-Languages.plist"; sourceTree = ""; }; 85D8055B171631F10075EEAC /* SelectWPComLanguageViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = SelectWPComLanguageViewController.h; sourceTree = ""; }; 85D8055C171631F10075EEAC /* SelectWPComLanguageViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SelectWPComLanguageViewController.m; sourceTree = ""; }; @@ -2942,8 +2924,6 @@ 85EC44D31739826A00686604 /* CreateAccountAndBlogViewController.m */, 858DE40D1730384F000AC628 /* LoginViewController.h */, 858DE40E1730384F000AC628 /* LoginViewController.m */, - 85D08A5C17332C4A00E2BBCA /* NewAddUsersBlogViewController.h */, - 85D08A5D17332C4A00E2BBCA /* NewAddUsersBlogViewController.m */, 85B6F7501742DAE800CE7F3A /* WPNUXBackButton.h */, 85B6F7511742DAE800CE7F3A /* WPNUXBackButton.m */, 85B6F74D1742DA1D00CE7F3A /* WPNUXMainButton.h */, @@ -3310,20 +3290,10 @@ E13FA0FA134C8DDC007DCDD0 /* BlogSelectorViewController.m */, 83610AA711F4AD2C00421116 /* WPcomLoginViewController.h */, 83610AA811F4AD2C00421116 /* WPcomLoginViewController.m */, - 8370D1BA11FA6295009D650F /* AddSiteViewController.h */, - 8370D1BB11FA6295009D650F /* AddSiteViewController.m */, 83FEFC7311FF6C5A0078B462 /* EditSiteViewController.h */, 83FEFC7411FF6C5A0078B462 /* EditSiteViewController.m */, - 8369FF8E11F4F3BF003106C7 /* AddUsersBlogsViewController.h */, - 8369FF8F11F4F3BF003106C7 /* AddUsersBlogsViewController.m */, - 8566BC92170F84BC003C6BCF /* CreateWPComAccountViewController.h */, - 8566BC93170F84BC003C6BCF /* CreateWPComAccountViewController.m */, - 85D805501715F4EA0075EEAC /* CreateWPComBlogViewController.h */, - 85D805511715F4EA0075EEAC /* CreateWPComBlogViewController.m */, 85D8055B171631F10075EEAC /* SelectWPComLanguageViewController.h */, 85D8055C171631F10075EEAC /* SelectWPComLanguageViewController.m */, - 85149745171E671000B87F3F /* SelectWPComBlogVisibilityViewController.h */, - 85149746171E671000B87F3F /* SelectWPComBlogVisibilityViewController.m */, ); name = Blog; sourceTree = ""; @@ -5050,10 +5020,8 @@ E125443C12BF5A7200D87A0A /* WordPress.xcdatamodeld in Sources */, 8350E49611D2C71E00A7B073 /* Media.m in Sources */, 83610AAA11F4AD2C00421116 /* WPcomLoginViewController.m in Sources */, - 8369FF9111F4F3BF003106C7 /* AddUsersBlogsViewController.m in Sources */, 8370D10A11FA499A009D650F /* UITableViewActivityCell.m in Sources */, 93C486501810442200A24725 /* SupportViewController.m in Sources */, - 8370D1BD11FA6295009D650F /* AddSiteViewController.m in Sources */, 83FEFC7611FF6C5A0078B462 /* EditSiteViewController.m in Sources */, 838C672E1210C3C300B09CA3 /* Post.m in Sources */, 8383178812270E980047B476 /* PostMediaViewController.m in Sources */, @@ -5146,16 +5114,12 @@ E1D0D84716D3D2EA00E33F4C /* PocketActivity.m in Sources */, E15051CB16CA5DDB00D3DDDC /* Blog+Jetpack.m in Sources */, 85325A5917BC42E5008E87D1 /* NewPostTableViewCell.m in Sources */, - 8566BC95170F84BC003C6BCF /* CreateWPComAccountViewController.m in Sources */, - 85D805521715F4EA0075EEAC /* CreateWPComBlogViewController.m in Sources */, 85D8055D171631F10075EEAC /* SelectWPComLanguageViewController.m in Sources */, 8525398B171761D9003F6B32 /* WPComLanguages.m in Sources */, 85149741171E13DF00B87F3F /* WPAsyncBlockOperation.m in Sources */, - 85149747171E671000B87F3F /* SelectWPComBlogVisibilityViewController.m in Sources */, 858DE40F1730384F000AC628 /* LoginViewController.m in Sources */, 85C720B11730CEFA00460645 /* WPWalkthroughTextField.m in Sources */, 85E105861731A597001071A3 /* WPWalkthroughOverlayView.m in Sources */, - 85D08A5E17332C4A00E2BBCA /* NewAddUsersBlogViewController.m in Sources */, 85D08A7117342ECE00E2BBCA /* AddUsersBlogCell.m in Sources */, 85EC44D11738C24500686604 /* UIView+FormSheetHelpers.m in Sources */, 85EC44D41739826A00686604 /* CreateAccountAndBlogViewController.m in Sources */, From e01c5c7781e3563aa7a448d8066e9958d26b735f Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 22 Nov 2013 12:53:34 +0100 Subject: [PATCH 22/64] Store blog visibility --- WordPress/Classes/BlogListViewController.m | 1 + .../Classes/ReaderUsersBlogsViewController.m | 22 +++++++++---------- WordPress/Classes/WPAccount.h | 1 + WordPress/Classes/WPAccount.m | 6 +++++ .../WordPress 13.xcdatamodel/contents | 1 + 5 files changed, 20 insertions(+), 11 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index a6e5733e3b00..a2cbc980c338 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -279,6 +279,7 @@ - (NSFetchedResultsController *)resultsController { NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[WordPressAppDelegate sharedWordPressApplicationDelegate] managedObjectContext]; [fetchRequest setEntity:[NSEntityDescription entityForName:@"Blog" inManagedObjectContext:moc]]; + [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"isVisible = YES"]]; [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]]; // For some reasons, the cache sometimes gets corrupted diff --git a/WordPress/Classes/ReaderUsersBlogsViewController.m b/WordPress/Classes/ReaderUsersBlogsViewController.m index 2b8d110c21fb..9a94a3954d5d 100644 --- a/WordPress/Classes/ReaderUsersBlogsViewController.m +++ b/WordPress/Classes/ReaderUsersBlogsViewController.m @@ -10,6 +10,7 @@ #import "AddUsersBlogCell.h" #import "WordPressAppDelegate.h" #import "WPNUXUtility.h" +#import "WPAccount.h" @interface ReaderUsersBlogsViewController () @@ -17,7 +18,6 @@ @interface ReaderUsersBlogsViewController ())delegate { - (id)init { self = [super init]; if (self) { - self.blogs = [[NSUserDefaults standardUserDefaults] arrayForKey:@"wpcom_users_blogs"]; + self.blogs = [[WPAccount defaultWordPressComAccount] visibleBlogs]; self.primaryBlogId = [[NSUserDefaults standardUserDefaults] objectForKey:@"wpcom_users_prefered_blog_id"]; } return self; @@ -83,12 +83,11 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface #pragma mark - Instance Methods -- (NSString *)getCellTitleForIndexPath:(NSIndexPath *)indexPath { - NSDictionary *dict = [_blogs objectAtIndex:indexPath.row]; - if ([[[dict objectForKey:@"blogName"] trim] length] == 0) { - return [dict objectForKey:@"url"]; +- (NSString *)getCellTitleForBlog:(Blog *)blog { + if ([[blog.blogName trim] length] == 0) { + return blog.hostURL; } else { - return [dict objectForKey:@"blogName"]; + return blog.blogName; } } @@ -121,17 +120,18 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell.isWPCom = YES; } - NSDictionary *dict = [_blogs objectAtIndex:indexPath.row]; + Blog *blog = [_blogs objectAtIndex:indexPath.row]; cell.showTopSeparator = ( indexPath.row == 0 ) ? YES : NO; - cell.title = [self getCellTitleForIndexPath:indexPath]; - cell.blavatarUrl = [dict objectForKey:@"url"]; + cell.title = [self getCellTitleForBlog:blog]; + cell.blavatarUrl = [blog blavatarUrl]; return cell; } - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - return [AddUsersBlogCell rowHeightWithText:[self getCellTitleForIndexPath:indexPath]]; + Blog *blog = [_blogs objectAtIndex:indexPath.row]; + return [AddUsersBlogCell rowHeightWithText:[self getCellTitleForBlog:blog]]; } diff --git a/WordPress/Classes/WPAccount.h b/WordPress/Classes/WPAccount.h index 3b515f18e1df..674a49d97610 100644 --- a/WordPress/Classes/WPAccount.h +++ b/WordPress/Classes/WPAccount.h @@ -28,6 +28,7 @@ extern NSString * const WPAccountDefaultWordPressComAccountChangedNotification; @property (nonatomic, readonly) BOOL isWpcom; @property (nonatomic, retain) NSSet *blogs; @property (nonatomic, retain) NSSet *jetpackBlogs; +@property (nonatomic, readonly) NSArray *visibleBlogs; /** The account's password diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index cd59e6486c61..b31d92bbf9b1 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -223,6 +223,12 @@ - (void)setAuthToken:(NSString *)authToken { } } +- (NSArray *)visibleBlogs { + NSSet *visibleBlogs = [self.blogs filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"isVisible = YES"]]; + NSArray *sortedBlogs = [visibleBlogs sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]]; + return sortedBlogs; +} + #pragma mark - API Helpers - (WordPressComApi *)restApi diff --git a/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents b/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents index 70efdcb971bc..b38234c1b0b3 100644 --- a/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents +++ b/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents @@ -117,6 +117,7 @@ + From c2e223801c7a6805ae12d97aa9ce468c51352660 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 22 Nov 2013 16:56:04 +0100 Subject: [PATCH 23/64] Register for notifications after login --- WordPress/Classes/NotificationsManager.m | 3 +-- WordPress/Classes/WordPressAppDelegate.m | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index ec4507a54202..2d2eee1c5344 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -18,8 +18,7 @@ @implementation NotificationsManager + (void)registerForPushNotifications { - WordPressAppDelegate *appDelegate = [WordPressAppDelegate sharedWordPressApplicationDelegate]; - if (appDelegate.isWPcomAuthenticated) { + if ([WPAccount defaultWordPressComAccount]) { [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index 6cf830068ff8..7cfbea69815c 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -1098,6 +1098,7 @@ - (void)toggleExtraDebuggingIfNeeded { - (void)handleDefaultAccountChangedNotification:(NSNotification *)notification { [self toggleExtraDebuggingIfNeeded]; + [NotificationsManager registerForPushNotifications]; [self showWelcomeScreenIfNeededAnimated:NO]; } From 07acd4c49289fb6ad5419909f3ea1301cf8e9af8 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 22 Nov 2013 16:58:02 +0100 Subject: [PATCH 24/64] =?UTF-8?q?Rename=20visibility=20attribute=20to=20?= =?UTF-8?q?=E2=80=98visible=E2=80=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- WordPress/Classes/Blog.h | 3 ++- WordPress/Classes/Blog.m | 2 +- WordPress/Classes/WPAccount.m | 2 +- .../WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) diff --git a/WordPress/Classes/Blog.h b/WordPress/Classes/Blog.h index 3456090f626b..5ff0f3d738ba 100644 --- a/WordPress/Classes/Blog.h +++ b/WordPress/Classes/Blog.h @@ -32,8 +32,9 @@ @property (nonatomic, strong) NSDate *lastStatsSync; @property (nonatomic, strong) NSString *lastUpdateWarning; @property (nonatomic, assign) BOOL geolocationEnabled; +@property (nonatomic, assign) BOOL visible; @property (nonatomic, weak) NSNumber *isActivated; -@property (nonatomic, strong) NSDictionary *options; //we can store an NSArray or an NSDictionary as a transformable attribute... +@property (nonatomic, strong) NSDictionary *options; //we can store an NSArray or an NSDictionary as a transformable attribute... @property (nonatomic, strong) NSDictionary *postFormats; @property (nonatomic, strong) WPAccount *account; @property (nonatomic, strong) WPAccount *jetpackAccount; diff --git a/WordPress/Classes/Blog.m b/WordPress/Classes/Blog.m index b6ac8448fe1d..4dd3bc0daef0 100644 --- a/WordPress/Classes/Blog.m +++ b/WordPress/Classes/Blog.m @@ -45,7 +45,7 @@ @implementation Blog { @dynamic posts, categories, comments; @dynamic lastPostsSync, lastStatsSync, lastPagesSync, lastCommentsSync, lastUpdateWarning; @synthesize isSyncingPosts, isSyncingPages, isSyncingComments; -@dynamic geolocationEnabled, options, postFormats, isActivated; +@dynamic geolocationEnabled, options, postFormats, isActivated, visible; @dynamic account; @dynamic jetpackAccount; diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index b31d92bbf9b1..1a170966df61 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -224,7 +224,7 @@ - (void)setAuthToken:(NSString *)authToken { } - (NSArray *)visibleBlogs { - NSSet *visibleBlogs = [self.blogs filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"isVisible = YES"]]; + NSSet *visibleBlogs = [self.blogs filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"visible = YES"]]; NSArray *sortedBlogs = [visibleBlogs sortedArrayUsingDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]]; return sortedBlogs; } diff --git a/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents b/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents index b38234c1b0b3..ec6483e46d6d 100644 --- a/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents +++ b/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents @@ -117,7 +117,6 @@ - @@ -146,6 +145,7 @@ + From bf4b5b602183137b2339762655166f118e2b9d99 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 22 Nov 2013 16:58:21 +0100 Subject: [PATCH 25/64] Hide wp.com blogs instead of removing them --- WordPress/Classes/BlogListViewController.m | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 43169bb049f8..48e416c2ab8d 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -139,6 +139,10 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N } - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { + Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]]; + if (blog.isWPcom) { + return NSLocalizedString(@"Hide", nil); + } return NSLocalizedString(@"Remove", @"Button label when removing a blog"); } @@ -170,7 +174,12 @@ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEd [WPMobileStats trackEventForWPCom:StatsEventSettingsRemovedBlog]; Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]]; - [blog remove]; + if (blog.isWPcom) { + blog.visible = NO; + [blog dataSave]; + } else { + [blog remove]; + } // Count won't be updated yet; if this is the last site (count 1), exit editing mode if ([self numSites] == 1) { @@ -280,7 +289,7 @@ - (NSFetchedResultsController *)resultsController { NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; NSManagedObjectContext *moc = [[WordPressAppDelegate sharedWordPressApplicationDelegate] managedObjectContext]; [fetchRequest setEntity:[NSEntityDescription entityForName:@"Blog" inManagedObjectContext:moc]]; - [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"isVisible = YES"]]; + [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"visible = YES"]]; [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]]; // For some reasons, the cache sometimes gets corrupted From 88afc0fe4392bb016050e1244aa06bac436344db Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 22 Nov 2013 17:56:02 +0100 Subject: [PATCH 26/64] Added option to manage blogs from Settings Actual management screen not implemented yet, just the wp.com settings section logic --- WordPress/Classes/SettingsViewController.m | 56 +++--- WordPress/WordPress.xcodeproj/project.pbxproj | 4 + WordPress/WordPressTest/CoreDataTestHelper.m | 1 + .../SettingsViewControllerTest.m | 171 ++++++++++++++++++ 4 files changed, 211 insertions(+), 21 deletions(-) create mode 100644 WordPress/WordPressTest/SettingsViewControllerTest.m diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index ddac4113dad0..fbb6a6f6fbb4 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -68,17 +68,12 @@ - (void)viewDidLoad { self.doneButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Done", @"") style:[WPStyleGuide barButtonStyleForBordered] target:self action:@selector(dismiss)]; self.navigationItem.rightBarButtonItem = self.doneButton; - [[NSNotificationCenter defaultCenter] addObserverForName:WordPressComApiDidLoginNotification object:nil queue:nil usingBlock:^(NSNotification *note) { + [[NSNotificationCenter defaultCenter] addObserverForName:WPAccountDefaultWordPressComAccountChangedNotification object:nil queue:nil usingBlock:^(NSNotification *note) { NSMutableIndexSet *sections = [NSMutableIndexSet indexSet]; [sections addIndex:SettingsSectionWpcom]; [self.tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade]; }]; - [[NSNotificationCenter defaultCenter] addObserverForName:WordPressComApiDidLogoutNotification object:nil queue:nil usingBlock:^(NSNotification *note) { - NSMutableIndexSet *sections = [NSMutableIndexSet indexSet]; - [sections addIndex:SettingsSectionWpcom]; - [self.tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade]; - }]; - + [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; } @@ -155,6 +150,9 @@ - (BOOL)supportsNotifications { return nil != [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; } +- (BOOL)supportsManageBlogs { + return [[[WPAccount defaultWordPressComAccount] blogs] count] > 0; +} #pragma mark - Table view data source @@ -164,30 +162,35 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // The Sign Out row in Wpcom section can change, so identify it dynamically - (NSInteger)rowForSignOut { - return [self supportsNotifications] ? 2 : 1; + NSInteger rowForSignOut = 1; + if ([self supportsNotifications]) { + rowForSignOut += 1; + } + if ([self supportsManageBlogs]) { + rowForSignOut += 1; + } + return rowForSignOut; } - (NSInteger)rowForNotifications { - return [self supportsNotifications] ? 1 : -1; + if ([self supportsNotifications]) { + return [self supportsManageBlogs] ? 2 : 1; + } + return -1; +} + +- (NSInteger)rowForManageBlogs { + return [self supportsManageBlogs] ? 1 : -1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - int numWpcomRows = 0; - switch (section) { case SettingsSectionWpcom: - numWpcomRows = 1; - - // Show a Sign Out row? if ([WPAccount defaultWordPressComAccount]) { - // Allow notifications management? - if ([self supportsNotifications]) { - numWpcomRows += 1; - } - numWpcomRows += 1; + return [self rowForSignOut] + 1; + } else { + return 1; } - - return numWpcomRows; case SettingsSectionMedia: return [self.mediaSettingsArray count]; @@ -239,16 +242,24 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa cell.detailTextLabel.text = [[WPAccount defaultWordPressComAccount] username]; cell.detailTextLabel.textColor = [UIColor UIColorFromHex:0x888888]; cell.selectionStyle = UITableViewCellSelectionStyleNone; + cell.accessibilityIdentifier = @"wpcom-username"; + } else if (indexPath.row == [self rowForManageBlogs]) { + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + cell.textLabel.text = NSLocalizedString(@"Manage Blogs", @""); + cell.accessibilityIdentifier = @"wpcom-manage-blogs"; } else if (indexPath.row == [self rowForNotifications]) { cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; cell.textLabel.text = NSLocalizedString(@"Manage Notifications", @""); + cell.accessibilityIdentifier = @"wpcom-manage-notifications"; } else { cell.textLabel.textAlignment = NSTextAlignmentCenter; cell.textLabel.text = NSLocalizedString(@"Sign Out", @"Sign out from WordPress.com"); + cell.accessibilityIdentifier = @"wpcom-sign-out"; } } else { cell.textLabel.textAlignment = NSTextAlignmentCenter; cell.textLabel.text = NSLocalizedString(@"Sign In", @"Sign in to WordPress.com"); + cell.accessibilityIdentifier = @"wpcom-sign-in"; cell.selectionStyle = UITableViewCellSelectionStyleBlue; } @@ -369,6 +380,9 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath destructiveButtonTitle:NSLocalizedString(@"Sign Out", @"")otherButtonTitles:nil, nil ]; actionSheet.actionSheetStyle = UIActionSheetStyleDefault; [actionSheet showInView:self.view]; + } else if (indexPath.row == [self rowForManageBlogs]) { + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Not yet" message:@"Coming soon" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; + [alertView show]; } else if (indexPath.row == [self rowForNotifications]) { [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedManageNotifications]; diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index ef56d3223849..97f5b69910d9 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -779,6 +779,7 @@ CEBD3EAB0FF1BA3B00C1396E /* Blog.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBD3EAA0FF1BA3B00C1396E /* Blog.m */; }; E100C6BB1741473000AE48D8 /* WordPress-11-12.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = E100C6BA1741472F00AE48D8 /* WordPress-11-12.xcmappingmodel */; }; E10675CA183FA78E00E5CE5C /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E10675C9183FA78E00E5CE5C /* XCTest.framework */; }; + E10675C8183F82E900E5CE5C /* SettingsViewControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E10675C7183F82E900E5CE5C /* SettingsViewControllerTest.m */; }; E10A2E9B134E8AD3007643F9 /* PostAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 833AF25A114575A50016DE8F /* PostAnnotation.m */; }; E10B3652158F2D3F00419A93 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E10B3651158F2D3F00419A93 /* QuartzCore.framework */; }; E10B3654158F2D4500419A93 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E10B3653158F2D4500419A93 /* UIKit.framework */; }; @@ -1908,6 +1909,7 @@ E105E9CD1726955600C0D9E7 /* WPAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPAccount.h; sourceTree = ""; }; E105E9CE1726955600C0D9E7 /* WPAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPAccount.m; sourceTree = ""; }; E10675C9183FA78E00E5CE5C /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; + E10675C7183F82E900E5CE5C /* SettingsViewControllerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewControllerTest.m; sourceTree = ""; }; E10B3651158F2D3F00419A93 /* QuartzCore.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; E10B3653158F2D4500419A93 /* UIKit.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; E10DB0061771926D00B7A0A3 /* GooglePlusActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GooglePlusActivity.h; sourceTree = ""; }; @@ -3866,6 +3868,7 @@ E1239B7C176A2EE600D37220 /* AccountTest.m */, E18C1C4F176A3A880002F8AC /* AccountMigrationTest.m */, E1E4CE071773AB4200430844 /* WPTableImageSourceTest.m */, + E10675C7183F82E900E5CE5C /* SettingsViewControllerTest.m */, ); name = Tests; sourceTree = ""; @@ -5155,6 +5158,7 @@ E183ECA016B2164900C2EB11 /* EditPostViewControllerTest.m in Sources */, E150520C16CAC5C400D3DDDC /* BlogJetpackTest.m in Sources */, E150520F16CAC75A00D3DDDC /* CoreDataTestHelper.m in Sources */, + E10675C8183F82E900E5CE5C /* SettingsViewControllerTest.m in Sources */, E131CB5E16CAD659004B0314 /* AsyncTestHelper.m in Sources */, E15618FD16DB8677006532C4 /* UIKitTestHelper.m in Sources */, E18C1C50176A3A880002F8AC /* AccountMigrationTest.m in Sources */, diff --git a/WordPress/WordPressTest/CoreDataTestHelper.m b/WordPress/WordPressTest/CoreDataTestHelper.m index 2a1dbf0e46e6..791b27dbd332 100644 --- a/WordPress/WordPressTest/CoreDataTestHelper.m +++ b/WordPress/WordPressTest/CoreDataTestHelper.m @@ -149,6 +149,7 @@ - (NSPersistentStoreCoordinator *)persistentStoreCoordinator { _coordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]]; NSError *error; + [[NSFileManager defaultManager] removeItemAtURL:[self storeURL] error:nil]; NSPersistentStore *store = [_coordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:[self storeURL] options:nil error:&error]; NSAssert(store != nil, @"Can't initialize core data storage"); } diff --git a/WordPress/WordPressTest/SettingsViewControllerTest.m b/WordPress/WordPressTest/SettingsViewControllerTest.m new file mode 100644 index 000000000000..b66928c4ba88 --- /dev/null +++ b/WordPress/WordPressTest/SettingsViewControllerTest.m @@ -0,0 +1,171 @@ +// +// SettingsViewControllerTest.m +// WordPress +// +// Created by Jorge Bernal on 22/11/13. +// Copyright (c) 2013 WordPress. All rights reserved. +// + +#import +#import "CoreDataTestHelper.h" +#import "WPAccount.h" +#import "Blog.h" +#import "Constants.h" +#import "SettingsViewController.h" + +@interface SettingsViewControllerTest : XCTestCase + +@end + +@implementation SettingsViewControllerTest + +- (void)setUp +{ + [super setUp]; + // Put setup code here; it will be run once, before the first test case. + [[CoreDataTestHelper sharedHelper] registerDefaultContext]; +} + +- (void)tearDown +{ + // Put teardown code here; it will be run once, after the last test case. + [super tearDown]; + [[CoreDataTestHelper sharedHelper] reset]; +} + +- (void)testWpcomSection +{ + [WPAccount removeDefaultWordPressComAccount]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:kApnsDeviceTokenPrefKey]; + SettingsViewController *controller = [self settingsViewController]; + [self present:controller]; + + UITableView *table = controller.tableView; + UITableViewCell *cell = [self tableView:table cellForRow:0]; + + /* + Signed out + + - Sign In + */ + XCTAssertEqual(1, [table numberOfRowsInSection:0]); + XCTAssertEqualObjects(@"wpcom-sign-in", cell.accessibilityIdentifier); + + + // Sign In + WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:@"jacksparrow" password:@"piratesobrave" authToken:@"sevenseas"]; + [WPAccount setDefaultWordPressComAccount:account]; + + /* + Signed In, Notifications disabled, 1 blog + + - Username jacksparrow + - Sign Out + */ + XCTAssertEqual(2, [table numberOfRowsInSection:0]); + cell = [self tableView:table cellForRow:0]; + XCTAssertEqualObjects(@"wpcom-username", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:1]; + XCTAssertEqualObjects(@"wpcom-sign-out", cell.accessibilityIdentifier); + + [[NSUserDefaults standardUserDefaults] setObject:@"aFakeAPNSToken" forKey:kApnsDeviceTokenPrefKey]; + [table reloadData]; + + /* + Signed In, Notifications enabled, 0 blogs + + - Username jacksparrow + - Manage Notifications + - Sign Out + */ + XCTAssertEqual(3, [table numberOfRowsInSection:0]); + cell = [self tableView:table cellForRow:0]; + XCTAssertEqualObjects(@"wpcom-username", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:1]; + XCTAssertEqualObjects(@"wpcom-manage-notifications", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:2]; + XCTAssertEqualObjects(@"wpcom-sign-out", cell.accessibilityIdentifier); + + Blog *blog = [account findOrCreateBlogFromDictionary:@{@"url": @"blog1.com"} withContext:account.managedObjectContext]; + [blog dataSave]; + [table reloadData]; + + /* + Signed In, Notifications enabled, 1 blogs + + - Username jacksparrow + - Manage Blogs + - Manage Notifications + - Sign Out + */ + XCTAssertEqual(4, [table numberOfRowsInSection:0]); + cell = [self tableView:table cellForRow:0]; + XCTAssertEqualObjects(@"wpcom-username", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:1]; + XCTAssertEqualObjects(@"wpcom-manage-blogs", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:2]; + XCTAssertEqualObjects(@"wpcom-manage-notifications", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:3]; + XCTAssertEqualObjects(@"wpcom-sign-out", cell.accessibilityIdentifier); + + blog = [account findOrCreateBlogFromDictionary:@{@"url": @"blog2.com"} withContext:account.managedObjectContext]; + [blog dataSave]; + [table reloadData]; + + /* + Signed In, Notifications enabled, 2 blogs + + - Username jacksparrow + - Manage Blogs + - Manage Notifications + - Sign Out + */ + XCTAssertEqual(4, [table numberOfRowsInSection:0]); + cell = [self tableView:table cellForRow:0]; + XCTAssertEqualObjects(@"wpcom-username", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:1]; + XCTAssertEqualObjects(@"wpcom-manage-blogs", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:2]; + XCTAssertEqualObjects(@"wpcom-manage-notifications", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:3]; + XCTAssertEqualObjects(@"wpcom-sign-out", cell.accessibilityIdentifier); + + [[NSUserDefaults standardUserDefaults] removeObjectForKey:kApnsDeviceTokenPrefKey]; + [table reloadData]; + + /* + Signed In, Notifications disabled, 2 blogs + + - Username jacksparrow + - Manage Blogs + - Sign Out + */ + XCTAssertEqual(3, [table numberOfRowsInSection:0]); + cell = [self tableView:table cellForRow:0]; + XCTAssertEqualObjects(@"wpcom-username", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:1]; + XCTAssertEqualObjects(@"wpcom-manage-blogs", cell.accessibilityIdentifier); + cell = [self tableView:table cellForRow:2]; + XCTAssertEqualObjects(@"wpcom-sign-out", cell.accessibilityIdentifier); +} + +- (SettingsViewController *)settingsViewController { + SettingsViewController *controller = [SettingsViewController new]; + // Force view load + [controller view]; + return controller; +} + +- (void)present:(UIViewController *)controller { + [[[[[UIApplication sharedApplication] delegate] window] rootViewController] presentViewController:controller animated:NO completion:nil]; +} + +- (void)dismiss:(UIViewController *)controller { + [[[[[UIApplication sharedApplication] delegate] window] rootViewController] dismissViewControllerAnimated:NO completion:nil]; +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRow:(NSInteger)row { + return [tableView.dataSource tableView:tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:row inSection:0]]; +} + +@end From 9a83591c551ac026db86475b041d770c43a42a48 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 27 Nov 2013 13:30:18 +0100 Subject: [PATCH 27/64] Added manage blogs screen --- WordPress/Classes/ManageBlogsViewController.h | 17 +++ WordPress/Classes/ManageBlogsViewController.m | 133 ++++++++++++++++++ WordPress/Classes/SettingsViewController.m | 5 +- WordPress/Classes/WPAccount.m | 14 +- WordPress/WordPress.xcodeproj/project.pbxproj | 10 +- 5 files changed, 174 insertions(+), 5 deletions(-) create mode 100644 WordPress/Classes/ManageBlogsViewController.h create mode 100644 WordPress/Classes/ManageBlogsViewController.m diff --git a/WordPress/Classes/ManageBlogsViewController.h b/WordPress/Classes/ManageBlogsViewController.h new file mode 100644 index 000000000000..b5b9c90729ca --- /dev/null +++ b/WordPress/Classes/ManageBlogsViewController.h @@ -0,0 +1,17 @@ +// +// ManageBlogsViewController.h +// WordPress +// +// Created by Jorge Bernal on 27/11/13. +// Copyright (c) 2013 WordPress. All rights reserved. +// + +#import +#import "WPAccount.h" + +/** + An interface to manage which blogs are visible for a given account + */ +@interface ManageBlogsViewController : UITableViewController +- (id)initWithAccount:(WPAccount *)account; +@end diff --git a/WordPress/Classes/ManageBlogsViewController.m b/WordPress/Classes/ManageBlogsViewController.m new file mode 100644 index 000000000000..1ba9aecc0ccb --- /dev/null +++ b/WordPress/Classes/ManageBlogsViewController.m @@ -0,0 +1,133 @@ +// +// ManageBlogsViewController.m +// WordPress +// +// Created by Jorge Bernal on 27/11/13. +// Copyright (c) 2013 WordPress. All rights reserved. +// + +#import "ManageBlogsViewController.h" +#import "Blog.h" +#import "UIImageView+Gravatar.h" + +static NSString * const CellIdentifier = @"ManageBlogsCell"; + +@implementation ManageBlogsViewController { + NSArray *_blogs; + UIActivityIndicatorView *_activityIndicator; +} + +- (id)initWithAccount:(WPAccount *)account { + self = [super initWithStyle:UITableViewStyleGrouped]; + if (self) { + _account = account; + } + return self; +} + +- (void)viewDidLoad { + [super viewDidLoad]; + self.title = NSLocalizedString(@"Visible Blogs", nil); + [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; + + _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; + self.tableView.tableFooterView = _activityIndicator; + + [self buildToolbar]; + [self updateBlogs]; +} + +- (void)viewWillAppear:(BOOL)animated { + [super viewWillAppear:animated]; + + [self refreshBlogs]; +} + +- (void)buildToolbar { + UIBarButtonItem *showAll = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Show All", @"Show all blogs (Manage Blogs)") style:UIBarButtonItemStyleBordered target:self action:@selector(showAll:)]; + UIBarButtonItem *separator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; + UIBarButtonItem *hideAll = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Hide All", @"Hide all blogs (Manage Blogs)") style:UIBarButtonItemStyleBordered target:self action:@selector(hideAll:)]; + [self setToolbarItems:@[showAll, separator, hideAll]]; +} + +- (void)updateBlogs { + _blogs = [[_account.blogs allObjects] sortedArrayUsingSelector:@selector(blogName)]; + if ([_blogs count] > 2) { + [self.navigationController setToolbarHidden:NO animated:YES]; + } else { + [self.navigationController setToolbarHidden:YES animated:YES]; + } +} + +- (void)refreshBlogs { + [_activityIndicator startAnimating]; + [_account syncBlogsWithSuccess:^{ + [self updateBlogs]; + [self.tableView reloadData]; + [_activityIndicator stopAnimating]; + } failure:^(NSError *error) { + [_activityIndicator stopAnimating]; + }]; +} + +- (void)setAllBlogsVisible:(BOOL)visible { + [_blogs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { + Blog *blog = (Blog *)obj; + blog.visible = visible; + }]; + [_account.managedObjectContext save:nil]; + [self.tableView reloadData]; +} + +- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + return 1; +} + +- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { + return [_blogs count]; +} + +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + return NSLocalizedString(@"Visible Blogs", nil); +} + +- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; + Blog *blog = [_blogs objectAtIndex:indexPath.row]; + [cell.imageView setImageWithBlavatarUrl:blog.blavatarUrl isWPcom:YES]; + cell.textLabel.text = blog.blogName; + UISwitch *visibilitySwitch = [UISwitch new]; + visibilitySwitch.on = blog.visible; + visibilitySwitch.tag = indexPath.row; + [visibilitySwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; + cell.accessoryView = visibilitySwitch; + + return cell; +} + +- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { + UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; + UISwitch *switcher = (UISwitch *)cell.accessoryView; + if ([switcher isKindOfClass:[UISwitch class]]) { + [switcher setOn:!switcher.on animated:YES]; + [self switchChanged:switcher]; + } + [tableView deselectRowAtIndexPath:indexPath animated:YES]; +} + +- (void)switchChanged:(id)sender { + UISwitch *switcher = (UISwitch *)sender; + Blog *blog = [_blogs objectAtIndex:switcher.tag]; + blog.visible = switcher.on; + [blog dataSave]; +} + +- (void)showAll:(id)sender { + [self setAllBlogsVisible:YES]; +} + +- (void)hideAll:(id)sender { + [self setAllBlogsVisible:NO]; +} + +@end diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index fbb6a6f6fbb4..0c6ef68afc59 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -38,6 +38,7 @@ #import "SupportViewController.h" #import "WPAccount.h" #import "WPTableViewSectionHeaderView.h" +#import "ManageBlogsViewController.h" typedef enum { SettingsSectionWpcom = 0, @@ -381,8 +382,8 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath actionSheet.actionSheetStyle = UIActionSheetStyleDefault; [actionSheet showInView:self.view]; } else if (indexPath.row == [self rowForManageBlogs]) { - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Not yet" message:@"Coming soon" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; - [alertView show]; + ManageBlogsViewController *manageBlogsViewController = [[ManageBlogsViewController alloc] initWithAccount:[WPAccount defaultWordPressComAccount]]; + [self.navigationController pushViewController:manageBlogsViewController animated:YES]; } else if (indexPath.row == [self rowForNotifications]) { [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedManageNotifications]; diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index 1a170966df61..c1befa4bf90b 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -157,13 +157,21 @@ - (Blog *)findOrCreateBlogFromDictionary:(NSDictionary *)blogInfo withContext:(N blog.blogName = [[blogInfo objectForKey:@"blogName"] stringByDecodingXMLCharacters]; blog.xmlrpc = [blogInfo objectForKey:@"xmlrpc"]; + DDLogInfo(@"Created blog: %@", blog); + return blog; } - (void)syncBlogsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { + WPFLogMethod(); [self.xmlrpcApi getBlogsWithSuccess:^(NSArray *blogs) { [self mergeBlogs:blogs withCompletion:success]; - } failure:failure]; + } failure:^(NSError *error) { + DDLogError(@"Error syncing blogs: %@", error); + if (failure) { + failure(error); + } + }]; } - (void)mergeBlogs:(NSArray *)blogs withCompletion:(void (^)())completion { @@ -180,6 +188,10 @@ - (void)mergeBlogs:(NSArray *)blogs withCompletion:(void (^)())completion { if (![backgroundMOC save:&error]) { DDLogError(@"Unresolved core data save error: %@", error); } + NSManagedObjectContext *parentMOC = backgroundMOC.parentContext; + [parentMOC performBlockAndWait:^{ + [parentMOC save:nil]; + }]; dispatch_async(dispatch_get_main_queue(), completion); }]; diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 97f5b69910d9..c6bb0242cfe6 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -778,8 +778,8 @@ CCEF153114C9EA050001176D /* WPWebAppViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = CCEF153014C9EA050001176D /* WPWebAppViewController.m */; }; CEBD3EAB0FF1BA3B00C1396E /* Blog.m in Sources */ = {isa = PBXBuildFile; fileRef = CEBD3EAA0FF1BA3B00C1396E /* Blog.m */; }; E100C6BB1741473000AE48D8 /* WordPress-11-12.xcmappingmodel in Sources */ = {isa = PBXBuildFile; fileRef = E100C6BA1741472F00AE48D8 /* WordPress-11-12.xcmappingmodel */; }; - E10675CA183FA78E00E5CE5C /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E10675C9183FA78E00E5CE5C /* XCTest.framework */; }; E10675C8183F82E900E5CE5C /* SettingsViewControllerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E10675C7183F82E900E5CE5C /* SettingsViewControllerTest.m */; }; + E10675CA183FA78E00E5CE5C /* XCTest.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E10675C9183FA78E00E5CE5C /* XCTest.framework */; }; E10A2E9B134E8AD3007643F9 /* PostAnnotation.m in Sources */ = {isa = PBXBuildFile; fileRef = 833AF25A114575A50016DE8F /* PostAnnotation.m */; }; E10B3652158F2D3F00419A93 /* QuartzCore.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E10B3651158F2D3F00419A93 /* QuartzCore.framework */; }; E10B3654158F2D4500419A93 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E10B3653158F2D4500419A93 /* UIKit.framework */; }; @@ -915,6 +915,7 @@ E1D95EB817A28F5E00A3E9F3 /* WPActivityDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = E1D95EB717A28F5E00A3E9F3 /* WPActivityDefaults.m */; }; E1D95EBF17A2AB7400A3E9F3 /* video_play.png in Resources */ = {isa = PBXBuildFile; fileRef = E1D95EBD17A2AB7400A3E9F3 /* video_play.png */; }; E1D95EC017A2AB7400A3E9F3 /* video_play@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E1D95EBE17A2AB7400A3E9F3 /* video_play@2x.png */; }; + E1E38AF118460AF600A0F954 /* ManageBlogsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E1E38AF018460AF600A0F954 /* ManageBlogsViewController.m */; }; E1E4CE0417739E3300430844 /* WPImageSourceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E1E4CE0317739E3300430844 /* WPImageSourceTest.m */; }; E1E4CE0617739FAB00430844 /* test-image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = E1E4CE0517739FAB00430844 /* test-image.jpg */; }; E1E4CE081773AB4200430844 /* WPTableImageSourceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E1E4CE071773AB4200430844 /* WPTableImageSourceTest.m */; }; @@ -1908,8 +1909,8 @@ E100C6BA1741472F00AE48D8 /* WordPress-11-12.xcmappingmodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcmappingmodel; path = "WordPress-11-12.xcmappingmodel"; sourceTree = ""; }; E105E9CD1726955600C0D9E7 /* WPAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WPAccount.h; sourceTree = ""; }; E105E9CE1726955600C0D9E7 /* WPAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPAccount.m; sourceTree = ""; }; - E10675C9183FA78E00E5CE5C /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; E10675C7183F82E900E5CE5C /* SettingsViewControllerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = SettingsViewControllerTest.m; sourceTree = ""; }; + E10675C9183FA78E00E5CE5C /* XCTest.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = XCTest.framework; path = Library/Frameworks/XCTest.framework; sourceTree = DEVELOPER_DIR; }; E10B3651158F2D3F00419A93 /* QuartzCore.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = QuartzCore.framework; path = System/Library/Frameworks/QuartzCore.framework; sourceTree = SDKROOT; }; E10B3653158F2D4500419A93 /* UIKit.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; E10DB0061771926D00B7A0A3 /* GooglePlusActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GooglePlusActivity.h; sourceTree = ""; }; @@ -2095,6 +2096,8 @@ E1D95EB717A28F5E00A3E9F3 /* WPActivityDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPActivityDefaults.m; sourceTree = ""; }; E1D95EBD17A2AB7400A3E9F3 /* video_play.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = video_play.png; path = Resources/Images/video_play.png; sourceTree = ""; }; E1D95EBE17A2AB7400A3E9F3 /* video_play@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "video_play@2x.png"; path = "Resources/Images/video_play@2x.png"; sourceTree = ""; }; + E1E38AEF18460AF600A0F954 /* ManageBlogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ManageBlogsViewController.h; sourceTree = ""; }; + E1E38AF018460AF600A0F954 /* ManageBlogsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ManageBlogsViewController.m; sourceTree = ""; }; E1E4CE0317739E3300430844 /* WPImageSourceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPImageSourceTest.m; sourceTree = ""; }; E1E4CE0517739FAB00430844 /* test-image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "test-image.jpg"; sourceTree = ""; }; E1E4CE071773AB4200430844 /* WPTableImageSourceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPTableImageSourceTest.m; sourceTree = ""; }; @@ -3274,6 +3277,8 @@ 83FEFC7411FF6C5A0078B462 /* EditSiteViewController.m */, 85D8055B171631F10075EEAC /* SelectWPComLanguageViewController.h */, 85D8055C171631F10075EEAC /* SelectWPComLanguageViewController.m */, + E1E38AEF18460AF600A0F954 /* ManageBlogsViewController.h */, + E1E38AF018460AF600A0F954 /* ManageBlogsViewController.m */, ); name = Blog; sourceTree = ""; @@ -5040,6 +5045,7 @@ E12F95B9155820A40067A653 /* NSObject+BlockObservation.m in Sources */, A25EBD87156E330600530E3D /* WPTableViewController.m in Sources */, 5DEB61B4156FCD3400242C35 /* WPWebView.m in Sources */, + E1E38AF118460AF600A0F954 /* ManageBlogsViewController.m in Sources */, 5DEB61B8156FCD5200242C35 /* WPChromelessWebViewController.m in Sources */, CC24E5EF1577D1EA00A6D5B5 /* WPFriendFinderViewController.m in Sources */, E1AB07AD1578D34300D6AD64 /* SettingsViewController.m in Sources */, From 148cab346694c732ec5f8a8a2c47b845ce955f2a Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 27 Nov 2013 13:34:02 +0100 Subject: [PATCH 28/64] Added missing variable --- WordPress/Classes/ManageBlogsViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPress/Classes/ManageBlogsViewController.m b/WordPress/Classes/ManageBlogsViewController.m index 1ba9aecc0ccb..de128f96fefe 100644 --- a/WordPress/Classes/ManageBlogsViewController.m +++ b/WordPress/Classes/ManageBlogsViewController.m @@ -13,6 +13,7 @@ static NSString * const CellIdentifier = @"ManageBlogsCell"; @implementation ManageBlogsViewController { + WPAccount *_account; NSArray *_blogs; UIActivityIndicatorView *_activityIndicator; } From 6c4bd1c71bdd29de1b042f0b3bfabb6c37e9757f Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 27 Nov 2013 13:35:16 +0100 Subject: [PATCH 29/64] Hide toolbar when leaving manage blogs --- WordPress/Classes/ManageBlogsViewController.m | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/WordPress/Classes/ManageBlogsViewController.m b/WordPress/Classes/ManageBlogsViewController.m index de128f96fefe..f9a9c6ba8206 100644 --- a/WordPress/Classes/ManageBlogsViewController.m +++ b/WordPress/Classes/ManageBlogsViewController.m @@ -44,6 +44,12 @@ - (void)viewWillAppear:(BOOL)animated { [self refreshBlogs]; } +- (void)viewWillDisappear:(BOOL)animated { + [super viewWillDisappear:animated]; + + [self.navigationController setToolbarHidden:YES animated:animated]; +} + - (void)buildToolbar { UIBarButtonItem *showAll = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Show All", @"Show all blogs (Manage Blogs)") style:UIBarButtonItemStyleBordered target:self action:@selector(showAll:)]; UIBarButtonItem *separator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; From 5cb064086a897409d0762f8a2d917891197e05f6 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 27 Nov 2013 13:47:01 +0100 Subject: [PATCH 30/64] Tell users about Manage Blogs when hiding a blog The first time the hide feature is used, let users know how to "undo" it Screens: https://cloudup.com/cxPDiufUsF1 --- WordPress/Classes/BlogListViewController.m | 18 ++++++++++++++++++ WordPress/Classes/ManageBlogsViewController.h | 2 ++ WordPress/Classes/ManageBlogsViewController.m | 8 ++++++++ 3 files changed, 28 insertions(+) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 48e416c2ab8d..ae1d5a172ee3 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -17,6 +17,7 @@ #import "Blog.h" #import "WPAccount.h" #import "FakePushTransitionAnimator.h" +#import "ManageBlogsViewController.h" CGFloat const blavatarImageSize = 50.f; @@ -90,6 +91,22 @@ - (NSUInteger)numSites { return [[self.resultsController fetchedObjects] count]; } +- (void)showManageBlogsHintIfNeeded { + NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; + + if ([defaults objectForKey:HasSeenManageBlogsHintDefaultsKey]) { + return; + } + + UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Hidden Blogs", nil) + message:NSLocalizedString(@"If you want to see this or other hidden blogs in the app, you can do it from Settings > Manage Blogs", nil) + delegate:nil + cancelButtonTitle:NSLocalizedString(@"OK", nil) + otherButtonTitles:nil]; + [alertView show]; + [defaults setBool:YES forKey:HasSeenManageBlogsHintDefaultsKey]; + [defaults synchronize]; +} #pragma mark - Actions @@ -177,6 +194,7 @@ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEd if (blog.isWPcom) { blog.visible = NO; [blog dataSave]; + [self showManageBlogsHintIfNeeded]; } else { [blog remove]; } diff --git a/WordPress/Classes/ManageBlogsViewController.h b/WordPress/Classes/ManageBlogsViewController.h index b5b9c90729ca..963c14a128ad 100644 --- a/WordPress/Classes/ManageBlogsViewController.h +++ b/WordPress/Classes/ManageBlogsViewController.h @@ -9,6 +9,8 @@ #import #import "WPAccount.h" +extern NSString * const HasSeenManageBlogsHintDefaultsKey; + /** An interface to manage which blogs are visible for a given account */ diff --git a/WordPress/Classes/ManageBlogsViewController.m b/WordPress/Classes/ManageBlogsViewController.m index f9a9c6ba8206..c60936b780c9 100644 --- a/WordPress/Classes/ManageBlogsViewController.m +++ b/WordPress/Classes/ManageBlogsViewController.m @@ -10,6 +10,7 @@ #import "Blog.h" #import "UIImageView+Gravatar.h" +NSString * const HasSeenManageBlogsHintDefaultsKey = @"HasSeenManageBlogsHint"; static NSString * const CellIdentifier = @"ManageBlogsCell"; @implementation ManageBlogsViewController { @@ -44,6 +45,13 @@ - (void)viewWillAppear:(BOOL)animated { [self refreshBlogs]; } +- (void)viewDidAppear:(BOOL)animated { + [super viewDidAppear:animated]; + + [[NSUserDefaults standardUserDefaults] setBool:YES forKey:HasSeenManageBlogsHintDefaultsKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; +} + - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; From 9e9f547ded65356ab0e6b8a3b75fe4ee35a7ea42 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 27 Nov 2013 19:52:48 +0100 Subject: [PATCH 31/64] Blog list tweaks - Removed edit button - Don't allow hiding wp.com blogs from the list - Separate wp.com and self hosted in sections --- WordPress/Classes/BlogListViewController.m | 156 +++++++++--------- WordPress/Classes/ManageBlogsViewController.h | 2 - WordPress/Classes/ManageBlogsViewController.m | 8 - 3 files changed, 78 insertions(+), 88 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 24f8e0c7b85a..170fb035cd08 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -42,7 +42,6 @@ - (id)initWithStyle:(UITableViewStyle)style - (void)viewDidLoad { [super viewDidLoad]; - self.navigationItem.leftBarButtonItem = self.editButtonItem; self.settingsButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Settings", nil) style:UIBarButtonItemStylePlain target:self @@ -79,8 +78,6 @@ - (void)viewWillAppear:(BOOL)animated { self.resultsController.delegate = self; [self.resultsController performFetch:nil]; [self.tableView reloadData]; - - self.editButtonItem.enabled = ([self numSites] > 0); } - (void)viewWillDisappear:(BOOL)animated { @@ -92,21 +89,8 @@ - (NSUInteger)numSites { return [[self.resultsController fetchedObjects] count]; } -- (void)showManageBlogsHintIfNeeded { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - if ([defaults objectForKey:HasSeenManageBlogsHintDefaultsKey]) { - return; - } - - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Hidden Blogs", nil) - message:NSLocalizedString(@"If you want to see this or other hidden blogs in the app, you can do it from Settings > Manage Blogs", nil) - delegate:nil - cancelButtonTitle:NSLocalizedString(@"OK", nil) - otherButtonTitles:nil]; - [alertView show]; - [defaults setBool:YES forKey:HasSeenManageBlogsHintDefaultsKey]; - [defaults synchronize]; +- (BOOL)hasDotComAndSelfHosted { + return ([[self.resultsController sections] count] > 1); } #pragma mark - Actions @@ -129,17 +113,15 @@ - (void)showSettings:(id)sender { #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; + return [self.resultsController.sections count] + 1; } - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - NSInteger numRows = [self numSites]; - - // Plus an extra row for 'Add a Site' (when not editing) - if (![tableView isEditing]) - numRows += 1; - - return numRows; + if (section == [self sectionForAddSite]) { + return 1; + } + id sectionInfo = [[self.resultsController sections] objectAtIndex:section]; + return sectionInfo.numberOfObjects; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath @@ -156,46 +138,45 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N return cell; } -- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { - Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]]; - if (blog.isWPcom) { - return NSLocalizedString(@"Hide", nil); +- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { + if (![self hasDotComAndSelfHosted]) { + return nil; } + + if (section < [self sectionForAddSite]) { + return [[self.resultsController sectionIndexTitles] objectAtIndex:section]; + } + + return nil; +} + +- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { return NSLocalizedString(@"Remove", @"Button label when removing a blog"); } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - return indexPath.row != [self rowForAddSite]; -} + if (indexPath.section == [self sectionForAddSite]) { + return NO; + } -- (void)setEditing:(BOOL)editing animated:(BOOL)animated { - [super setEditing:editing animated:animated]; - - // And the "Add a Site" row too - NSArray *rowsToChange = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:[self rowForAddSite] inSection:0]]; - - UITableViewRowAnimation rowAnimation = animated ? UITableViewRowAnimationFade : UITableViewRowAnimationNone; - [self.tableView beginUpdates]; - if (editing) { - [self.tableView deleteRowsAtIndexPaths:rowsToChange withRowAnimation:rowAnimation]; - [self.navigationItem setRightBarButtonItem:nil animated:animated]; - } else { - [self.tableView insertRowsAtIndexPaths:rowsToChange withRowAnimation:rowAnimation]; - [self.navigationItem setRightBarButtonItem:self.settingsButton animated:animated]; + + id sectionInfo = [[self.resultsController sections] objectAtIndex:indexPath.section]; + if ([[sectionInfo name] isEqualToString:@"0"]) { + return YES; } - [self.tableView endUpdates]; -} + return NO; +} - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { [WPMobileStats trackEventForWPCom:StatsEventSettingsRemovedBlog]; - Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]]; + Blog *blog = [self.resultsController objectAtIndexPath:indexPath]; if (blog.isWPcom) { + DDLogWarn(@"Tried to remove a WordPress.com blog. This shouldn't happen but just in case, let's hide it"); blog.visible = NO; [blog dataSave]; - [self showManageBlogsHintIfNeeded]; } else { [blog remove]; } @@ -217,8 +198,8 @@ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEd } } -- (NSInteger)rowForAddSite { - return [self numSites]; +- (NSInteger)sectionForAddSite { + return [self.resultsController.sections count]; } - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { @@ -226,49 +207,46 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa cell.accessoryType = UITableViewCellAccessoryNone; cell.accessoryView = nil; - if (indexPath.row < [self rowForAddSite]) { - Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]]; - if ([blog.blogName length] != 0) { - cell.textLabel.text = blog.blogName; - } else { - cell.textLabel.text = blog.url; - } - - [cell.imageView setImageWithBlavatarUrl:blog.blavatarUrl isWPcom:blog.isWPcom]; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - -// if (indexPath.row == 0) { -// [self maskImageView:cell.imageView corner:UIRectCornerTopLeft]; -// } else if (indexPath.row == ([self.tableView numberOfRowsInSection:indexPath.section] -1)) { -// [self maskImageView:cell.imageView corner:UIRectCornerBottomLeft]; -// } else { -// cell.imageView.layer.mask = NULL; -// } - } else { + if (indexPath.section == [self sectionForAddSite]) { cell.textLabel.text = NSLocalizedString(@"Add a Site", @""); cell.selectionStyle = UITableViewCellSelectionStyleBlue; cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - + // To align the label, create and add a blank image UIGraphicsBeginImageContextWithOptions(CGSizeMake(blavatarImageSize, blavatarImageSize), NO, 0.0); UIImage *blank = UIGraphicsGetImageFromCurrentImageContext(); UIGraphicsEndImageContext(); [cell.imageView setImage:blank]; + } else { + + Blog *blog = [self.resultsController objectAtIndexPath:indexPath]; + if ([blog.blogName length] != 0) { + cell.textLabel.text = blog.blogName; + } else { + cell.textLabel.text = blog.url; + } + + [cell.imageView setImageWithBlavatarUrl:blog.blavatarUrl isWPcom:blog.isWPcom]; + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; } } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { // No top margin on iPhone - if (IS_IPHONE) - return 1; - - return 40; + if (section == [self sectionForAddSite]) { + return 20.0; + } + if (IS_IPHONE && section == 0) { + return 36.0; + } + + return 40.0; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { [tableView deselectRowAtIndexPath:indexPath animated:YES]; - if (indexPath.row < [self rowForAddSite]) { + if (indexPath.section < [self sectionForAddSite]) { [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedEditBlog]; Blog *blog = [self.resultsController objectAtIndexPath:indexPath]; @@ -316,7 +294,7 @@ - (NSFetchedResultsController *)resultsController { _resultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc - sectionNameKeyPath:nil + sectionNameKeyPath:@"isWPcom" cacheName:nil]; _resultsController.delegate = self; @@ -370,6 +348,28 @@ - (void)controller:(NSFetchedResultsController *)controller } } +- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type { + switch (type) { + case NSFetchedResultsChangeInsert: + [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; + break; + + case NSFetchedResultsChangeDelete: + [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; + break; + + default: + break; + } +} + +- (NSString *)controller:(NSFetchedResultsController *)controller sectionIndexTitleForSectionName:(NSString *)sectionName { + if ([sectionName isEqualToString:@"1"]) { + return [NSString stringWithFormat:NSLocalizedString(@"%@'s blogs", @"Section header for WordPress.com blogs"), [[WPAccount defaultWordPressComAccount] username]]; + } + return NSLocalizedString(@"Self Hosted", @"Section header for self hosted blogs"); +} + #pragma mark - UIViewControllerTransitioningDelegate - (id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { diff --git a/WordPress/Classes/ManageBlogsViewController.h b/WordPress/Classes/ManageBlogsViewController.h index 963c14a128ad..b5b9c90729ca 100644 --- a/WordPress/Classes/ManageBlogsViewController.h +++ b/WordPress/Classes/ManageBlogsViewController.h @@ -9,8 +9,6 @@ #import #import "WPAccount.h" -extern NSString * const HasSeenManageBlogsHintDefaultsKey; - /** An interface to manage which blogs are visible for a given account */ diff --git a/WordPress/Classes/ManageBlogsViewController.m b/WordPress/Classes/ManageBlogsViewController.m index c60936b780c9..f9a9c6ba8206 100644 --- a/WordPress/Classes/ManageBlogsViewController.m +++ b/WordPress/Classes/ManageBlogsViewController.m @@ -10,7 +10,6 @@ #import "Blog.h" #import "UIImageView+Gravatar.h" -NSString * const HasSeenManageBlogsHintDefaultsKey = @"HasSeenManageBlogsHint"; static NSString * const CellIdentifier = @"ManageBlogsCell"; @implementation ManageBlogsViewController { @@ -45,13 +44,6 @@ - (void)viewWillAppear:(BOOL)animated { [self refreshBlogs]; } -- (void)viewDidAppear:(BOOL)animated { - [super viewDidAppear:animated]; - - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:HasSeenManageBlogsHintDefaultsKey]; - [[NSUserDefaults standardUserDefaults] synchronize]; -} - - (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; From 620e01966fbf733b093f7d2a03539bf3a6502a27 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 27 Nov 2013 19:53:58 +0100 Subject: [PATCH 32/64] Only show manage blogs if there are multiple --- WordPress/Classes/SettingsViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index 06d69136b0c7..f62788aff721 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -154,7 +154,7 @@ - (BOOL)supportsNotifications { } - (BOOL)supportsManageBlogs { - return [[[WPAccount defaultWordPressComAccount] blogs] count] > 0; + return [[[WPAccount defaultWordPressComAccount] blogs] count] > 1; } #pragma mark - Table view data source From 2f9cc324e05191cc17de36ad79185ad97a5f66f8 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 27 Nov 2013 20:14:48 +0100 Subject: [PATCH 33/64] Reload section header when it changes --- WordPress/Classes/BlogListViewController.m | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 170fb035cd08..e73962e53eb1 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -312,6 +312,19 @@ - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView endUpdates]; + + /* + This covers the corner case when the only self hosted blog is removed and + there's a WordPress.com account. + + Since we only show the section title if there are multiple blog sections, + the section header wouldn't change when the section count changed, and it + would still display the wordpress.com header. + + It's not a big deal but it wouldn't be consistent with future appearances + of the same view. + */ + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; } - (void)controller:(NSFetchedResultsController *)controller From ef02aed29a3c37c6e0e4737c7d4bc99f1adf1d43 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 27 Nov 2013 20:18:09 +0100 Subject: [PATCH 34/64] Cleaned merge oopsies --- WordPress/Classes/Blog+Jetpack.m.orig | 161 --- WordPress/Classes/Blog.m.orig | 794 ------------- .../Classes/BlogListViewController.m.orig | 393 ------- .../CreateAccountAndBlogViewController.m.orig | 757 ------------ .../Classes/SettingsViewController.m.orig | 455 -------- .../Classes/WPcomLoginViewController.m.orig | 379 ------ WordPress/Classes/WordPressAppDelegate.m.orig | 1020 ----------------- WordPress/WordPressApi/WordPressComApi.m.orig | 888 -------------- 8 files changed, 4847 deletions(-) delete mode 100644 WordPress/Classes/Blog+Jetpack.m.orig delete mode 100644 WordPress/Classes/Blog.m.orig delete mode 100644 WordPress/Classes/BlogListViewController.m.orig delete mode 100644 WordPress/Classes/CreateAccountAndBlogViewController.m.orig delete mode 100644 WordPress/Classes/SettingsViewController.m.orig delete mode 100644 WordPress/Classes/WPcomLoginViewController.m.orig delete mode 100644 WordPress/Classes/WordPressAppDelegate.m.orig delete mode 100644 WordPress/WordPressApi/WordPressComApi.m.orig diff --git a/WordPress/Classes/Blog+Jetpack.m.orig b/WordPress/Classes/Blog+Jetpack.m.orig deleted file mode 100644 index e1d297ddf3d8..000000000000 --- a/WordPress/Classes/Blog+Jetpack.m.orig +++ /dev/null @@ -1,161 +0,0 @@ -// -// Blog+Jetpack.m -// WordPress -// -// Created by Jorge Bernal on 2/12/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import - -#import "Blog+Jetpack.h" -#import "WPAccount.h" -#import "WordPressAppDelegate.h" -#import "ContextManager.h" - -NSString * const BlogJetpackErrorDomain = @"BlogJetpackError"; -NSString * const BlogJetpackApiBaseUrl = @"https://public-api.wordpress.com/"; -NSString * const BlogJetpackApiPath = @"get-user-blogs/1.0"; - -// AFJSONRequestOperation requires that a URI end with .json in order to match -// This will make any request to be processed as JSON -@interface BlogJetpackJSONRequestOperation : AFJSONRequestOperation -@end -@implementation BlogJetpackJSONRequestOperation -+(BOOL)canProcessRequest:(NSURLRequest *)urlRequest { - return YES; -} -@end - - -@implementation Blog (Jetpack) - -- (BOOL)hasJetpack { - NSAssert(![self isWPcom], @"Blog+Jetpack doesn't support WordPress.com blogs"); - - return (nil != [self jetpackVersion]); -} - -- (NSString *)jetpackVersion { - NSAssert(![self isWPcom], @"Blog+Jetpack doesn't support WordPress.com blogs"); - - return [self.options stringForKeyPath:@"jetpack_version.value"]; -} - -- (NSNumber *)jetpackBlogID { - NSAssert(![self isWPcom], @"Blog+Jetpack doesn't support WordPress.com blogs"); - - return [self.options numberForKeyPath:@"jetpack_client_id.value"]; -} - -- (NSString *)jetpackUsername { - NSAssert(![self isWPcom], @"Blog+Jetpack doesn't support WordPress.com blogs"); - - return self.jetpackAccount.username; -} - -- (NSString *)jetpackPassword { - NSAssert(![self isWPcom], @"Blog+Jetpack doesn't support WordPress.com blogs"); - - return self.jetpackAccount.password; -} - -- (void)validateJetpackUsername:(NSString *)username password:(NSString *)password success:(void (^)())success failure:(void (^)(NSError *))failure { - NSAssert(![self isWPcom], @"Can't validate credentials for a WordPress.com blog"); - NSAssert(username != nil, @"Can't validate with a nil username"); - NSAssert(password != nil, @"Can't validate with a nil password"); - - if ([self isWPcom]) { - if (failure) { - NSError *error = [NSError errorWithDomain:BlogJetpackErrorDomain code:BlogJetpackErrorCodeInvalidBlog userInfo:@{NSLocalizedDescriptionKey: NSLocalizedString(@"Can't validate credentials for a WordPress.com blog", @"")}]; - failure(error); - return; - } - } - - AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:BlogJetpackApiBaseUrl]]; - [client registerHTTPOperationClass:[BlogJetpackJSONRequestOperation class]]; - [client setDefaultHeader:@"User-Agent" value:[[WordPressAppDelegate sharedWordPressApplicationDelegate] applicationUserAgent]]; - [client setAuthorizationHeaderWithUsername:username password:password]; - [client getPath:BlogJetpackApiPath - parameters:@{@"f": @"json"} - success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSArray *blogs = [responseObject arrayForKeyPath:@"userinfo.blog"]; - NSNumber *searchID = [self jetpackBlogID]; - NSString *searchURL = self.url; - DDLogInfo(@"Available wp.com/jetpack blogs for %@: %@", username, blogs); - NSArray *foundBlogs = [blogs filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) { - BOOL valid = NO; - if (searchID && [[evaluatedObject numberForKey:@"id"] isEqualToNumber:searchID]) { - valid = YES; - } else if ([[evaluatedObject stringForKey:@"url"] isEqualToString:searchURL]) { - valid = YES; - } - if (valid) { - DDLogInfo(@"Found blog: %@", evaluatedObject); - [self saveJetpackUsername:username andPassword:password]; - } - return valid; - }]]; - if (foundBlogs && [foundBlogs count] > 0) { - - if (success) success(); - } else { - NSError *error = [NSError errorWithDomain:BlogJetpackErrorDomain - code:BlogJetpackErrorCodeNoRecordForBlog - userInfo:@{NSLocalizedDescriptionKey: NSLocalizedString(@"This blog is not connected to that WordPress.com username", @"")}]; - if (failure) failure(error); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) { - NSError *jetpackError = error; - if (operation.response.statusCode == 401) { - jetpackError = [NSError errorWithDomain:BlogJetpackErrorDomain - code:BlogJetpackErrorCodeInvalidCredentials - userInfo:@{NSLocalizedDescriptionKey: NSLocalizedString(@"Invalid username or password", @""), NSUnderlyingErrorKey: error}]; - - } - failure(jetpackError); - } - }]; -} - -- (void)removeJetpackCredentials { - NSAssert(![self isWPcom], @"Blog+Jetpack doesn't support WordPress.com blogs"); - - self.account = nil; -} - -#pragma mark - Private methods - -- (void)saveJetpackUsername:(NSString *)username andPassword:(NSString *)password { - NSAssert(![self isWPcom], @"Blog+Jetpack doesn't support WordPress.com blogs"); -<<<<<<< HEAD - WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:nil]; -======= - WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username andPassword:password withContext:self.managedObjectContext]; ->>>>>>> refs/heads/develop - self.jetpackAccount = account; -} - -/* - Replacement method for `-[Blog remove]` - - @warning Don't call this directly - */ -- (void)removeWithoutJetpack { - if (![self isWPcom]) { - [self removeJetpackCredentials]; - } - - // Since we exchanged implementations, this actually calls `-[Blog remove]` - [self removeWithoutJetpack]; -} - -+ (void)load { - Method originalRemove = class_getInstanceMethod(self, @selector(remove)); - Method customRemove = class_getInstanceMethod(self, @selector(removeWithoutJetpack)); - method_exchangeImplementations(originalRemove, customRemove); -} - -@end diff --git a/WordPress/Classes/Blog.m.orig b/WordPress/Classes/Blog.m.orig deleted file mode 100644 index 76c912fbaa0d..000000000000 --- a/WordPress/Classes/Blog.m.orig +++ /dev/null @@ -1,794 +0,0 @@ -// -// Blog.m -// WordPress -// -// Created by Gareth Townsend on 24/06/09. -// - -#import "Blog.h" -#import "Post.h" -#import "Page.h" -#import "Category.h" -#import "Comment.h" -#import "WPAccount.h" -#import "UIImage+Resize.h" -#import "NSURL+IDN.h" -#import "NSString+XMLExtensions.h" -#import "WPError.h" -#import "ContextManager.h" - -@interface Blog (PrivateMethods) - -@property (readwrite, assign) BOOL reachable; - -@end - - -@implementation Blog { - WPXMLRPCClient *_api; - NSString *_blavatarUrl; - Reachability *_reachability; - BOOL _isReachable; -} - -@dynamic blogID, blogName, url, xmlrpc, apiKey; -@dynamic hasOlderPosts, hasOlderPages; -@dynamic posts, categories, comments; -@dynamic lastPostsSync, lastStatsSync, lastPagesSync, lastCommentsSync, lastUpdateWarning; -@synthesize isSyncingPosts, isSyncingPages, isSyncingComments; -@dynamic geolocationEnabled, options, postFormats, isActivated, visible; -@dynamic account; -@dynamic jetpackAccount; - -#pragma mark - -#pragma mark Dealloc - -- (void)dealloc { - _blavatarUrl = nil; - _api = nil; - [_reachability stopNotifier]; - _reachability = nil; - - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - - -- (BOOL)geolocationEnabled -{ - BOOL tmpValue; - - [self willAccessValueForKey:@"geolocationEnabled"]; - tmpValue = [[self primitiveValueForKey:@"geolocationEnabled"] boolValue]; - [self didAccessValueForKey:@"geolocationEnabled"]; - - return tmpValue; -} - -- (void)setGeolocationEnabled:(BOOL)value -{ - [self willChangeValueForKey:@"geolocationEnabled"]; - [self setPrimitiveValue:[NSNumber numberWithBool:value] forKey:@"geolocationEnabled"]; - [self didChangeValueForKey:@"geolocationEnabled"]; -} - -#pragma mark - -#pragma mark Custom methods - -+ (NSInteger)countWithContext:(NSManagedObjectContext *)moc { - NSFetchRequest *request = [[NSFetchRequest alloc] init]; - [request setEntity:[NSEntityDescription entityForName:@"Blog" inManagedObjectContext:moc]]; - [request setIncludesSubentities:NO]; - - NSError *err; - NSUInteger count = [moc countForFetchRequest:request error:&err]; - if(count == NSNotFound) { - count = 0; - } - return count; -} - -- (NSString *)blavatarUrl { - if (_blavatarUrl == nil) { - NSString *hostUrl = [[NSURL URLWithString:self.xmlrpc] host]; - if (hostUrl == nil) { - hostUrl = self.xmlrpc; - } - - _blavatarUrl = hostUrl; - } - - return _blavatarUrl; -} - -// used as a key to store passwords, if you change the algorithm, logins will break -- (NSString *)displayURL { - NSString *url = [NSURL IDNDecodedHostname:self.url]; - NSAssert(url != nil, @"Decoded url shouldn't be nil"); - if (url == nil) { - DDLogInfo(@"displayURL: decoded url is nil: %@", self.url); - return self.url; - } - NSError *error = nil; - NSRegularExpression *protocol = [NSRegularExpression regularExpressionWithPattern:@"http(s?)://" options:NSRegularExpressionCaseInsensitive error:&error]; - NSString *result = [NSString stringWithFormat:@"%@", [protocol stringByReplacingMatchesInString:url options:0 range:NSMakeRange(0, [url length]) withTemplate:@""]]; - - if([result hasSuffix:@"/"]) - result = [result substringToIndex:[result length] - 1]; - - return result; -} - -- (NSString *)hostURL { - return [self displayURL]; -} - -- (NSString *)homeURL -{ - NSString *homeURL = [self getOptionValue:@"home_url"]; - if (!homeURL) { - homeURL = self.url; - } - return homeURL; -} - -- (NSString *)hostname { - NSString *hostname = [[NSURL URLWithString:self.xmlrpc] host]; - if (hostname == nil) { - NSError *error = nil; - NSRegularExpression *protocol = [NSRegularExpression regularExpressionWithPattern:@"^.*://" options:NSRegularExpressionCaseInsensitive error:&error]; - hostname = [protocol stringByReplacingMatchesInString:self.url options:0 range:NSMakeRange(0, [self.url length]) withTemplate:@""]; - } - - // NSURL seems to not recongnize some TLDs like .me and .it, which results in hostname returning a full path. - // This can break reachibility (among other things) for the blog. - // As a saftey net, make sure we drop any path component before returning the hostname. - NSArray *parts = [hostname componentsSeparatedByString:@"/"]; - if([parts count] > 0) { - hostname = [parts objectAtIndex:0]; - } - - return hostname; -} - -- (NSString *)loginUrl { - NSString *loginUrl = [self getOptionValue:@"login_url"]; - if (!loginUrl) { - loginUrl = [self urlWithPath:@"wp-login.php"]; - } - return loginUrl; -} - -- (NSString *)urlWithPath:(NSString *)path { - NSError *error = nil; - NSRegularExpression *xmlrpc = [NSRegularExpression regularExpressionWithPattern:@"xmlrpc.php$" options:NSRegularExpressionCaseInsensitive error:&error]; - return [xmlrpc stringByReplacingMatchesInString:self.xmlrpc options:0 range:NSMakeRange(0, [self.xmlrpc length]) withTemplate:path]; -} - -- (NSString *)adminUrlWithPath:(NSString *)path { - NSString *adminBaseUrl = [self getOptionValue:@"admin_url"]; - if (!adminBaseUrl) { - adminBaseUrl = [self urlWithPath:@"wp-admin/"]; - } - if (![adminBaseUrl hasSuffix:@"/"]) { - adminBaseUrl = [adminBaseUrl stringByAppendingString:@"/"]; - } - return [NSString stringWithFormat:@"%@%@", adminBaseUrl, path]; -} - -- (int)numberOfPendingComments{ - int pendingComments = 0; - if ([self hasFaultForRelationshipNamed:@"comments"]) { - NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Comment"]; - [request setPredicate:[NSPredicate predicateWithFormat:@"blog = %@ AND status like 'hold'", self]]; - [request setIncludesSubentities:NO]; - NSError *error; - pendingComments = [self.managedObjectContext countForFetchRequest:request error:&error]; - } else { - for (Comment *element in self.comments) { - if ( [@"hold" isEqualToString: element.status] ) - pendingComments++; - } - } - - return pendingComments; -} - --(NSArray *)sortedCategories { - NSSortDescriptor *sortNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"categoryName" - ascending:YES - selector:@selector(caseInsensitiveCompare:)]; - NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortNameDescriptor, nil]; - - return [[self.categories allObjects] sortedArrayUsingDescriptors:sortDescriptors]; -} - -- (NSArray *)sortedPostFormatNames { - NSMutableArray *sortedNames = [NSMutableArray arrayWithCapacity:[self.postFormats count]]; - - if ([self.postFormats count] != 0) { - id standardPostFormat = [self.postFormats objectForKey:@"standard"]; - if (standardPostFormat) { - [sortedNames addObject:standardPostFormat]; - } - [self.postFormats enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) { - if (![key isEqual:@"standard"]) { - [sortedNames addObject:obj]; - } - }]; - } - - return [NSArray arrayWithArray:sortedNames]; -} - -- (BOOL)isWPcom { - if ([[self getOptionValue:@"wordpress.com"] boolValue]) { - return YES; - } - NSRange range = [self.xmlrpc rangeOfString:@"wordpress.com"]; - return (range.location != NSNotFound); -} - -//WP.COM private blog. -- (BOOL)isPrivate { - if ( [self isWPcom] && [[self getOptionValue:@"blog_public"] isEqual:@"-1"] ) - return YES; - return NO; -} - -- (NSDictionary *) getImageResizeDimensions{ - CGSize smallSize, mediumSize, largeSize; - int small_size_w = [[self getOptionValue:@"thumbnail_size_w"] intValue] > 0 ? [[self getOptionValue:@"thumbnail_size_w"] intValue] : image_small_size_w; - int small_size_h = [[self getOptionValue:@"thumbnail_size_h"] intValue] > 0 ? [[self getOptionValue:@"thumbnail_size_h"] intValue] : image_small_size_h; - int medium_size_w = [[self getOptionValue:@"medium_size_w"] intValue] > 0 ? [[self getOptionValue:@"medium_size_w"] intValue] : image_medium_size_w; - int medium_size_h = [[self getOptionValue:@"medium_size_h"] intValue] > 0 ? [[self getOptionValue:@"medium_size_h"] intValue] : image_medium_size_h; - int large_size_w = [[self getOptionValue:@"large_size_w"] intValue] > 0 ? [[self getOptionValue:@"large_size_w"] intValue] : image_large_size_w; - int large_size_h = [[self getOptionValue:@"large_size_h"] intValue] > 0 ? [[self getOptionValue:@"large_size_h"] intValue] : image_large_size_h; - - smallSize = CGSizeMake(small_size_w, small_size_h); - mediumSize = CGSizeMake(medium_size_w, medium_size_h); - largeSize = CGSizeMake(large_size_w, large_size_h); - - return [NSDictionary dictionaryWithObjectsAndKeys: [NSValue valueWithCGSize:smallSize], @"smallSize", - [NSValue valueWithCGSize:mediumSize], @"mediumSize", - [NSValue valueWithCGSize:largeSize], @"largeSize", - nil]; -} - -- (void)awakeFromFetch { - if (!self.isDeleted) { - [self reachability]; - } -} - -- (void)dataSave { -<<<<<<< HEAD - [self dataSaveWithContext:self.managedObjectContext]; -} - -- (void)dataSaveWithContext:(NSManagedObjectContext*)context { - __block NSError *error = nil; - [context performBlock:^{ - if (![context save:&error]) { - DDLogInfo(@"Unresolved Core Data Save error %@, %@", error, [error userInfo]); - #if DEBUG - exit(-1); - #endif - } - if (context.parentContext) { - [context.parentContext performBlock:^{ - if (![context.parentContext save:&error]) { - DDLogInfo(@"Unresolved Core Data Save error %@, %@", error, [error userInfo]); - #if DEBUG - exit(-1); - #endif - } - }]; - } - }]; -======= - [[ContextManager sharedInstance] saveContext:self.managedObjectContext]; ->>>>>>> refs/heads/develop -} - -- (void)remove { - DDLogInfo(@" remove", self.hostURL); - [self.api cancelAllHTTPOperations]; - _reachability.reachableBlock = nil; - _reachability.unreachableBlock = nil; - [_reachability stopNotifier]; - [self.managedObjectContext performBlock:^{ - [[self managedObjectContext] deleteObject:self]; - [self dataSave]; - }]; -} - -- (void)setXmlrpc:(NSString *)xmlrpc { - [self willChangeValueForKey:@"xmlrpc"]; - [self setPrimitiveValue:xmlrpc forKey:@"xmlrpc"]; - [self didChangeValueForKey:@"xmlrpc"]; - _blavatarUrl = nil; - - // Reset the api client so next time we use the new XML-RPC URL - _api = nil; -} - -- (NSArray *)getXMLRPCArgsWithExtra:(id)extra { - NSMutableArray *result = [NSMutableArray array]; - NSString *password = self.password; - if (!password) { - password = @""; - } - [result addObject:self.blogID]; - [result addObject:self.username]; - [result addObject:password]; - - if ([extra isKindOfClass:[NSArray class]]) { - [result addObjectsFromArray:extra]; - } else if (extra != nil) { - [result addObject:extra]; - } - - return [NSArray arrayWithArray:result]; -} - -- (NSString *)version { - return [self getOptionValue:@"software_version"]; -} - -- (Reachability *)reachability { - if (_reachability == nil) { - _reachability = [Reachability reachabilityWithHostname:self.hostname]; - __weak Blog *blog = self; - blog.reachable = YES; - _reachability.reachableBlock = ^(Reachability *reach) { - blog.reachable = YES; - }; - _reachability.unreachableBlock = ^(Reachability *reach) { - blog.reachable = NO; - }; - [_reachability startNotifier]; - } - - return _reachability; -} - -- (BOOL)reachable { - // Creates reachability object if it's nil - [self reachability]; - return _isReachable; -} - -- (void)setReachable:(BOOL)reachable { - _isReachable = reachable; -} - -- (NSString *)username { - return self.account.username ?: @""; -} - -- (NSString *)password { - return self.account.password ?: @""; -} - -#pragma mark - -#pragma mark Synchronization - -- (NSUInteger)countForSyncedPostsWithEntityName:(NSString *)entityName { - __block NSUInteger count = 0; - NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:entityName]; - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(remoteStatusNumber == %@) AND (postID != NULL) AND (original == NULL) AND (blog == %@)", - [NSNumber numberWithInt:AbstractPostRemoteStatusSync], self]; - [request setPredicate:predicate]; - NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"date_created_gmt" ascending:YES]; - [request setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]]; - request.includesSubentities = NO; - request.resultType = NSCountResultType; - - [self.managedObjectContext performBlockAndWait:^{ - NSError *error = nil; - count = [self.managedObjectContext countForFetchRequest:request error:&error]; - }]; - return count; -} - -- (void)syncPostsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure loadMore:(BOOL)more { - if (self.isSyncingPosts) { - DDLogWarn(@"Already syncing posts. Skip"); - return; - } - self.isSyncingPosts = YES; - - WPXMLRPCRequestOperation *operation = [self operationForPostsWithSuccess:success failure:failure loadMore:more]; - [self.api enqueueXMLRPCRequestOperation:operation]; -} - -- (void)syncPagesWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure loadMore:(BOOL)more { - if (self.isSyncingPages) { - DDLogWarn(@"Already syncing pages. Skip"); - return; - } - self.isSyncingPages = YES; - WPXMLRPCRequestOperation *operation = [self operationForPagesWithSuccess:success failure:failure loadMore:more]; - [self.api enqueueXMLRPCRequestOperation:operation]; -} - -- (void)syncCategoriesWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - WPXMLRPCRequestOperation *operation = [self operationForCategoriesWithSuccess:success failure:failure]; - [self.api enqueueXMLRPCRequestOperation:operation]; -} - -- (void)syncOptionsWithWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - WPXMLRPCRequestOperation *operation = [self operationForOptionsWithSuccess:success failure:failure]; - [self.api enqueueXMLRPCRequestOperation:operation]; -} - -- (id)getOptionValue:(NSString *) name { - __block id optionValue; - [self.managedObjectContext performBlockAndWait:^{ - if ( self.options == nil || (self.options.count == 0) ) { - optionValue = nil; - } - NSDictionary *currentOption = [self.options objectForKey:name]; - optionValue = [currentOption objectForKey:@"value"]; - }]; - return optionValue; -} - -- (void)syncCommentsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - if (self.isSyncingComments) { - DDLogWarn(@"Already syncing comments. Skip"); - return; - } - self.isSyncingComments = YES; - WPXMLRPCRequestOperation *operation = [self operationForCommentsWithSuccess:success failure:failure]; - [self.api enqueueXMLRPCRequestOperation:operation]; -} - -- (void)syncPostFormatsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - WPXMLRPCRequestOperation *operation = [self operationForPostFormatsWithSuccess:success failure:failure]; - [self.api enqueueXMLRPCRequestOperation:operation]; -} - -- (void)syncBlogWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - WPXMLRPCRequestOperation *operation; - NSMutableArray *operations = [NSMutableArray arrayWithCapacity:6]; - operation = [self operationForOptionsWithSuccess:nil failure:nil]; - [operations addObject:operation]; - operation = [self operationForPostFormatsWithSuccess:nil failure:nil]; - [operations addObject:operation]; - operation = [self operationForCategoriesWithSuccess:nil failure:nil]; - [operations addObject:operation]; - - if (!self.isSyncingComments) { - operation = [self operationForCommentsWithSuccess:nil failure:nil]; - [operations addObject:operation]; - self.isSyncingComments = YES; - } - - if (!self.isSyncingPosts) { - operation = [self operationForPostsWithSuccess:nil failure:nil loadMore:NO]; - [operations addObject:operation]; - self.isSyncingPosts = YES; - } - - if (!self.isSyncingPages) { - operation = [self operationForPagesWithSuccess:nil failure:nil loadMore:NO]; - [operations addObject:operation]; - self.isSyncingPages = YES; - } - - AFHTTPRequestOperation *combinedOperation = [self.api combinedHTTPRequestOperationWithOperations:operations success:^(AFHTTPRequestOperation *operation, id responseObject) { - DDLogVerbose(@"syncBlogWithSuccess:failure: completed successfully."); - if (success) { - success(); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"syncBlogWithSuccess:failure: encountered an error: %@", error); - if (failure) { - failure(error); - } - }]; - - [self.api enqueueHTTPRequestOperation:combinedOperation]; -} - -- (void)syncBlogPostsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - WPXMLRPCRequestOperation *operation; - NSMutableArray *operations = [NSMutableArray arrayWithCapacity:4]; - operation = [self operationForOptionsWithSuccess:nil failure:nil]; - [operations addObject:operation]; - operation = [self operationForPostFormatsWithSuccess:nil failure:nil]; - [operations addObject:operation]; - operation = [self operationForCategoriesWithSuccess:nil failure:nil]; - [operations addObject:operation]; - if (!self.isSyncingPosts) { - operation = [self operationForPostsWithSuccess:success failure:failure loadMore:NO]; - [operations addObject:operation]; - self.isSyncingPosts = YES; - } - - AFHTTPRequestOperation *combinedOperation = [self.api combinedHTTPRequestOperationWithOperations:operations success:nil failure:nil]; - [self.api enqueueHTTPRequestOperation:combinedOperation]; -} - -- (void)checkVideoPressEnabledWithSuccess:(void (^)(BOOL enabled))success failure:(void (^)(NSError *error))failure { - if (!self.isWPcom) { - if (success) success(YES); - return; - } - NSArray *parameters = [self getXMLRPCArgsWithExtra:nil]; - WPXMLRPCRequest *request = [self.api XMLRPCRequestWithMethod:@"wpcom.getFeatures" parameters:parameters]; - WPXMLRPCRequestOperation *operation = [self.api XMLRPCRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - BOOL videoEnabled = YES; - if(([responseObject isKindOfClass:[NSDictionary class]]) && ([responseObject objectForKey:@"videopress_enabled"] != nil)) { - videoEnabled = [[responseObject objectForKey:@"videopress_enabled"] boolValue]; - } else { - videoEnabled = YES; - } - - if (success) { - success(videoEnabled); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"Error while checking if VideoPress is enabled: %@", error); - - if (failure) { - failure(error); - } - }]; - [self.api enqueueXMLRPCRequestOperation:operation]; -} - -#pragma mark - api accessor - -- (WPXMLRPCClient *)api { - if (_api == nil) { - _api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:self.xmlrpc]]; - // Enable compression for wp.com only, as some self hosted have connection issues - if (self.isWPcom) { - [_api setDefaultHeader:@"gzip, deflate" value:@"Accept-Encoding"]; - } - } - return _api; -} - -#pragma mark - - -- (WPXMLRPCRequestOperation *)operationForOptionsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - __block WPXMLRPCRequestOperation *operation; - [self.managedObjectContext performBlockAndWait:^{ - NSArray *parameters = [self getXMLRPCArgsWithExtra:nil]; - WPXMLRPCRequest *request = [self.api XMLRPCRequestWithMethod:@"wp.getOptions" parameters:parameters]; - operation = [self.api XMLRPCRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - if ([self isDeleted] || self.managedObjectContext == nil) - return; - - self.options = [NSDictionary dictionaryWithDictionary:(NSDictionary *)responseObject]; - NSString *minimumVersion = @"3.1"; - float version = [[self version] floatValue]; - if (version < [minimumVersion floatValue]) { - if (self.lastUpdateWarning == nil || [self.lastUpdateWarning floatValue] < [minimumVersion floatValue]) { - [[WordPressAppDelegate sharedWordPressApplicationDelegate] showAlertWithTitle:NSLocalizedString(@"WordPress version too old", @"") - message:[NSString stringWithFormat:NSLocalizedString(@"The site at %@ uses WordPress %@. We recommend to update to the latest version, or at least %@", @""), [self hostname], [self version], minimumVersion]]; - self.lastUpdateWarning = minimumVersion; - } - } - if (success) { - success(); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"Error syncing options: %@", error); - - if (failure) { - failure(error); - } - }]; - }]; - return operation; -} - -- (WPXMLRPCRequestOperation *)operationForPostFormatsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - __block WPXMLRPCRequestOperation *operation; - [self.managedObjectContext performBlockAndWait:^{ - NSDictionary *dict = [NSDictionary dictionaryWithObject:@"1" forKey:@"show-supported"]; - NSArray *parameters = [self getXMLRPCArgsWithExtra:dict]; - - WPXMLRPCRequest *request = [self.api XMLRPCRequestWithMethod:@"wp.getPostFormats" parameters:parameters]; - operation = [self.api XMLRPCRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - if ([self isDeleted] || self.managedObjectContext == nil) - return; - - NSDictionary *respDict = [NSDictionary dictionaryWithDictionary:(NSDictionary *)responseObject]; - if ([respDict objectForKey:@"supported"] && [[respDict objectForKey:@"supported"] isKindOfClass:[NSArray class]]) { - NSMutableArray *supportedKeys = [NSMutableArray arrayWithArray:[respDict objectForKey:@"supported"]]; - // Standard isn't included in the list of supported formats? Maybe it will be one day? - if (![supportedKeys containsObject:@"standard"]) { - [supportedKeys addObject:@"standard"]; - } - - NSDictionary *allFormats = [respDict objectForKey:@"all"]; - NSMutableArray *supportedValues = [NSMutableArray array]; - for (NSString *key in supportedKeys) { - [supportedValues addObject:[allFormats objectForKey:key]]; - } - respDict = [NSDictionary dictionaryWithObjects:supportedValues forKeys:supportedKeys]; - } - self.postFormats = respDict; - if (success) { - success(); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"Error syncing post formats: %@", error); - - if (failure) { - failure(error); - } - }]; - }]; - return operation; -} - -- (WPXMLRPCRequestOperation *)operationForCommentsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - __block WPXMLRPCRequestOperation *operation; - [self.managedObjectContext performBlockAndWait:^{ - NSDictionary *requestOptions = [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:100] forKey:@"number"]; - NSArray *parameters = [self getXMLRPCArgsWithExtra:requestOptions]; - WPXMLRPCRequest *request = [self.api XMLRPCRequestWithMethod:@"wp.getComments" parameters:parameters]; - operation = [self.api XMLRPCRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - if ([self isDeleted] || self.managedObjectContext == nil) - return; - - [Comment mergeNewComments:responseObject forBlog:self]; - self.isSyncingComments = NO; - self.lastCommentsSync = [NSDate date]; - - if (success) { - success(); - } - [[NSNotificationCenter defaultCenter] postNotificationName:kCommentsChangedNotificationName object:self]; - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"Error syncing comments: %@", error); - self.isSyncingComments = NO; - - if (failure) { - failure(error); - } - [[NSNotificationCenter defaultCenter] postNotificationName:kCommentsChangedNotificationName object:self]; - }]; - }]; - return operation; -} - -- (WPXMLRPCRequestOperation *)operationForCategoriesWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - __block WPXMLRPCRequestOperation *operation; - [self.managedObjectContext performBlockAndWait:^{ - NSArray *parameters = [self getXMLRPCArgsWithExtra:nil]; - WPXMLRPCRequest *request = [self.api XMLRPCRequestWithMethod:@"wp.getCategories" parameters:parameters]; - operation = [self.api XMLRPCRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - if ([self isDeleted] || self.managedObjectContext == nil) - return; - - [Category mergeNewCategories:responseObject forBlog:self]; - - if (success) { - success(); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"Error syncing categories: %@", error); - - if (failure) { - failure(error); - } - }]; - }]; - return operation; -} - -- (WPXMLRPCRequestOperation *)operationForPostsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure loadMore:(BOOL)more { - // Don't load more than 20 posts if we aren't at the end of the table, - // even if they were previously donwloaded - // - // Blogs with long history can get really slow really fast, - // with no chance to go back - - NSUInteger postBatchSize = 40; - __block WPXMLRPCRequestOperation *operation; - [self.managedObjectContext performBlockAndWait:^{ - NSUInteger postsToRequest = postBatchSize; - if (more) { - postsToRequest = MAX([self.posts count], postBatchSize); - if ([self.hasOlderPosts boolValue]) { - postsToRequest += postBatchSize; - } - } - - NSArray *parameters = [self getXMLRPCArgsWithExtra:[NSNumber numberWithInt:postsToRequest]]; - WPXMLRPCRequest *request = [self.api XMLRPCRequestWithMethod:@"metaWeblog.getRecentPosts" parameters:parameters]; - operation = [self.api XMLRPCRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - if ([self isDeleted] || self.managedObjectContext == nil) - return; - - NSArray *posts = (NSArray *)responseObject; - - // If we asked for more and we got what we had, there are no more posts to load - if (more && ([posts count] <= [self.posts count])) { - self.hasOlderPosts = [NSNumber numberWithBool:NO]; - } else if (!more) { - //we should reset the flag otherwise when you refresh this blog you can't get more than 20 posts - self.hasOlderPosts = [NSNumber numberWithBool:YES]; - } - - [Post mergeNewPosts:responseObject forBlog:self]; - - self.lastPostsSync = [NSDate date]; - self.isSyncingPosts = NO; - - if (success) { - success(); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"Error syncing posts: %@", error); - self.isSyncingPosts = NO; - - if (failure) { - failure(error); - } - }]; - }]; - return operation; -} - -- (WPXMLRPCRequestOperation *)operationForPagesWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure loadMore:(BOOL)more { - // Don't load more than 20 pages if we aren't at the end of the table, - // even if they were previously donwloaded - // - // Blogs with long history can get really slow really fast, - // with no chance to go back - - NSUInteger pageBatchSize = 40; - __block WPXMLRPCRequestOperation *operation; - [self.managedObjectContext performBlockAndWait:^{ - NSUInteger pagesToRequest = pageBatchSize; - NSUInteger syncCount = [self countForSyncedPostsWithEntityName:@"Page"]; - if (more) { - pagesToRequest = MAX(syncCount, pageBatchSize); - if ([self.hasOlderPages boolValue]) { - pagesToRequest += pageBatchSize; - } - } - - NSArray *parameters = [self getXMLRPCArgsWithExtra:[NSNumber numberWithInt:pagesToRequest]]; - WPXMLRPCRequest *request = [self.api XMLRPCRequestWithMethod:@"wp.getPages" parameters:parameters]; - operation = [self.api XMLRPCRequestOperationWithRequest:request success:^(AFHTTPRequestOperation *operation, id responseObject) { - if ([self isDeleted] || self.managedObjectContext == nil) - return; - - NSArray *pages = (NSArray *)responseObject; - - // If we asked for more and we got what we had, there are no more pages to load - if (more && ([pages count] <= syncCount)) { - self.hasOlderPages = [NSNumber numberWithBool:NO]; - } else if (!more) { - //we should reset the flag otherwise when you refresh this blog you can't get more than 20 pages - self.hasOlderPages = [NSNumber numberWithBool:YES]; - } - - [Page mergeNewPosts:responseObject forBlog:self]; - self.lastPagesSync = [NSDate date]; - self.isSyncingPages = NO; - if (success) { - success(); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"Error syncing pages: %@", error); - self.isSyncingPages = NO; - - if (failure) { - failure(error); - } - }]; - }]; - return operation; -} - -@end diff --git a/WordPress/Classes/BlogListViewController.m.orig b/WordPress/Classes/BlogListViewController.m.orig deleted file mode 100644 index c6670d275224..000000000000 --- a/WordPress/Classes/BlogListViewController.m.orig +++ /dev/null @@ -1,393 +0,0 @@ -// -// BlogListViewController.m -// WordPress -// -// Created by Michael Johnston on 11/8/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import "BlogListViewController.h" -#import "WordPressAppDelegate.h" -#import "UIImageView+Gravatar.h" -#import "WordPressComApi.h" -#import "SettingsViewController.h" -#import "LoginViewController.h" -#import "BlogDetailsViewController.h" -#import "WPTableViewCell.h" -#import "ContextManager.h" -#import "Blog.h" -#import "WPAccount.h" -#import "FakePushTransitionAnimator.h" -#import "ManageBlogsViewController.h" - -CGFloat const blavatarImageSize = 50.f; - -@interface BlogListViewController () -@property (nonatomic, strong) NSFetchedResultsController *resultsController; -@property (nonatomic, strong) UIBarButtonItem *settingsButton; - -@end - -@implementation BlogListViewController - -- (id)initWithStyle:(UITableViewStyle)style -{ - self = [super initWithStyle:UITableViewStyleGrouped]; - if (self) { - // Custom initialization - } - return self; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - self.navigationItem.leftBarButtonItem = self.editButtonItem; - self.settingsButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Settings", nil) - style:UIBarButtonItemStylePlain - target:self - action:@selector(showSettings:)]; - self.navigationItem.rightBarButtonItem = self.settingsButton; - - [[NSNotificationCenter defaultCenter] addObserverForName:WordPressComApiDidLoginNotification object:nil queue:nil usingBlock:^(NSNotification *note) { - [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; - }]; - [[NSNotificationCenter defaultCenter] addObserverForName:WordPressComApiDidLogoutNotification object:nil queue:nil usingBlock:^(NSNotification *note) { - [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; - }]; - - // Remove one-pixel gap resulting from a top-aligned grouped table view - if (IS_IPHONE) { - UIEdgeInsets tableInset = [self.tableView contentInset]; - tableInset.top = -1; - self.tableView.contentInset = tableInset; - } - - [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; - - // Uncomment the following line to preserve selection between presentations. - // self.clearsSelectionOnViewWillAppear = NO; - - // Uncomment the following line to display an Edit button in the navigation bar for this view controller. - // self.navigationItem.rightBarButtonItem = self.editButtonItem; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self.navigationController setNavigationBarHidden:NO animated:animated]; - self.resultsController.delegate = self; - [self.resultsController performFetch:nil]; - [self.tableView reloadData]; - - self.editButtonItem.enabled = ([self numSites] > 0); -} - -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - self.resultsController.delegate = nil; -} - -- (NSUInteger)numSites { - return [[self.resultsController fetchedObjects] count]; -} - -- (void)showManageBlogsHintIfNeeded { - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - - if ([defaults objectForKey:HasSeenManageBlogsHintDefaultsKey]) { - return; - } - - UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Hidden Blogs", nil) - message:NSLocalizedString(@"If you want to see this or other hidden blogs in the app, you can do it from Settings > Manage Blogs", nil) - delegate:nil - cancelButtonTitle:NSLocalizedString(@"OK", nil) - otherButtonTitles:nil]; - [alertView show]; - [defaults setBool:YES forKey:HasSeenManageBlogsHintDefaultsKey]; - [defaults synchronize]; -} - -#pragma mark - Actions - -- (void)showSettings:(id)sender { - [WPMobileStats incrementProperty:StatsPropertySidebarClickedSettings forEvent:StatsEventAppClosed]; - - SettingsViewController *settingsViewController = [[SettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:settingsViewController]; - aNavigationController.navigationBar.translucent = NO; - if (IS_IPAD) - aNavigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; - aNavigationController.modalPresentationStyle = UIModalPresentationFormSheet; - - [self.navigationController presentViewController:aNavigationController animated:YES completion:nil]; -} - - - -#pragma mark - Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - NSInteger numRows = [self numSites]; - - // Plus an extra row for 'Add a Site' (when not editing) - if (![tableView isEditing]) - numRows += 1; - - return numRows; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath -{ - NSString *cellIdentifier = @"BlogCell"; - UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier]; - if (cell == nil) { - cell = [[WPTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier]; - } - - [WPStyleGuide configureTableViewCell:cell]; - [self configureCell:cell atIndexPath:indexPath]; - - return cell; -} - -- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath { - Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]]; - if (blog.isWPcom) { - return NSLocalizedString(@"Hide", nil); - } - return NSLocalizedString(@"Remove", @"Button label when removing a blog"); -} - -- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - return indexPath.row != [self rowForAddSite]; -} - -- (void)setEditing:(BOOL)editing animated:(BOOL)animated { - [super setEditing:editing animated:animated]; - - // And the "Add a Site" row too - NSArray *rowsToChange = [NSArray arrayWithObject:[NSIndexPath indexPathForRow:[self rowForAddSite] inSection:0]]; - - UITableViewRowAnimation rowAnimation = animated ? UITableViewRowAnimationFade : UITableViewRowAnimationNone; - [self.tableView beginUpdates]; - if (editing) { - [self.tableView deleteRowsAtIndexPaths:rowsToChange withRowAnimation:rowAnimation]; - [self.navigationItem setRightBarButtonItem:nil animated:animated]; - } else { - [self.tableView insertRowsAtIndexPaths:rowsToChange withRowAnimation:rowAnimation]; - [self.navigationItem setRightBarButtonItem:self.settingsButton animated:animated]; - } - [self.tableView endUpdates]; -} - - -- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { - if (editingStyle == UITableViewCellEditingStyleDelete) { - [WPMobileStats trackEventForWPCom:StatsEventSettingsRemovedBlog]; - - Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]]; - if (blog.isWPcom) { - blog.visible = NO; - [blog dataSave]; - [self showManageBlogsHintIfNeeded]; - } else { - [blog remove]; - } - - // Count won't be updated yet; if this is the last site (count 1), exit editing mode - if ([self numSites] == 1) { - // Update the UI in the next run loop after the resultsController has updated - // (otherwise row insertion/deletion logic won't work) - dispatch_async(dispatch_get_main_queue(), ^{ - self.editButtonItem.enabled = NO; - [self setEditing:NO animated:YES]; - - // No blogs and signed out, show NUX - if (![WPAccount defaultWordPressComAccount]) { - [[WordPressAppDelegate sharedWordPressApplicationDelegate] showWelcomeScreenIfNeededAnimated:YES]; - } - }); - } - } -} - -- (NSInteger)rowForAddSite { - return [self numSites]; -} - -- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { - cell.textLabel.textAlignment = NSTextAlignmentLeft; - cell.accessoryType = UITableViewCellAccessoryNone; - cell.accessoryView = nil; - - if (indexPath.row < [self rowForAddSite]) { - Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:indexPath.row inSection:0]]; - if ([blog.blogName length] != 0) { - cell.textLabel.text = blog.blogName; - } else { - cell.textLabel.text = blog.url; - } - - [cell.imageView setImageWithBlavatarUrl:blog.blavatarUrl isWPcom:blog.isWPcom]; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - -// if (indexPath.row == 0) { -// [self maskImageView:cell.imageView corner:UIRectCornerTopLeft]; -// } else if (indexPath.row == ([self.tableView numberOfRowsInSection:indexPath.section] -1)) { -// [self maskImageView:cell.imageView corner:UIRectCornerBottomLeft]; -// } else { -// cell.imageView.layer.mask = NULL; -// } - } else { - cell.textLabel.text = NSLocalizedString(@"Add a Site", @""); - cell.selectionStyle = UITableViewCellSelectionStyleBlue; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - - // To align the label, create and add a blank image - UIGraphicsBeginImageContextWithOptions(CGSizeMake(blavatarImageSize, blavatarImageSize), NO, 0.0); - UIImage *blank = UIGraphicsGetImageFromCurrentImageContext(); - UIGraphicsEndImageContext(); - [cell.imageView setImage:blank]; - } -} - -- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { - // No top margin on iPhone - if (IS_IPHONE) - return 1; - - return 40; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - - if (indexPath.row < [self rowForAddSite]) { - [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedEditBlog]; - - Blog *blog = [self.resultsController objectAtIndexPath:indexPath]; - - BlogDetailsViewController *blogDetailsViewController = [[BlogDetailsViewController alloc] init]; - blogDetailsViewController.blog = blog; - [self.navigationController pushViewController:blogDetailsViewController animated:YES]; - } else { - [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedAddBlog]; - - LoginViewController *loginViewController = [[LoginViewController alloc] init]; - if (![WPAccount defaultWordPressComAccount]) { - loginViewController.prefersSelfHosted = YES; - } - loginViewController.dismissBlock = ^{ - [self dismissViewControllerAnimated:YES completion:nil]; - }; - UINavigationController *loginNavigationController = [[UINavigationController alloc] initWithRootViewController:loginViewController]; - loginNavigationController.transitioningDelegate = self; - loginNavigationController.modalTransitionStyle = UIModalPresentationCustom; - [self presentViewController:loginNavigationController animated:YES completion:nil]; - } -} - -- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - return 54; -} - - -#pragma mark - -#pragma mark NSFetchedResultsController - -- (NSFetchedResultsController *)resultsController { - if (_resultsController) { - return _resultsController; - } - -<<<<<<< HEAD - NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; - NSManagedObjectContext *moc = [[WordPressAppDelegate sharedWordPressApplicationDelegate] managedObjectContext]; - [fetchRequest setEntity:[NSEntityDescription entityForName:@"Blog" inManagedObjectContext:moc]]; - [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"visible = YES"]]; - [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]]; -======= - NSManagedObjectContext *moc = [[ContextManager sharedInstance] mainContext]; - NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Blog"]; - fetchRequest.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES]]; ->>>>>>> refs/heads/develop - - // For some reasons, the cache sometimes gets corrupted - // Since we don't really use sections we skip the cache here - _resultsController = [[NSFetchedResultsController alloc] - initWithFetchRequest:fetchRequest - managedObjectContext:moc - sectionNameKeyPath:nil - cacheName:nil]; - _resultsController.delegate = self; - - NSError *error = nil; - if (![_resultsController performFetch:&error]) { - DDLogError(@"Couldn't fetch blogs: %@", [error localizedDescription]); - _resultsController = nil; - } - return _resultsController; -} - -- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { - [self.tableView beginUpdates]; -} - -- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { - [self.tableView endUpdates]; -} - -- (void)controller:(NSFetchedResultsController *)controller - didChangeObject:(id)anObject - atIndexPath:(NSIndexPath *)indexPath - forChangeType:(NSFetchedResultsChangeType)type - newIndexPath:(NSIndexPath *)newIndexPath { - - if (NSFetchedResultsChangeUpdate == type && newIndexPath != nil) { - // Seriously, Apple? - // http://developer.apple.com/library/ios/#releasenotes/iPhone/NSFetchedResultsChangeMoveReportedAsNSFetchedResultsChangeUpdate/_index.html - type = NSFetchedResultsChangeMove; - } - - switch (type) { - case NSFetchedResultsChangeInsert: - [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; - break; - - case NSFetchedResultsChangeDelete: - [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; - break; - - case NSFetchedResultsChangeUpdate: - [self configureCell:[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; - break; - - case NSFetchedResultsChangeMove: - [self.tableView deleteRowsAtIndexPaths:[NSArray - arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; - [self.tableView insertRowsAtIndexPaths:[NSArray - arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; - break; - } -} - -#pragma mark - UIViewControllerTransitioningDelegate - -- (id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { - FakePushTransitionAnimator *animator = [FakePushTransitionAnimator new]; - animator.presenting = YES; - return animator; -} - -- (id )animationControllerForDismissedController:(UIViewController *)dismissed { - FakePushTransitionAnimator *animator = [FakePushTransitionAnimator new]; - return animator; -} - -@end diff --git a/WordPress/Classes/CreateAccountAndBlogViewController.m.orig b/WordPress/Classes/CreateAccountAndBlogViewController.m.orig deleted file mode 100644 index 50968de0d1f0..000000000000 --- a/WordPress/Classes/CreateAccountAndBlogViewController.m.orig +++ /dev/null @@ -1,757 +0,0 @@ -// -// CreateAccountAndBlogViewController.m -// WordPress -// -// Created by Sendhil Panchadsaram on 5/7/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import "CreateAccountAndBlogViewController.h" -#import -#import -#import "SupportViewController.h" -#import "WordPressComApi.h" -#import "UIView+FormSheetHelpers.h" -#import "WPNUXBackButton.h" -#import "WPNUXMainButton.h" -#import "WPWalkthroughTextField.h" -#import "WPAsyncBlockOperation.h" -#import "WPComLanguages.h" -#import "WPWalkthroughOverlayView.h" -#import "SelectWPComLanguageViewController.h" -#import "WPNUXUtility.h" -#import "WPWebViewController.h" -#import "WPStyleGuide.h" -#import "UILabel+SuggestSize.h" -#import "WPAccount.h" -#import "Blog.h" -#import "WordPressComOAuthClient.h" - -@interface CreateAccountAndBlogViewController ()< - UITextFieldDelegate, - UIGestureRecognizerDelegate> { - - // Page 1 - WPNUXBackButton *_cancelButton; - UIButton *_helpButton; - UILabel *_titleLabel; - UILabel *_TOSLabel; - UILabel *_siteAddressWPComLabel; - WPWalkthroughTextField *_emailField; - WPWalkthroughTextField *_usernameField; - WPWalkthroughTextField *_passwordField; - WPNUXMainButton *_createAccountButton; - WPWalkthroughTextField *_siteAddressField; - - NSOperationQueue *_operationQueue; - - BOOL _authenticating; - BOOL _keyboardVisible; - BOOL _shouldCorrectEmail; - BOOL _userDefinedSiteAddress; - CGFloat _keyboardOffset; - NSString *_defaultSiteUrl; - - CGFloat _viewWidth; - CGFloat _viewHeight; - - NSDictionary *_currentLanguage; - - WPAccount *_account; -} - -@end - -@implementation CreateAccountAndBlogViewController - -CGFloat const CreateAccountAndBlogStandardOffset = 16.0; -CGFloat const CreateAccountAndBlogIconVerticalOffset = 70.0; -CGFloat const CreateAccountAndBlogMaxTextWidth = 260.0; -CGFloat const CreateAccountAndBlogTextFieldWidth = 320.0; -CGFloat const CreateAccountAndBlogTextFieldHeight = 44.0; -CGFloat const CreateAccountAndBlogKeyboardOffset = 132.0; -CGFloat const CreateAccountAndBlogiOS7StatusBarOffset = 20.0; -CGFloat const CreateAccountAndBlogButtonWidth = 289.0; -CGFloat const CreateAccountAndBlogButtonHeight = 41.0; - -- (id)init -{ - self = [super init]; - if (self) { - _shouldCorrectEmail = YES; - _operationQueue = [[NSOperationQueue alloc] init]; - _currentLanguage = [WPComLanguages currentLanguage]; - } - return self; -} - -- (void)viewDidLoad -{ - [super viewDidLoad]; - - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXCreateAccountOpened]; - - _viewWidth = [self.view formSheetViewWidth]; - _viewHeight = [self.view formSheetViewHeight]; - self.view.backgroundColor = [WPNUXUtility backgroundColor]; - - [self initializeView]; - - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidShow) name:UIKeyboardDidShowNotification object:nil]; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(keyboardDidHide) name:UIKeyboardDidHideNotification object:nil]; -} - -- (void)viewWillAppear:(BOOL)animated -{ - [super viewWillAppear:animated]; - [self.navigationController setNavigationBarHidden:YES animated:animated]; -} - -- (NSUInteger)supportedInterfaceOrientations { - if (IS_IPHONE) - return UIInterfaceOrientationMaskPortrait; - - return UIInterfaceOrientationMaskAll; -} - -#pragma mark - UITextField Delegate methods - -- (BOOL)textFieldShouldReturn:(UITextField *)textField -{ - if (textField == _emailField) { - [_usernameField becomeFirstResponder]; - } else if (textField == _usernameField) { - [_passwordField becomeFirstResponder]; - } else if (textField == _passwordField) { - [_siteAddressField becomeFirstResponder]; - } else if (textField == _siteAddressField) { - if (_createAccountButton.enabled) { - [self createAccountButtonAction]; - } - } - return YES; -} - -- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string -{ - NSArray *fields = @[_emailField, _usernameField, _passwordField, _siteAddressField]; - - NSMutableString *updatedString = [[NSMutableString alloc] initWithString:textField.text]; - [updatedString replaceCharactersInRange:range withString:string]; - - if ([fields containsObject:textField]) { - [self updateCreateAccountButtonForTextfield:textField andUpdatedString:updatedString]; - } - - if ([textField isEqual:_siteAddressField]) { - _userDefinedSiteAddress = YES; - } - return YES; -} - -- (void)textFieldDidEndEditing:(UITextField *)textField { - - if ([textField isEqual:_usernameField]) { - if ([[_siteAddressField.text trim] length] == 0 || !_userDefinedSiteAddress) { - _siteAddressField.text = _defaultSiteUrl = _usernameField.text; - _userDefinedSiteAddress = NO; - [self updateCreateAccountButtonForTextfield:_siteAddressField andUpdatedString:_siteAddressField.text]; - } - } -} - -- (void)updateCreateAccountButtonForTextfield:(UITextField *)textField andUpdatedString:(NSString *)updatedString -{ - BOOL isEmailFilled = [self isEmailedFilled]; - BOOL isUsernameFilled = [self isUsernameFilled]; - BOOL isPasswordFilled = [self isPasswordFilled]; - BOOL isSiteAddressFilled = [self isSiteAddressFilled]; - BOOL updatedStringHasContent = [[updatedString trim] length] != 0; - - if (textField == _emailField) { - isEmailFilled = updatedStringHasContent; - } else if (textField == _usernameField) { - isUsernameFilled = updatedStringHasContent; - } else if (textField == _passwordField) { - isPasswordFilled = updatedStringHasContent; - } else if (textField == _siteAddressField) { - isSiteAddressFilled = updatedStringHasContent; - } - - _createAccountButton.enabled = isEmailFilled && isUsernameFilled && isPasswordFilled && isSiteAddressFilled; -} - -- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField -{ - _createAccountButton.enabled = [self fieldsFilled]; - return YES; -} - -- (BOOL)textFieldShouldEndEditing:(UITextField *)textField -{ - if (textField == _emailField) { - // check email validity - NSString *suggestedEmail = [EmailChecker suggestDomainCorrection: _emailField.text]; - if (![suggestedEmail isEqualToString:_emailField.text] && _shouldCorrectEmail) { - textField.text = suggestedEmail; - _shouldCorrectEmail = NO; - } - } - _createAccountButton.enabled = [self fieldsFilled]; - return YES; -} - -#pragma mark - Private Methods - -- (void)initializeView -{ - UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(viewWasTapped:)]; - gestureRecognizer.numberOfTapsRequired = 1; - gestureRecognizer.cancelsTouchesInView = YES; - [self.view addGestureRecognizer:gestureRecognizer]; - - [self addControls]; - [self layoutControls]; -} - -- (void)addControls -{ - // Add Help Button - UIImage *helpButtonImage = [UIImage imageNamed:@"btn-help"]; - if (_helpButton == nil) { - _helpButton = [UIButton buttonWithType:UIButtonTypeCustom]; - [_helpButton setImage:helpButtonImage forState:UIControlStateNormal]; - _helpButton.frame = CGRectMake(0, 0, helpButtonImage.size.width, helpButtonImage.size.height); - [_helpButton addTarget:self action:@selector(helpButtonAction) forControlEvents:UIControlEventTouchUpInside]; - [self.view addSubview:_helpButton]; - } - - // Add Cancel Button - if (_cancelButton == nil) { - _cancelButton = [[WPNUXBackButton alloc] init]; - [_cancelButton setTitle:NSLocalizedString(@"Cancel", nil) forState:UIControlStateNormal]; - [_cancelButton addTarget:self action:@selector(cancelButtonAction) forControlEvents:UIControlEventTouchUpInside]; - [_cancelButton sizeToFit]; - [self.view addSubview:_cancelButton]; - } - - // Add Title - if (_titleLabel == nil) { - _titleLabel = [[UILabel alloc] init]; - _titleLabel.attributedText = [WPNUXUtility titleAttributedString:NSLocalizedString(@"Create an account on WordPress.com", @"NUX Create Account Page 1 Title")]; - _titleLabel.numberOfLines = 0; - _titleLabel.backgroundColor = [UIColor clearColor]; - [self.view addSubview:_titleLabel]; - } - - // Add Email - if (_emailField == nil) { - _emailField = [[WPWalkthroughTextField alloc] initWithLeftViewImage:[UIImage imageNamed:@"icon-email-field"]]; - _emailField.backgroundColor = [UIColor whiteColor]; - _emailField.placeholder = NSLocalizedString(@"Email Address", @"NUX Create Account Page 1 Email Placeholder"); - _emailField.font = [WPNUXUtility textFieldFont]; - _emailField.adjustsFontSizeToFitWidth = YES; - _emailField.delegate = self; - _emailField.autocorrectionType = UITextAutocorrectionTypeNo; - _emailField.autocapitalizationType = UITextAutocapitalizationTypeNone; - _emailField.keyboardType = UIKeyboardTypeEmailAddress; - [self.view addSubview:_emailField]; - } - - // Add Username - if (_usernameField == nil) { - _usernameField = [[WPWalkthroughTextField alloc] initWithLeftViewImage:[UIImage imageNamed:@"icon-username-field"]]; - _usernameField.backgroundColor = [UIColor whiteColor]; - _usernameField.placeholder = NSLocalizedString(@"Username", nil); - _usernameField.font = [WPNUXUtility textFieldFont]; - _usernameField.adjustsFontSizeToFitWidth = YES; - _usernameField.delegate = self; - _usernameField.autocorrectionType = UITextAutocorrectionTypeNo; - _usernameField.autocapitalizationType = UITextAutocapitalizationTypeNone; - _usernameField.showTopLineSeparator = YES; - [self.view addSubview:_usernameField]; - } - - // Add Password - if (_passwordField == nil) { - _passwordField = [[WPWalkthroughTextField alloc] initWithLeftViewImage:[UIImage imageNamed:@"icon-password-field"]]; - _passwordField.secureTextEntry = YES; - _passwordField.backgroundColor = [UIColor whiteColor]; - _passwordField.placeholder = NSLocalizedString(@"Password", nil); - _passwordField.font = [WPNUXUtility textFieldFont]; - _passwordField.adjustsFontSizeToFitWidth = YES; - _passwordField.delegate = self; - _passwordField.autocorrectionType = UITextAutocorrectionTypeNo; - _passwordField.autocapitalizationType = UITextAutocapitalizationTypeNone; - _passwordField.showTopLineSeparator = YES; - [self.view addSubview:_passwordField]; - } - - // Add Site Address - if (_siteAddressField == nil) { - _siteAddressField = [[WPWalkthroughTextField alloc] initWithLeftViewImage:[UIImage imageNamed:@"icon-url-field"]]; - _siteAddressField.backgroundColor = [UIColor whiteColor]; - _siteAddressField.placeholder = NSLocalizedString(@"Site Address (URL)", nil); - _siteAddressField.font = [WPNUXUtility textFieldFont]; - _siteAddressField.adjustsFontSizeToFitWidth = YES; - _siteAddressField.delegate = self; - _siteAddressField.autocorrectionType = UITextAutocorrectionTypeNo; - _siteAddressField.autocapitalizationType = UITextAutocapitalizationTypeNone; - _siteAddressField.showTopLineSeparator = YES; - [self.view addSubview:_siteAddressField]; - - // add .wordpress.com label to textfield - _siteAddressWPComLabel = [[UILabel alloc] init]; - _siteAddressWPComLabel.text = @".wordpress.com"; - _siteAddressWPComLabel.textAlignment = NSTextAlignmentCenter; - _siteAddressWPComLabel.font = [WPNUXUtility descriptionTextFont]; - _siteAddressWPComLabel.textColor = [WPStyleGuide allTAllShadeGrey]; - [_siteAddressWPComLabel sizeToFit]; - - UIEdgeInsets siteAddressTextInsets = [(WPWalkthroughTextField *)_siteAddressField textInsets]; - siteAddressTextInsets.right += _siteAddressWPComLabel.frame.size.width + 10; - [(WPWalkthroughTextField *)_siteAddressField setTextInsets:siteAddressTextInsets]; - [_siteAddressField addSubview:_siteAddressWPComLabel]; - } - - // Add Terms of Service Label - if (_TOSLabel == nil) { - _TOSLabel = [[UILabel alloc] init]; - _TOSLabel.userInteractionEnabled = YES; - _TOSLabel.textAlignment = NSTextAlignmentCenter; - _TOSLabel.text = NSLocalizedString(@"By creating an account you agree to the fascinating terms of service.", @"NUX Create Account TOS Label"); - _TOSLabel.numberOfLines = 0; - _TOSLabel.backgroundColor = [UIColor clearColor]; - _TOSLabel.font = [WPNUXUtility tosLabelFont]; - _TOSLabel.textColor = [WPNUXUtility tosLabelColor]; - [self.view addSubview:_TOSLabel]; - - UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(TOSLabelWasTapped)]; - gestureRecognizer.numberOfTapsRequired = 1; - [_TOSLabel addGestureRecognizer:gestureRecognizer]; - } - - // Add Next Button - if (_createAccountButton == nil) { - _createAccountButton = [[WPNUXMainButton alloc] init]; - [_createAccountButton setTitle:NSLocalizedString(@"Create Account", nil) forState:UIControlStateNormal]; - _createAccountButton.enabled = NO; - [_createAccountButton addTarget:self action:@selector(createAccountButtonAction) forControlEvents:UIControlEventTouchUpInside]; - [_createAccountButton sizeToFit]; - [self.view addSubview:_createAccountButton]; - } -} - -- (void)layoutControls -{ - CGFloat x,y; - - // Layout Help Button - UIImage *helpButtonImage = [UIImage imageNamed:@"btn-help"]; - x = _viewWidth - helpButtonImage.size.width - CreateAccountAndBlogStandardOffset; - y = 0.5 * CreateAccountAndBlogStandardOffset; - if (IS_IOS7 && IS_IPHONE) { - y += CreateAccountAndBlogiOS7StatusBarOffset; - } - _helpButton.frame = CGRectMake(x, y, helpButtonImage.size.width, helpButtonImage.size.height); - - // Layout Cancel Button - x = 0; - y = 0.5 * CreateAccountAndBlogStandardOffset; - if (IS_IOS7 && IS_IPHONE) { - y += CreateAccountAndBlogiOS7StatusBarOffset; - } - _cancelButton.frame = CGRectMake(x, y, CGRectGetWidth(_cancelButton.frame), CGRectGetHeight(_cancelButton.frame)); - - // Layout the controls starting out from y of 0, then offset them once the height of the controls - // is accurately calculated we can determine the vertical center and adjust everything accordingly. - - // Layout Title - CGSize titleSize = [_titleLabel suggestedSizeForWidth:CreateAccountAndBlogMaxTextWidth]; - x = (_viewWidth - titleSize.width)/2.0; - y = 0; - _titleLabel.frame = CGRectIntegral(CGRectMake(x, y, titleSize.width, titleSize.height)); - - // Layout Email - x = (_viewWidth - CreateAccountAndBlogTextFieldWidth)/2.0; - y = CGRectGetMaxY(_titleLabel.frame) + CreateAccountAndBlogStandardOffset; - _emailField.frame = CGRectIntegral(CGRectMake(x, y, CreateAccountAndBlogTextFieldWidth, CreateAccountAndBlogTextFieldHeight)); - - // Layout Username - x = (_viewWidth - CreateAccountAndBlogTextFieldWidth)/2.0; - y = CGRectGetMaxY(_emailField.frame) - 1; - _usernameField.frame = CGRectIntegral(CGRectMake(x, y, CreateAccountAndBlogTextFieldWidth, CreateAccountAndBlogTextFieldHeight)); - - // Layout Password - x = (_viewWidth - CreateAccountAndBlogTextFieldWidth)/2.0; - y = CGRectGetMaxY(_usernameField.frame) - 1; - _passwordField.frame = CGRectIntegral(CGRectMake(x, y, CreateAccountAndBlogTextFieldWidth, CreateAccountAndBlogTextFieldHeight)); - - // Layout Site Address - x = (_viewWidth - CreateAccountAndBlogTextFieldWidth)/2.0; - y = CGRectGetMaxY(_passwordField.frame) - 1; - _siteAddressField.frame = CGRectIntegral(CGRectMake(x, y, CreateAccountAndBlogTextFieldWidth, CreateAccountAndBlogTextFieldHeight)); - - // Layout WordPressCom Label - [_siteAddressWPComLabel sizeToFit]; - CGSize wordPressComLabelSize = _siteAddressWPComLabel.frame.size; - wordPressComLabelSize.height = _siteAddressField.frame.size.height - 10; - wordPressComLabelSize.width += 10; - _siteAddressWPComLabel.frame = CGRectMake(_siteAddressField.frame.size.width - wordPressComLabelSize.width - 5, (_siteAddressField.frame.size.height - wordPressComLabelSize.height) / 2 - 1, wordPressComLabelSize.width, wordPressComLabelSize.height); - - // Layout Create Account Button - x = (_viewWidth - CreateAccountAndBlogButtonWidth)/2.0; - y = CGRectGetMaxY(_siteAddressField.frame) + CreateAccountAndBlogStandardOffset; - _createAccountButton.frame = CGRectIntegral(CGRectMake(x, y, CreateAccountAndBlogButtonWidth, CreateAccountAndBlogButtonHeight)); - - // Layout Terms of Service - CGFloat TOSSingleLineHeight = [@"WordPress" sizeWithAttributes:@{NSFontAttributeName:_TOSLabel.font}].height; - CGSize TOSLabelSize = [_TOSLabel.text boundingRectWithSize:CGSizeMake(CreateAccountAndBlogMaxTextWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: _TOSLabel.font} context:nil].size; - // If the terms of service don't fit on two lines, then shrink the font to make sure the entire terms of service is visible. - if (TOSLabelSize.height > 2*TOSSingleLineHeight) { - _TOSLabel.font = [WPNUXUtility tosLabelSmallerFont]; - TOSLabelSize = [_TOSLabel.text boundingRectWithSize:CGSizeMake(CreateAccountAndBlogMaxTextWidth, CGFLOAT_MAX) options:NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName: _TOSLabel.font} context:nil].size; - } - x = (_viewWidth - TOSLabelSize.width)/2.0; - y = CGRectGetMaxY(_createAccountButton.frame) + 0.5 * CreateAccountAndBlogStandardOffset; - _TOSLabel.frame = CGRectIntegral(CGRectMake(x, y, TOSLabelSize.width, TOSLabelSize.height)); - - NSArray *controls = @[_titleLabel, _emailField, _usernameField, _passwordField, _TOSLabel, _createAccountButton, _siteAddressField]; - [WPNUXUtility centerViews:controls withStartingView:_titleLabel andEndingView:_TOSLabel forHeight:_viewHeight]; -} - - -- (void)helpButtonAction -{ - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXCreateAccountClickedHelp]; - SupportViewController *supportViewController = [[SupportViewController alloc] init]; - UINavigationController *nc = [[UINavigationController alloc] initWithRootViewController:supportViewController]; - nc.navigationBar.translucent = NO; - nc.modalPresentationStyle = UIModalPresentationFormSheet; - [self.navigationController presentViewController:nc animated:YES completion:nil]; -} - -- (void)cancelButtonAction -{ - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXCreateAccountClickedCancel]; - [self.navigationController popViewControllerAnimated:YES]; -} - -- (void)viewWasTapped:(UITapGestureRecognizer *)gestureRecognizer -{ - [self.view endEditing:YES]; -} - -- (void)createAccountButtonAction -{ - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXCreateAccountClickedAccountPageNext]; - - [self.view endEditing:YES]; - - if (![self fieldsValid]) { - [self showAllErrors]; - return; - } else { - // Check if user changed default URL and if so track the stat for it. - if (![_siteAddressField.text isEqualToString:_defaultSiteUrl]) { - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXCreateAccountChangedDefaultURL]; - } - - [self createUserAndSite]; - } -} - -- (void)TOSLabelWasTapped -{ - WPWebViewController *webViewController = [[WPWebViewController alloc] init]; - [webViewController setUrl:[NSURL URLWithString:@"http://en.wordpress.com/tos/"]]; - [self.navigationController setNavigationBarHidden:NO animated:NO]; - [self.navigationController pushViewController:webViewController animated:NO]; -} - -- (void)keyboardWillShow:(NSNotification *)notification -{ - NSDictionary *keyboardInfo = notification.userInfo; - CGFloat animationDuration = [[keyboardInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]; - CGRect keyboardFrame = [[keyboardInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue]; - keyboardFrame = [self.view convertRect:keyboardFrame fromView:nil]; - - _keyboardOffset = (CGRectGetMaxY(_createAccountButton.frame) - CGRectGetMinY(keyboardFrame)) + 0.5 * CreateAccountAndBlogStandardOffset; - - // make sure keyboard offset is greater than 0, otherwise do not move controls - if (_keyboardOffset < 0) { - _keyboardOffset = 0; - return; - } - - [UIView animateWithDuration:animationDuration animations:^{ - for (UIControl *control in [self controlsToMoveDuringKeyboardTransition]) { - CGRect frame = control.frame; - frame.origin.y -= _keyboardOffset; - control.frame = frame; - } - - for (UIControl *control in [self controlsToShowOrHideDuringKeyboardTransition]) { - control.alpha = 0.0; - } - }]; -} - -- (void)keyboardWillHide:(NSNotification *)notification -{ - NSDictionary *keyboardInfo = notification.userInfo; - CGFloat animationDuration = [[keyboardInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] floatValue]; - - [UIView animateWithDuration:animationDuration animations:^{ - for (UIControl *control in [self controlsToMoveDuringKeyboardTransition]) { - CGRect frame = control.frame; - frame.origin.y += _keyboardOffset; - control.frame = frame; - } - - for (UIControl *control in [self controlsToShowOrHideDuringKeyboardTransition]) { - control.alpha = 1.0; - } - }]; -} - -- (void)keyboardDidShow -{ - _keyboardVisible = YES; -} - -- (void)keyboardDidHide -{ - _keyboardVisible = NO; -} - -- (NSArray *)controlsToMoveDuringKeyboardTransition -{ - return @[_usernameField, _emailField, _passwordField, _createAccountButton, _siteAddressField]; -} - -- (NSArray *)controlsToShowOrHideDuringKeyboardTransition -{ - return @[_titleLabel, _helpButton, _cancelButton, _TOSLabel]; -} - -- (void)displayRemoteError:(NSError *)error -{ - NSString *errorMessage = [error.userInfo objectForKey:WordPressComApiErrorMessageKey]; - [self showError:errorMessage]; -} - -- (BOOL)fieldsFilled -{ - return [self isEmailedFilled] && [self isUsernameFilled] && [self isPasswordFilled] && [self isSiteAddressFilled]; -} - -- (BOOL)isEmailedFilled -{ - return ([[_emailField.text trim] length] != 0); -} - -- (BOOL)isUsernameFilled -{ - return ([[_usernameField.text trim] length] != 0); -} - -- (BOOL)isUsernameUnderFiftyCharacters -{ - return [[_usernameField.text trim] length] <= 50; -} - -- (BOOL)isPasswordFilled -{ - return ([[_passwordField.text trim] length] != 0); -} - -- (BOOL)isSiteAddressFilled -{ - return ([[_siteAddressField.text trim] length] != 0); -} - -- (BOOL)fieldsValid -{ - return [self fieldsFilled] && [self isUsernameUnderFiftyCharacters]; -} - -- (NSString *)generateSiteTitleFromUsername:(NSString *)username { - - // Currently, we set the title of a new site to the username of the account. - // Another possibility would be to name the site "username's blog", which is - // why this has been placed in a separate method. - return username; -} - -- (void)showAllErrors -{ - if (![self isUsernameUnderFiftyCharacters]) { - [self showError:NSLocalizedString(@"Username must be less than fifty characters.", nil)]; - } else { - [self showFieldsNotFilledError]; - } -} - -- (void)showFieldsNotFilledError -{ - [self showError:NSLocalizedString(@"Please fill out all the fields", nil)]; -} - -- (NSString *)getSiteAddressWithoutWordPressDotCom -{ - NSRegularExpression *dotCom = [NSRegularExpression regularExpressionWithPattern:@"\\.wordpress\\.com/?$" options:NSRegularExpressionCaseInsensitive error:nil]; - return [dotCom stringByReplacingMatchesInString:_siteAddressField.text options:0 range:NSMakeRange(0, [_siteAddressField.text length]) withTemplate:@""]; -} - -- (void)showError:(NSString *)message -{ - WPWalkthroughOverlayView *overlayView = [[WPWalkthroughOverlayView alloc] initWithFrame:self.view.bounds]; - overlayView.overlayTitle = NSLocalizedString(@"Error", nil); - overlayView.overlayDescription = message; - overlayView.dismissCompletionBlock = ^(WPWalkthroughOverlayView *overlayView){ - [overlayView dismiss]; - }; - [self.view addSubview:overlayView]; -} - -- (void)setAuthenticating:(BOOL)authenticating -{ - _authenticating = authenticating; - _createAccountButton.enabled = !authenticating; - [_createAccountButton showActivityIndicator:authenticating]; -} - -- (void)createUserAndSite -{ - if (_authenticating) { - return; - } - - [self setAuthenticating:YES]; - - // The site must be validated prior to making an account. Without validation, - // the situation could exist where a user account is created, but the site creation - // fails. - WPAsyncBlockOperation *siteValidation = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation) { - void (^blogValidationSuccess)(id) = ^(id responseObject) { - [operation didSucceed]; - }; - void (^blogValidationFailure)(NSError *) = ^(NSError *error) { - [operation didFail]; - [self setAuthenticating:NO]; - [self displayRemoteError:error]; - }; - - NSNumber *languageId = [_currentLanguage objectForKey:@"lang_id"]; - [[WordPressComApi sharedApi] validateWPComBlogWithUrl:[self getSiteAddressWithoutWordPressDotCom] - andBlogTitle:[self generateSiteTitleFromUsername:_usernameField.text] - andLanguageId:languageId - success:blogValidationSuccess - failure:blogValidationFailure]; - }]; - - WPAsyncBlockOperation *userCreation = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ - void (^createUserSuccess)(id) = ^(id responseObject){ - [operation didSucceed]; - }; - void (^createUserFailure)(NSError *) = ^(NSError *error) { - DDLogError(@"Failed creating user: %@", error); - [operation didFail]; - [self setAuthenticating:NO]; - [self displayRemoteError:error]; - }; - - [[WordPressComApi anonymousApi] createWPComAccountWithEmail:_emailField.text - andUsername:_usernameField.text - andPassword:_passwordField.text - success:createUserSuccess - failure:createUserFailure]; - - }]; - WPAsyncBlockOperation *userSignIn = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ - void (^signInSuccess)(NSString *authToken) = ^(NSString *authToken){ - _account = [WPAccount createOrUpdateWordPressComAccountWithUsername:_usernameField.text password:_passwordField.text authToken:authToken]; - if (![WPAccount defaultWordPressComAccount]) { - [WPAccount setDefaultWordPressComAccount:_account]; - } - [operation didSucceed]; - }; - void (^signInFailure)(NSError *) = ^(NSError *error) { - DDLogError(@"Failed signing in user: %@", error); - // We've hit a strange failure at this point, the user has been created successfully but for some reason - // we are unable to sign in and proceed - [operation didFail]; - [self setAuthenticating:NO]; - [self displayRemoteError:error]; - }; - - - WordPressComOAuthClient *client = [WordPressComOAuthClient client]; - [client authenticateWithUsername:_usernameField.text - password:_passwordField.text - success:signInSuccess - failure:signInFailure]; - }]; - - WPAsyncBlockOperation *blogCreation = [WPAsyncBlockOperation operationWithBlock:^(WPAsyncBlockOperation *operation){ - void (^createBlogSuccess)(id) = ^(id responseObject){ - [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXCreateAccountCreatedAccount]; - [operation didSucceed]; -<<<<<<< HEAD - - NSMutableDictionary *blogOptions = [[responseObject dictionaryForKey:@"blog_details"] mutableCopy]; - if ([blogOptions objectForKey:@"blogname"]) { - [blogOptions setObject:[blogOptions objectForKey:@"blogname"] forKey:@"blogName"]; - [blogOptions removeObjectForKey:@"blogname"]; -======= - [self setAuthenticating:NO]; - if (self.onCreatedUser) { - self.onCreatedUser(_usernameField.text, _passwordField.text); ->>>>>>> refs/heads/develop - } - Blog *blog = [_account findOrCreateBlogFromDictionary:blogOptions withContext:_account.managedObjectContext]; - [blog dataSave]; - [blog syncBlogWithSuccess:nil failure:nil]; - [SVProgressHUD dismiss]; - [self dismissViewControllerAnimated:YES completion:nil]; - }; - void (^createBlogFailure)(NSError *error) = ^(NSError *error) { -<<<<<<< HEAD - DDLogError(@"Failed creating blog: %@", error); - [SVProgressHUD dismiss]; -======= - [self setAuthenticating:NO]; ->>>>>>> refs/heads/develop - [operation didFail]; - [self displayRemoteError:error]; - }; - - NSNumber *languageId = [_currentLanguage objectForKey:@"lang_id"]; - [[_account restApi] createWPComBlogWithUrl:[self getSiteAddressWithoutWordPressDotCom] - andBlogTitle:[self generateSiteTitleFromUsername:_usernameField.text] - andLanguageId:languageId - andBlogVisibility:WordPressComApiBlogVisibilityPublic - success:createBlogSuccess - failure:createBlogFailure]; - }]; - - [blogCreation addDependency:userSignIn]; - [userSignIn addDependency:userCreation]; -<<<<<<< HEAD - - [SVProgressHUD showWithStatus:NSLocalizedString(@"Creating User and Site", nil) maskType:SVProgressHUDMaskTypeBlack]; - -======= - [userCreation addDependency:siteValidation]; - - [_operationQueue addOperation:siteValidation]; ->>>>>>> refs/heads/develop - [_operationQueue addOperation:userCreation]; - [_operationQueue addOperation:userSignIn]; - [_operationQueue addOperation:blogCreation]; -} - -@end diff --git a/WordPress/Classes/SettingsViewController.m.orig b/WordPress/Classes/SettingsViewController.m.orig deleted file mode 100644 index 0bec63054e16..000000000000 --- a/WordPress/Classes/SettingsViewController.m.orig +++ /dev/null @@ -1,455 +0,0 @@ -/* - * SettingsViewController.m - * - * Copyright (c) 2013 WordPress. All rights reserved. - * - * Licensed under GNU General Public License 2.0. - * Some rights reserved. See license.txt - */ - -/* - - Settings contents: - - - Blogs list - - Add blog - - Edit/Delete - - WordPress.com account - - Sign out / Sign in - - Media Settings - - Image Resize - - Video API - - Video Quality - - Video Content - - Info - - Version - - About - - Extra debug - - */ - -#import "SettingsViewController.h" -#import "WordPressComApi.h" -#import "AboutViewController.h" -#import "SettingsPageViewController.h" -#import "NotificationSettingsViewController.h" -#import "Blog+Jetpack.h" -#import "LoginViewController.h" -#import "SupportViewController.h" -#import "WPAccount.h" -#import "WPTableViewSectionHeaderView.h" -<<<<<<< HEAD -#import "ManageBlogsViewController.h" -======= -#import "AddUsersBlogsViewController.h" -#import "SupportViewController.h" -#import "ContextManager.h" ->>>>>>> refs/heads/develop - -typedef enum { - SettingsSectionWpcom = 0, - SettingsSectionMedia, - SettingsSectionInfo, - SettingsSectionCount -} SettingsSection; - -CGFloat const blavatarImageViewSize = 43.f; - -@interface SettingsViewController () - -@property (nonatomic, strong) NSArray *mediaSettingsArray; -@property (nonatomic, strong) UIBarButtonItem *doneButton; - -@end - -@implementation SettingsViewController - -- (void)dealloc { - [[NSNotificationCenter defaultCenter] removeObserver:self]; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - - self.title = NSLocalizedString(@"Settings", @"App Settings"); - self.doneButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Done", @"") style:[WPStyleGuide barButtonStyleForBordered] target:self action:@selector(dismiss)]; - self.navigationItem.rightBarButtonItem = self.doneButton; - - [[NSNotificationCenter defaultCenter] addObserverForName:WPAccountDefaultWordPressComAccountChangedNotification object:nil queue:nil usingBlock:^(NSNotification *note) { - NSMutableIndexSet *sections = [NSMutableIndexSet indexSet]; - [sections addIndex:SettingsSectionWpcom]; - [self.tableView reloadSections:sections withRowAnimation:UITableViewRowAnimationFade]; - }]; - - [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - [self.navigationController setNavigationBarHidden:NO animated:animated]; - [self.tableView reloadData]; -} - -#pragma mark - Custom Getter - -- (NSArray *)mediaSettingsArray { - if (_mediaSettingsArray) { - return _mediaSettingsArray; - } - - // Construct the media data to mimick how it would appear if a settings bundle plist was loaded - // into an NSDictionary - // Our settings bundle stored numeric values as strings so we use strings here for backward compatibility. - NSDictionary *imageResizeDict = [NSDictionary dictionaryWithObjectsAndKeys:@"0", @"DefaultValue", - @"media_resize_preference", @"Key", - NSLocalizedString(@"Image Quality", @""), @"Title", - [NSArray arrayWithObjects:NSLocalizedString(@"Always Ask", @"Always Ask (ask for size on every upload) - Image Quality setting"), - NSLocalizedString(@"Small", @"Small - Image Quality setting"), - NSLocalizedString(@"Medium", @"Medium - Image Quality setting"), - NSLocalizedString(@"Large", @"Large - Image Quality setting"), - NSLocalizedString(@"Original Size", @"Original (uncompressed) - Image Quality setting"), nil], @"Titles", - [NSArray arrayWithObjects:@"0",@"1",@"2",@"3",@"4", nil], @"Values", - NSLocalizedString(@"Set which size images should be uploaded in.", @""), @"Info", - nil]; - - NSDictionary *videoQualityDict = [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"DefaultValue", - @"video_quality_preference", @"Key", - NSLocalizedString(@"Video Quality", @""), @"Title", - [NSArray arrayWithObjects:NSLocalizedString(@"Original Size", @"Video quality - uncompressed original size for the device"), - NSLocalizedString(@"Medium (480p)", @"Video quality - medium quality, 480p"), - NSLocalizedString(@"Default (360p)", @"Video quality - default size, 360p"), - NSLocalizedString(@"Low (144p)", @"Video quality - low quality, 144p"), nil], @"Titles", - [NSArray arrayWithObjects:@"0", @"3", @"1", @"2", nil], @"Values", - NSLocalizedString(@"Choose the quality at which video should be uploaded when inserting into posts.", @""), @"Info", - nil]; - - NSDictionary *videoContentDict = [NSDictionary dictionaryWithObjectsAndKeys:@"0", @"DefaultValue", - @"video_html_preference", @"Key", - NSLocalizedString(@"Video Content", @""), @"Title", - [NSArray arrayWithObjects:@"HTML 5",@"HTML 4", nil ], @"Titles", - [NSArray arrayWithObjects:@"0", @"1", nil], @"Values", - NSLocalizedString(@"Set which HTML standard video should conform to when added to a post.", @""), @"Info", - nil]; - _mediaSettingsArray = [NSArray arrayWithObjects:imageResizeDict, videoQualityDict, videoContentDict, nil]; - return _mediaSettingsArray; -} - -- (void)dismiss { - [self dismissViewControllerAnimated:YES completion:nil]; -} - -- (void)maskImageView:(UIImageView *)imageView corner:(UIRectCorner)corner { - if (IS_IOS7) { - // We don't want this effect in iOS7 - return; - } - - CGRect frame = CGRectMake(0.0, 0.0, 43.0, 43.0); - UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:frame - byRoundingCorners:corner cornerRadii:CGSizeMake(7.0f, 7.0f)]; - CAShapeLayer *maskLayer = [CAShapeLayer layer]; - maskLayer.frame = frame; - maskLayer.path = path.CGPath; - imageView.layer.mask = maskLayer; -} - -- (BOOL)supportsNotifications { - return nil != [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; -} - -- (BOOL)supportsManageBlogs { - return [[[WPAccount defaultWordPressComAccount] blogs] count] > 0; -} - -#pragma mark - Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return [self.tableView isEditing] ? 1 : SettingsSectionCount; -} - -// The Sign Out row in Wpcom section can change, so identify it dynamically -- (NSInteger)rowForSignOut { - NSInteger rowForSignOut = 1; - if ([self supportsNotifications]) { - rowForSignOut += 1; - } - if ([self supportsManageBlogs]) { - rowForSignOut += 1; - } - return rowForSignOut; -} - -- (NSInteger)rowForNotifications { - if ([self supportsNotifications]) { - return [self supportsManageBlogs] ? 2 : 1; - } - return -1; -} - -- (NSInteger)rowForManageBlogs { - return [self supportsManageBlogs] ? 1 : -1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - switch (section) { - case SettingsSectionWpcom: - if ([WPAccount defaultWordPressComAccount]) { - return [self rowForSignOut] + 1; - } else { - return 1; - } - - case SettingsSectionMedia: - return [self.mediaSettingsArray count]; - - case SettingsSectionInfo: - return 3; - - default: - return 0; - } -} - -- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section { - WPTableViewSectionHeaderView *header = [[WPTableViewSectionHeaderView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 0)]; - header.title = [self titleForHeaderInSection:section]; - header.leftMarginPercent = 0; - return header; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { - NSString *title = [self titleForHeaderInSection:section]; - return [WPTableViewSectionHeaderView heightForTitle:title andWidth:CGRectGetWidth(self.view.bounds)]; -} - -- (NSString *)titleForHeaderInSection:(NSInteger)section { - if (section == SettingsSectionWpcom) { - return NSLocalizedString(@"WordPress.com", @""); - - } else if (section == SettingsSectionMedia) { - return NSLocalizedString(@"Media", @"Title label for the media settings section in the app settings"); - - } else if (section == SettingsSectionInfo) { - return NSLocalizedString(@"App Info", @"Title label for the application information section in the app settings"); - } - - return nil; -} - - -- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { - cell.textLabel.textAlignment = NSTextAlignmentLeft; - cell.accessoryType = UITableViewCellAccessoryNone; - cell.accessoryView = nil; - - if (indexPath.section == SettingsSectionWpcom) { - if ([WPAccount defaultWordPressComAccount]) { - if (indexPath.row == 0) { - cell.textLabel.text = NSLocalizedString(@"Username", @""); - cell.detailTextLabel.text = [[WPAccount defaultWordPressComAccount] username]; - cell.detailTextLabel.textColor = [UIColor UIColorFromHex:0x888888]; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - cell.accessibilityIdentifier = @"wpcom-username"; - } else if (indexPath.row == [self rowForManageBlogs]) { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.text = NSLocalizedString(@"Manage Blogs", @""); - cell.accessibilityIdentifier = @"wpcom-manage-blogs"; - } else if (indexPath.row == [self rowForNotifications]) { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.text = NSLocalizedString(@"Manage Notifications", @""); - cell.accessibilityIdentifier = @"wpcom-manage-notifications"; - } else { - cell.textLabel.textAlignment = NSTextAlignmentCenter; - cell.textLabel.text = NSLocalizedString(@"Sign Out", @"Sign out from WordPress.com"); - cell.accessibilityIdentifier = @"wpcom-sign-out"; - } - } else { - cell.textLabel.textAlignment = NSTextAlignmentCenter; - cell.textLabel.text = NSLocalizedString(@"Sign In", @"Sign in to WordPress.com"); - cell.accessibilityIdentifier = @"wpcom-sign-in"; - cell.selectionStyle = UITableViewCellSelectionStyleBlue; - } - - } else if (indexPath.section == SettingsSectionMedia){ - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - - NSDictionary *dict = self.mediaSettingsArray[indexPath.row]; - cell.textLabel.text = dict[@"Title"]; - NSString *key = dict[@"Key"]; - NSString *currentVal = [[NSUserDefaults standardUserDefaults] objectForKey:key]; - if (currentVal == nil) { - currentVal = dict[@"DefaultValue"]; - } - - NSArray *values = [dict objectForKey:@"Values"]; - NSInteger index = [values indexOfObject:currentVal]; - NSArray *titles = [dict objectForKey:@"Titles"]; - cell.detailTextLabel.text = titles[index]; - - } else if (indexPath.section == SettingsSectionInfo) { - if (indexPath.row == 0) { - // App Version - cell.textLabel.text = NSLocalizedString(@"Version", @""); - NSString *appversion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; -#if DEBUG - appversion = [appversion stringByAppendingString:@" (DEV)"]; -#endif - cell.detailTextLabel.text = appversion; - cell.selectionStyle = UITableViewCellSelectionStyleNone; - - } else if (indexPath.row == 1) { - // About - cell.textLabel.text = NSLocalizedString(@"About", @""); - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - - } else if (indexPath.row == 2) { - // Settings - cell.textLabel.text = NSLocalizedString(@"Support", @""); - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - } - } -} - -- (UITableViewCell *)cellForIndexPath:(NSIndexPath *)indexPath { - NSString *cellIdentifier = @"Cell"; - UITableViewCellStyle cellStyle = UITableViewCellStyleDefault; - - switch (indexPath.section) { - case SettingsSectionWpcom: - if ([WPAccount defaultWordPressComAccount] && indexPath.row == 0) { - cellIdentifier = @"WpcomUsernameCell"; - cellStyle = UITableViewCellStyleValue1; - } else { - cellIdentifier = @"WpcomCell"; - cellStyle = UITableViewCellStyleDefault; - } - break; - - case SettingsSectionMedia: - cellIdentifier = @"Media"; - cellStyle = UITableViewCellStyleValue1; - break; - - case SettingsSectionInfo: - if (indexPath.row == 0) { - cellIdentifier = @"InfoCell"; - cellStyle = UITableViewCellStyleValue1; - } - break; - default: - break; - } - - UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:cellIdentifier]; - if (cell == nil) { - cell = [[UITableViewCell alloc] initWithStyle:cellStyle reuseIdentifier:cellIdentifier]; - } - - return cell; -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [self cellForIndexPath:indexPath]; - [WPStyleGuide configureTableViewCell:cell]; - [self configureCell:cell atIndexPath:indexPath]; - - BOOL isSignInCell = NO; - if (![[WordPressComApi sharedApi] hasCredentials]) { - isSignInCell = indexPath.section == SettingsSectionWpcom && indexPath.row == 0; - } - - BOOL isSignOutCell = indexPath.section == SettingsSectionWpcom && indexPath.row == [self rowForSignOut]; - if (isSignOutCell || isSignInCell) { - [WPStyleGuide configureTableViewActionCell:cell]; - } - - return cell; -} - - -#pragma mark - Table view delegate - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [tableView deselectRowAtIndexPath:indexPath animated:YES]; - - if (indexPath.section == SettingsSectionWpcom) { - if ([WPAccount defaultWordPressComAccount]) { - if (indexPath.row == [self rowForSignOut]) { - [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedSignOutOfDotCom]; - - // Present the Sign out ActionSheet - NSString *signOutTitle = NSLocalizedString(@"You are logged in as %@", @""); - signOutTitle = [NSString stringWithFormat:signOutTitle, [[WPAccount defaultWordPressComAccount] username]]; - UIActionSheet *actionSheet; - actionSheet = [[UIActionSheet alloc] initWithTitle:signOutTitle - delegate:self - cancelButtonTitle:NSLocalizedString(@"Cancel", @"") - destructiveButtonTitle:NSLocalizedString(@"Sign Out", @"")otherButtonTitles:nil, nil ]; - actionSheet.actionSheetStyle = UIActionSheetStyleDefault; - [actionSheet showInView:self.view]; - } else if (indexPath.row == [self rowForManageBlogs]) { - ManageBlogsViewController *manageBlogsViewController = [[ManageBlogsViewController alloc] initWithAccount:[WPAccount defaultWordPressComAccount]]; - [self.navigationController pushViewController:manageBlogsViewController animated:YES]; - } else if (indexPath.row == [self rowForNotifications]) { - [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedManageNotifications]; - - NotificationSettingsViewController *notificationSettingsViewController = [[NotificationSettingsViewController alloc] initWithStyle:UITableViewStyleGrouped]; - [self.navigationController pushViewController:notificationSettingsViewController animated:YES]; - } - } else { - [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedSignIntoDotCom]; - - LoginViewController *loginViewController = [[LoginViewController alloc] init]; - loginViewController.onlyDotComAllowed = YES; - loginViewController.dismissBlock = ^{ - [self.navigationController popToViewController:self animated:YES]; - }; - [self.navigationController pushViewController:loginViewController animated:YES]; - } - - } else if (indexPath.section == SettingsSectionMedia) { - if (indexPath.row == 0) { - [WPMobileStats trackEventForWPCom:StatsEventSettingsMediaClickedImageResize]; - } else if (indexPath.row == 1) { - [WPMobileStats trackEventForWPCom:StatsEventSettingsMediaClickedVideoQuality]; - } else if (indexPath.row == 2) { - [WPMobileStats trackEventForWPCom:StatsEventSettingsMediaClickedVideoContent]; - } - - NSDictionary *dict = [self.mediaSettingsArray objectAtIndex:indexPath.row]; - SettingsPageViewController *controller = [[SettingsPageViewController alloc] initWithDictionary:dict]; - [self.navigationController pushViewController:controller animated:YES]; - - } else if (indexPath.section == SettingsSectionInfo) { - if (indexPath.row == 1) { - [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedAbout]; - - AboutViewController *aboutViewController = [[AboutViewController alloc] initWithNibName:@"AboutViewController" bundle:nil]; - [self.navigationController pushViewController:aboutViewController animated:YES]; - } else if (indexPath.row == 2) { - // Support Page - SupportViewController *supportViewController = [[SupportViewController alloc] init]; - [self.navigationController pushViewController:supportViewController animated:YES]; - } - } -} - -#pragma mark - -#pragma mark Action Sheet Delegate Methods - -- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { - if (buttonIndex == 0) { - [WPMobileStats trackEventForWPCom:StatsEventSettingsSignedOutOfDotCom]; - - // Sign out - [WPAccount removeDefaultWordPressComAccount]; - [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:SettingsSectionWpcom] withRowAnimation:UITableViewRowAnimationFade]; - - // Remove defaults - [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_users_blogs"]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_user_id"]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_users_prefered_blog_id"]; - } -} - -@end diff --git a/WordPress/Classes/WPcomLoginViewController.m.orig b/WordPress/Classes/WPcomLoginViewController.m.orig deleted file mode 100644 index 9d6bd05ca0f7..000000000000 --- a/WordPress/Classes/WPcomLoginViewController.m.orig +++ /dev/null @@ -1,379 +0,0 @@ -// -// WPcomLoginViewController.m -// WordPress -// -// Created by Chris Boyd on 7/19/10. -// - -#import "WPcomLoginViewController.h" - -#import - -#import "UITableViewTextFieldCell.h" -#import "UITableViewActivityCell.h" -#import "WPAccount.h" -#import "WordPressComApi.h" -#import "ReachabilityUtils.h" -#import "WPTableViewSectionFooterView.h" - -@interface WPcomLoginViewController () { - UITableViewTextFieldCell *loginCell, *passwordCell; -} -@property (nonatomic, assign) BOOL isCancellable; -@property (nonatomic, assign) BOOL dismissWhenFinished; -@property (nonatomic, strong) NSString *footerText, *buttonText; -@property (nonatomic, assign) BOOL isSigningIn; -@property (nonatomic, strong) WordPressComApi *wpComApi; -- (void)signIn:(id)sender; -@end - - -@implementation WPcomLoginViewController - -@synthesize footerText, buttonText, isSigningIn, isCancellable, predefinedUsername; -@synthesize delegate; -@synthesize wpComApi = _wpComApi; - -+ (void)presentLoginScreen { - UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController]; - WPcomLoginViewController *loginViewController = [[WPcomLoginViewController alloc] initWithStyle:UITableViewStyleGrouped]; - loginViewController.isCancellable = YES; - loginViewController.dismissWhenFinished = YES; - UINavigationController *navController = [[UINavigationController alloc] initWithRootViewController:loginViewController]; - navController.navigationBar.translucent = NO; - navController.modalPresentationStyle = UIModalPresentationFormSheet; - navController.modalTransitionStyle = UIModalTransitionStyleCoverVertical; - [rootViewController presentViewController:navController animated:YES completion:nil]; -} - -#pragma mark - -#pragma mark View lifecycle - -- (void)viewDidLoad { - DDLogInfo(@"%@ %@", self, NSStringFromSelector(_cmd)); - [super viewDidLoad]; - - [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; - - self.wpComApi = [WordPressComApi sharedApi]; - self.footerText = @" "; - self.buttonText = NSLocalizedString(@"Sign In", @""); - self.navigationItem.title = NSLocalizedString(@"Sign In", @""); - - if (isCancellable) { - UIBarButtonItem *barButton = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Cancel", nil) - style:UIBarButtonItemStylePlain - target:self - action:@selector(cancel:)]; - self.navigationItem.leftBarButtonItem = barButton; - } - - // Setup WPcom table header - CGRect headerFrame = CGRectMake(0, 0, 320, 70); - CGRect logoFrame = CGRectMake(40, 20, 229, 43); - NSString *logoFile = @"logo_wpcom.png"; - if(IS_IPAD) { - logoFile = @"logo_wpcom@2x.png"; - logoFrame = CGRectMake(150, 20, 229, 43); - } - - UIView *headerView = [[UIView alloc] initWithFrame:headerFrame]; - UIImageView *logo = [[UIImageView alloc] initWithImage:[UIImage imageNamed:logoFile]]; - logo.frame = logoFrame; - [headerView addSubview:logo]; - self.tableView.tableHeaderView = headerView; - - if(IS_IPAD) - self.tableView.backgroundView = nil; -} - - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - isSigningIn = NO; -} - - -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { - return [super shouldAutorotateToInterfaceOrientation:interfaceOrientation]; -} - - -#pragma mark - -#pragma mark Table view data source - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - // Return the number of sections. - return 2; -} - - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - if(section == 0) - return 2; - else - return 1; -} - - -- (NSString *)titleForFooterInSection:(NSInteger)section { - if(section == 0) - return footerText; - else - return @""; -} - -- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section -{ - WPTableViewSectionFooterView *header = [[WPTableViewSectionFooterView alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), 0)]; - header.title = [self titleForFooterInSection:section]; - return header; -} - -- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section -{ - NSString *title = [self titleForFooterInSection:section]; - return [WPTableViewSectionFooterView heightForTitle:title andWidth:CGRectGetWidth(self.view.bounds)]; -} - - -// Customize the appearance of table view cells. -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = nil; - - if(indexPath.section == 1) { - UITableViewActivityCell *activityCell = nil; - NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"UITableViewActivityCell" owner:nil options:nil]; - for(id currentObject in topLevelObjects) - { - if([currentObject isKindOfClass:[UITableViewActivityCell class]]) - { - activityCell = (UITableViewActivityCell *)currentObject; - break; - } - } - if(isSigningIn) { - [activityCell.spinner startAnimating]; - self.buttonText = NSLocalizedString(@"Signing In...", @""); - } - else { - [activityCell.spinner stopAnimating]; - self.buttonText = NSLocalizedString(@"Sign In", @""); - } - - activityCell.textLabel.text = buttonText; - if (isSigningIn) { - activityCell.selectionStyle = UITableViewCellSelectionStyleNone; - } else { - activityCell.selectionStyle = UITableViewCellSelectionStyleBlue; - } - [WPStyleGuide configureTableViewActionCell:activityCell]; - cell = activityCell; - } else { - if ([indexPath row] == 0) { - if (loginCell == nil) { - loginCell = [[UITableViewTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"TextCell"]; - loginCell.textField.text = [[WPAccount defaultWordPressComAccount] username]; - } - loginCell.textLabel.text = NSLocalizedString(@"Username", @""); - loginCell.textField.placeholder = NSLocalizedString(@"WordPress.com username", @""); - loginCell.textField.keyboardType = UIKeyboardTypeEmailAddress; - loginCell.textField.returnKeyType = UIReturnKeyNext; - loginCell.textField.tag = 0; - loginCell.textField.delegate = self; - if( self.predefinedUsername ) - loginCell.textField.text = self.predefinedUsername; - if(isSigningIn) - [loginCell.textField resignFirstResponder]; - [WPStyleGuide configureTableViewTextCell:loginCell]; - cell = loginCell; - } - else { - if (passwordCell == nil) { - passwordCell = [[UITableViewTextFieldCell alloc] initWithStyle:UITableViewCellStyleDefault - reuseIdentifier:@"TextCell"]; - } - passwordCell.textLabel.text = NSLocalizedString(@"Password", @""); - passwordCell.textField.placeholder = NSLocalizedString(@"WordPress.com password", @""); - passwordCell.textField.keyboardType = UIKeyboardTypeDefault; - passwordCell.textField.secureTextEntry = YES; - passwordCell.textField.tag = 1; - passwordCell.textField.delegate = self; - if(isSigningIn) - [passwordCell.textField resignFirstResponder]; - [WPStyleGuide configureTableViewTextCell:passwordCell]; - cell = passwordCell; - } - } - - return cell; -} - - -#pragma mark - -#pragma mark Table view delegate - -- (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [tv deselectRowAtIndexPath:indexPath animated:YES]; - - switch (indexPath.section) { - case 0: - { - UITableViewCell *cell = (UITableViewCell *)[tv cellForRowAtIndexPath:indexPath]; - for(UIView *subview in cell.subviews) { - if([subview isKindOfClass:[UITextField class]] == YES) { - UITextField *tempTextField = (UITextField *)subview; - [tempTextField becomeFirstResponder]; - break; - } - } - break; - } - case 1: - for(int i = 0; i < 2; i++) { - UITableViewCell *cell = (UITableViewCell *)[tv cellForRowAtIndexPath:[NSIndexPath indexPathForRow:i inSection:0]]; - for(UIView *subview in cell.subviews) { - if([subview isKindOfClass:[UITextField class]] == YES) { - UITextField *tempTextField = (UITextField *)subview; - [self textFieldDidEndEditing:tempTextField]; - } - } - } - if([loginCell.textField.text isEqualToString:@""]) { - self.footerText = NSLocalizedString(@"Username is required.", @""); - self.buttonText = NSLocalizedString(@"Sign In", @""); - [tv reloadData]; - } - else if([passwordCell.textField.text isEqualToString:@""]) { - self.footerText = NSLocalizedString(@"Password is required.", @""); - self.buttonText = NSLocalizedString(@"Sign In", @""); - [tv reloadData]; - } - else { - - if (![ReachabilityUtils isInternetReachable]) { - [ReachabilityUtils showAlertNoInternetConnection]; - return; - } - - self.buttonText = NSLocalizedString(@"Signing in...", @""); - - [self signIn:self]; - } - break; - default: - break; - } -} - - -#pragma mark - -#pragma mark UITextField delegate methods - -- (BOOL)textFieldShouldReturn:(UITextField *)textField { - [textField resignFirstResponder]; - - UITableViewCell *cell = nil; - UITextField *nextField = nil; - switch (textField.tag) { - case 0: - [textField endEditing:YES]; - cell = [self.tableView cellForRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:0]]; - if(cell != nil) { - nextField = (UITextField*)[cell viewWithTag:1]; - if(nextField != nil) - [nextField becomeFirstResponder]; - } - break; - case 1: - [self signIn:self]; - break; - } - - return YES; -} - - -- (void)textFieldDidEndEditing:(UITextField *)textField { - UITableViewCell *cell = (UITableViewCell *)[textField superview]; - NSIndexPath *indexPath = [self.tableView indexPathForCell:cell]; - - switch (indexPath.row) { - case 0: - if((textField.text != nil) && ([textField.text isEqualToString:@""])) { - self.footerText = NSLocalizedString(@"Username is required.", @""); - } - else { - textField.text = [[textField.text stringByReplacingOccurrencesOfString:@" " withString:@""] lowercaseString]; - } - break; - case 1: - if((textField.text != nil) && ([textField.text isEqualToString:@""])) { - self.footerText = NSLocalizedString(@"Password is required.", @""); - } - break; - default: - break; - } - - [textField resignFirstResponder]; -} - - -#pragma mark - -#pragma mark Custom methods - -- (void)signIn:(id)sender { - if (isSigningIn) { - return; - } - [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:1]] withRowAnimation:UITableViewRowAnimationNone]; - __weak WPcomLoginViewController *loginController = self; - NSString *username = loginCell.textField.text; - NSString *password = passwordCell.textField.text; - if (![username length] > 0) { - self.footerText = NSLocalizedString(@"Username is required.", @""); - } else if (![password length] > 0) { - self.footerText = NSLocalizedString(@"Password is required.", @""); - } else { - isSigningIn = YES; - self.footerText = @" "; - [self.wpComApi signInWithUsername:username - password:password - success:^{ -<<<<<<< HEAD - WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:nil]; - [WPAccount setDefaultWordPressComAccount:account]; -======= - WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username andPassword:password]; ->>>>>>> refs/heads/develop - [loginController.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:[NSIndexPath indexPathForRow:0 inSection:1]] withRowAnimation:UITableViewRowAnimationNone]; - if (loginController.delegate) { - [loginController.delegate loginController:loginController didAuthenticateWithAccount:account]; - } - if (self.dismissWhenFinished) { - [self dismissViewControllerAnimated:YES completion:nil]; - } - } failure:^(NSError *error) { - DDLogError(@"Login failed with username %@: %@", username, error); - loginController.footerText = NSLocalizedString(@"Sign in failed. Please try again.", @""); - loginController.buttonText = NSLocalizedString(@"Sign In", @""); - loginController.isSigningIn = NO; - [loginController.tableView reloadData]; - }]; - } - [self.tableView reloadData]; -} - - -- (IBAction)cancel:(id)sender { - if (self.delegate) { - [self.delegate loginControllerDidDismiss:self]; - } - if (self.dismissWhenFinished) { - [self dismissViewControllerAnimated:YES completion:nil]; - } -} - -@end diff --git a/WordPress/Classes/WordPressAppDelegate.m.orig b/WordPress/Classes/WordPressAppDelegate.m.orig deleted file mode 100644 index 1ddb888d5536..000000000000 --- a/WordPress/Classes/WordPressAppDelegate.m.orig +++ /dev/null @@ -1,1020 +0,0 @@ -/* - * WordPressAppDelegate.m - * - * Copyright (c) 2013 WordPress. All rights reserved. - * - * Licensed under GNU General Public License 2.0. - * Some rights reserved. See license.txt - */ - -#import -#import -#import -#import "WordPressAppDelegate.h" -#import "Reachability.h" -#import "NSString+Helpers.h" -#import "Media.h" -#import "CameraPlusPickerManager.h" -#import "UIDevice+WordPressIdentifier.h" -#import "WordPressComApi.h" -#import "WordPressComApiCredentials.h" -#import "PocketAPI.h" -#import "WPAccount.h" -#import "SupportViewController.h" -#import "ContextManager.h" -#import "ReaderPostsViewController.h" -#import "NotificationsViewController.h" -#import "BlogListViewController.h" -#import "LoginViewController.h" -#import -#import -#import "NotificationsManager.h" -#import -#import -#import "ContextManager.h" - -#if DEBUG -#import "DDTTYLogger.h" -#import "DDASLLogger.h" -#endif - -int ddLogLevel = LOG_LEVEL_INFO; -NSInteger const UpdateCheckAlertViewTag = 102; - - -@interface WordPressAppDelegate () - -@property (nonatomic, assign) BOOL listeningForBlogChanges; -@property (nonatomic, strong) NotificationsViewController *notificationsViewController; -@property (nonatomic, assign) UIBackgroundTaskIdentifier bgTask; -@property (strong, nonatomic) DDFileLogger *fileLogger; - -@end - -@implementation WordPressAppDelegate - -+ (WordPressAppDelegate *)sharedWordPressApplicationDelegate { - return (WordPressAppDelegate *)[[UIApplication sharedApplication] delegate]; -} - - -#pragma mark - UIApplicationDelegate - -- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { - // Crash reporting, logging, debugging - [self configureHockeySDK]; - [self configureCrashlytics]; - [self configureLogging]; - [self printDebugLaunchInfo]; - [self toggleExtraDebuggingIfNeeded]; - [self removeCredentialsForDebug]; - - // Stats and feedback - [WPMobileStats initializeStats]; - [[GPPSignIn sharedInstance] setClientID:[WordPressComApiCredentials googlePlusClientId]]; - [self checkIfStatsShouldSendAndUpdateCheck]; - [self checkIfFeedbackShouldBeEnabled]; - - // Networking setup - [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES]; - [self setupReachability]; - [self setupUserAgent]; - [self checkWPcomAuthentication]; - [self setupSingleSignOn]; - - [self customizeAppearance]; - - CGRect bounds = [[UIScreen mainScreen] bounds]; - [self.window setFrame:bounds]; - [self.window setBounds:bounds]; // for good measure. - - self.window.backgroundColor = [UIColor blackColor]; - self.window.rootViewController = self.tabBarController; - [self.window makeKeyAndVisible]; - - [self showWelcomeScreenIfNeededAnimated:NO]; - - // Push notifications - [NotificationsManager registerForPushNotifications]; - [NotificationsManager handleNotificationForApplicationLaunch:launchOptions]; - - //listener for XML-RPC errors - //in the future we could put the errors message in a dedicated screen that users can bring to front when samething went wrong, and can take a look at the error msg. - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showNotificationErrorAlert:) name:kXML_RPC_ERROR_OCCURS object:nil]; - - // another notification message came from comments --> CommentUploadFailed - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showNotificationErrorAlert:) name:@"CommentUploadFailed" object:nil]; - - // another notification message came from WPWebViewController - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(showNotificationErrorAlert:) name:@"OpenWebPageFailed" object:nil]; - - // Deferred tasks to speed up app launch - dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{ - [self changeCurrentDirectory]; - [WordPressAppDelegate fixKeychainAccess]; - [[PocketAPI sharedAPI] setConsumerKey:[WordPressComApiCredentials pocketConsumerKey]]; - [self cleanUnusedMediaFileFromTmpDir]; - }); - - return YES; -} - -- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation -{ - if ([[BITHockeyManager sharedHockeyManager].authenticator handleOpenURL:url - sourceApplication:sourceApplication - annotation:annotation]) { - return YES; - } - - if ([[GPPShare sharedInstance] handleURL:url sourceApplication:sourceApplication annotation:annotation]) { - return YES; - } - - if ([[PocketAPI sharedAPI] handleOpenURL:url]) { - return YES; - } - - if ([[CameraPlusPickerManager sharedManager] shouldHandleURLAsCameraPlusPickerCallback:url]) { - /* Note that your application has been in the background and may have been terminated. - * The only CameraPlusPickerManager state that is restored is the pickerMode, which is - * restored to indicate the mode used to pick images. - */ - - /* Handle the callback and notify the delegate. */ - [[CameraPlusPickerManager sharedManager] handleCameraPlusPickerCallback:url usingBlock:^(CameraPlusPickedImages *images) { - DDLogInfo(@"Camera+ returned %@", [images images]); - UIImage *image = [images image]; - UIImageWriteToSavedPhotosAlbum(image, nil, nil, nil); - NSDictionary *userInfo = [NSDictionary dictionaryWithObject:image forKey:@"image"]; - [[NSNotificationCenter defaultCenter] postNotificationName:kCameraPlusImagesNotification object:nil userInfo:userInfo]; - } cancelBlock:^(void) { - DDLogInfo(@"Camera+ picker canceled"); - }]; - return YES; - } - - if ([WordPressApi handleOpenURL:url]) { - return YES; - } - - if (url && [url isKindOfClass:[NSURL class]]) { - NSString *URLString = [url absoluteString]; - DDLogInfo(@"Application launched with URL: %@", URLString); - if ([[url absoluteString] hasPrefix:@"wordpress://wpcom_signup_completed"]) { - NSDictionary *params = [[url query] dictionaryFromQueryString]; - DDLogInfo(@"%@", params); - [[NSNotificationCenter defaultCenter] postNotificationName:@"wpcomSignupNotification" object:nil userInfo:params]; - return YES; - } - } - - return NO; -} - -- (void)applicationWillTerminate:(UIApplication *)application { - DDLogInfo(@"%@ %@", self, NSStringFromSelector(_cmd)); - - [UIApplication sharedApplication].applicationIconBadgeNumber = 0; - [WPMobileStats endSession]; -} - -- (void)applicationDidEnterBackground:(UIApplication *)application { - DDLogInfo(@"%@ %@", self, NSStringFromSelector(_cmd)); - - [WPMobileStats trackEventForWPComWithSavedProperties:StatsEventAppClosed]; - [WPMobileStats pauseSession]; - - // Let the app finish any uploads that are in progress - UIApplication *app = [UIApplication sharedApplication]; - if (_bgTask != UIBackgroundTaskInvalid) { - [app endBackgroundTask:_bgTask]; - _bgTask = UIBackgroundTaskInvalid; - } - - _bgTask = [app beginBackgroundTaskWithExpirationHandler:^{ - // Synchronize the cleanup call on the main thread in case - // the task actually finishes at around the same time. - dispatch_async(dispatch_get_main_queue(), ^{ - if (_bgTask != UIBackgroundTaskInvalid) - { - [app endBackgroundTask:_bgTask]; - _bgTask = UIBackgroundTaskInvalid; - } - }); - }]; -} - -- (void)applicationWillEnterForeground:(UIApplication *)application -{ - [WPMobileStats resumeSession]; -} - -- (void)applicationWillResignActive:(UIApplication *)application { - DDLogInfo(@"%@ %@", self, NSStringFromSelector(_cmd)); -} - -- (void)applicationDidBecomeActive:(UIApplication *)application { - DDLogInfo(@"%@ %@", self, NSStringFromSelector(_cmd)); - - [WPMobileStats recordAppOpenedForEvent:StatsEventAppOpened]; - - // Clear notifications badge and update server - [UIApplication sharedApplication].applicationIconBadgeNumber = 0; - [[WordPressComApi sharedApi] syncPushNotificationInfo]; -} - -#pragma mark - Push Notification delegate - -- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken { - [NotificationsManager registerDeviceToken:deviceToken]; -} - -- (void)application:(UIApplication *)application didFailToRegisterForRemoteNotificationsWithError:(NSError *)error { - [NotificationsManager registrationDidFail:error]; -} - -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo { - WPFLogMethod(); - - [NotificationsManager handleNotification:userInfo forState:application.applicationState completionHandler:nil]; -} - -- (void)application:(UIApplication *)application didReceiveRemoteNotification:(NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler { - WPFLogMethod(); - - [NotificationsManager handleNotification:userInfo forState:[UIApplication sharedApplication].applicationState completionHandler:completionHandler]; -} - - -#pragma mark - Custom methods - -- (void)showWelcomeScreenIfNeededAnimated:(BOOL)animated { - if ([self noBlogsAndNoWordPressDotComAccount]) { - [WordPressAppDelegate wipeAllKeychainItems]; - - LoginViewController *welcomeViewController = [[LoginViewController alloc] init]; - UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:welcomeViewController]; - aNavigationController.navigationBar.translucent = NO; - aNavigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; - aNavigationController.modalPresentationStyle = UIModalPresentationFormSheet; - - UIViewController *presenter = self.window.rootViewController; - if (presenter.presentedViewController) { - [presenter dismissViewControllerAnimated:animated completion:nil]; - } - [self.window.rootViewController presentViewController:aNavigationController animated:NO completion:nil]; - } -} - -- (BOOL)noBlogsAndNoWordPressDotComAccount { - NSInteger blogCount = [Blog countWithContext:[[ContextManager sharedInstance] mainContext]]; - return blogCount == 0 && ![WPAccount defaultWordPressComAccount]; -} - -- (void)customizeAppearance -{ - UIColor *defaultTintColor = self.window.tintColor; - self.window.tintColor = [WPStyleGuide newKidOnTheBlockBlue]; - - [[UINavigationBar appearance] setBarTintColor:[WPStyleGuide newKidOnTheBlockBlue]]; - [[UINavigationBar appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setBarTintColor:[UIColor whiteColor]]; - [[UINavigationBar appearance] setTintColor:[UIColor whiteColor]]; - [[UINavigationBar appearanceWhenContainedIn:[MFMailComposeViewController class], nil] setTintColor:defaultTintColor]; - [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor], NSFontAttributeName: [UIFont fontWithName:@"OpenSans-Bold" size:16.0]} ]; - [[UINavigationBar appearance] setBackgroundImage:[UIImage imageNamed:@"transparent-point"] forBarMetrics:UIBarMetricsDefault]; - [[UINavigationBar appearance] setShadowImage:[UIImage imageNamed:@"transparent-point"]]; - [[UIBarButtonItem appearance] setTitleTextAttributes:@{NSFontAttributeName: [WPStyleGuide regularTextFont], NSForegroundColorAttributeName: [UIColor whiteColor]} forState:UIControlStateNormal]; - [[UIBarButtonItem appearance] setTitleTextAttributes:@{NSFontAttributeName: [WPStyleGuide regularTextFont], NSForegroundColorAttributeName: [UIColor lightGrayColor]} forState:UIControlStateDisabled]; - [[UIToolbar appearance] setBarTintColor:[WPStyleGuide newKidOnTheBlockBlue]]; - [[UISwitch appearance] setOnTintColor:[WPStyleGuide newKidOnTheBlockBlue]]; - [[UIApplication sharedApplication] setStatusBarStyle:UIStatusBarStyleLightContent]; -} - - -#pragma mark - Tab bar setup - -- (UITabBarController *)tabBarController { - _tabBarController = [[UITabBarController alloc] init]; - [_tabBarController.tabBar setTranslucent:NO]; - - self.readerPostsViewController = [[ReaderPostsViewController alloc] init]; - UINavigationController *readerNavigationController = [[UINavigationController alloc] initWithRootViewController:self.readerPostsViewController]; - readerNavigationController.navigationBar.translucent = NO; - readerNavigationController.tabBarItem.image = [UIImage imageNamed:@"icon-tab-reader"]; - self.readerPostsViewController.title = @"Reader"; - - self.notificationsViewController = [[NotificationsViewController alloc] init]; - UINavigationController *notificationsNavigationController = [[UINavigationController alloc] initWithRootViewController:self.notificationsViewController]; - notificationsNavigationController.navigationBar.translucent = NO; - notificationsNavigationController.tabBarItem.image = [UIImage imageNamed:@"icon-tab-notifications"]; - self.notificationsViewController.title = @"Notifications"; - - BlogListViewController *blogListViewController = [[BlogListViewController alloc] init]; - UINavigationController *blogListNavigationController = [[UINavigationController alloc] initWithRootViewController:blogListViewController]; - blogListNavigationController.navigationBar.translucent = NO; - blogListNavigationController.tabBarItem.image = [UIImage imageNamed:@"icon-tab-blogs"]; - blogListViewController.title = @"My Blogs"; - _tabBarController.viewControllers = [NSArray arrayWithObjects:blogListNavigationController, readerNavigationController, notificationsNavigationController, nil]; - - [_tabBarController setSelectedViewController:readerNavigationController]; - - return _tabBarController; -} - -- (void)showNotificationsTab { - NSInteger notificationsTabIndex = [[self.tabBarController viewControllers] indexOfObject:self.notificationsViewController.navigationController]; - [self.tabBarController setSelectedIndex:notificationsTabIndex]; -} - -#pragma mark - Global Alerts - -- (void)showAlertWithTitle:(NSString *)title message:(NSString *)message { - DDLogInfo(@"Showing alert with title: %@", message); - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title - message:message - delegate:self - cancelButtonTitle:NSLocalizedString(@"Need Help?", @"'Need help?' button label, links off to the WP for iOS FAQ.") - otherButtonTitles:NSLocalizedString(@"OK", @"OK button label."), nil]; - [alert show]; -} - -- (void)showNotificationErrorAlert:(NSNotification *)notification { - NSString *cleanedErrorMsg = nil; - - if([self isAlertRunning] == YES) return; //another alert is already shown - [self setAlertRunning:YES]; - - if([[notification object] isKindOfClass:[NSError class]]) { - - NSError *err = (NSError *)[notification object]; - cleanedErrorMsg = [err localizedDescription]; - - //org.wordpress.iphone --> XML-RPC errors - if ([[err domain] isEqualToString:@"org.wordpress.iphone"]){ - if([err code] == 401) - cleanedErrorMsg = NSLocalizedString(@"Sorry, you cannot access this feature. Please check your User Role on this blog.", @""); - } - - // ignore HTTP auth canceled errors - if ([err.domain isEqual:NSURLErrorDomain] && err.code == NSURLErrorUserCancelledAuthentication) { - [self setAlertRunning:NO]; - return; - } - } else { //the notification obj is a String - cleanedErrorMsg = (NSString *)[notification object]; - } - - if([cleanedErrorMsg rangeOfString:@"NSXMLParserErrorDomain"].location != NSNotFound ) - cleanedErrorMsg = NSLocalizedString(@"The app can't recognize the server response. Please, check the configuration of your blog.", @""); - - [self showAlertWithTitle:NSLocalizedString(@"Error", @"Generic popup title for any type of error.") message:cleanedErrorMsg]; -} - -- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { - [self setAlertRunning:NO]; - - if (alertView.tag == 102) { // Update alert - if (buttonIndex == 1) { - [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"http://itunes.apple.com/us/app/wordpress/id335703880?mt=8&ls=1"]]; - } - } else if (alertView.tag == kNotificationNewComment) { - if (buttonIndex == 1) { - [self showNotificationsTab]; - } - } else if (alertView.tag == kNotificationNewSocial) { - if (buttonIndex == 1) { - [self showNotificationsTab]; - } - } else { - //Need Help Alert - switch(buttonIndex) { - case 0: { - SupportViewController *supportViewController = [[SupportViewController alloc] init]; - UINavigationController *aNavigationController = [[UINavigationController alloc] initWithRootViewController:supportViewController]; - aNavigationController.navigationBar.translucent = NO; - if (IS_IPAD) { - aNavigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve; - aNavigationController.modalPresentationStyle = UIModalPresentationFormSheet; - } - - UIViewController *presenter = self.tabBarController; - if (presenter.presentedViewController) { - presenter = presenter.presentedViewController; - } - [presenter presentViewController:aNavigationController animated:YES completion:nil]; - - break; - } - case 1: - //ok - break; - default: - break; - } - } -} - - -#pragma mark - Application directories - -- (NSString *)applicationDocumentsDirectory { - return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject]; -} - -- (void)changeCurrentDirectory { - // Set current directory for WordPress app - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *currentDirectoryPath = [[paths objectAtIndex:0] stringByAppendingPathComponent:@"wordpress"]; - - BOOL isDir; - if (![fileManager fileExistsAtPath:currentDirectoryPath isDirectory:&isDir] || !isDir) { - [fileManager createDirectoryAtPath:currentDirectoryPath withIntermediateDirectories:YES attributes:nil error:nil]; - } - [fileManager changeCurrentDirectoryPath:currentDirectoryPath]; -} - - -#pragma mark - Stats and feedback - -- (void)checkIfStatsShouldSendAndUpdateCheck { - if (NO) { // Switch this to YES to debug stats/update check - [self sendStatsAndCheckForAppUpdate]; - return; - } - //check if statsDate exists in user defaults, if not, add it and run stats since this is obviously the first time - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - //[defaults setObject:nil forKey:@"statsDate"]; // Uncomment this line to force stats. - if (![defaults objectForKey:@"statsDate"]){ - NSDate *theDate = [NSDate date]; - [defaults setObject:theDate forKey:@"statsDate"]; - [self sendStatsAndCheckForAppUpdate]; - } else { - //if statsDate existed, check if it's 7 days since last stats run, if it is > 7 days, run stats - NSDate *statsDate = [defaults objectForKey:@"statsDate"]; - NSDate *today = [NSDate date]; - NSTimeInterval difference = [today timeIntervalSinceDate:statsDate]; - NSTimeInterval statsInterval = 7 * 24 * 60 * 60; //number of seconds in 30 days - if (difference > statsInterval) //if it's been more than 7 days since last stats run - { - // WARNING: for some reason, if runStats is called in a background thread - // NSURLConnection doesn't launch and stats are not sent - // Don't change this or be really sure it's working - [self sendStatsAndCheckForAppUpdate]; - } - } -} - -- (void)sendStatsAndCheckForAppUpdate { - //generate and post the stats data - /* - - device_uuid – A unique identifier to the iPhone/iPod that the app is installed on. - - app_version – the version number of the WP iPhone app - - language – language setting for the device. What does that look like? Is it EN or English? - - os_version – the version of the iPhone/iPod OS for the device - - num_blogs – number of blogs configured in the WP iPhone app - - device_model - kind of device on which the WP iPhone app is installed - */ - NSDictionary *info = [[NSBundle mainBundle] infoDictionary]; - NSLocale *locale = [NSLocale currentLocale]; - NSInteger blogCount = [Blog countWithContext:[[ContextManager sharedInstance] mainContext]]; - NSDictionary *parameters = @{@"device_uuid": [[UIDevice currentDevice] wordpressIdentifier], - @"app_version": [[info objectForKey:@"CFBundleVersion"] stringByUrlEncoding], - @"language": [[locale objectForKey: NSLocaleIdentifier] stringByUrlEncoding], - @"os_version": [[[UIDevice currentDevice] systemVersion] stringByUrlEncoding], - @"num_blogs": [[NSString stringWithFormat:@"%d", blogCount] stringByUrlEncoding], - @"device_model": [[UIDeviceHardware platform] stringByUrlEncoding]}; - - AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"http://api.wordpress.org/iphoneapp/update-check/1.0/"]]; - client.parameterEncoding = AFFormURLParameterEncoding; - [client postPath:@"" parameters:parameters success:^(AFHTTPRequestOperation *operation, NSData *responseObject) { - NSString *statsDataString = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]; - statsDataString = [[statsDataString componentsSeparatedByCharactersInSet:[NSCharacterSet newlineCharacterSet]] objectAtIndex:0]; - NSString *appversion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; - if ([statsDataString compare:appversion options:NSNumericSearch] > 0) { - DDLogInfo(@"There's a new version: %@", statsDataString); - UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Update Available", @"Popup title to highlight a new version of the app being available.") - message:NSLocalizedString(@"A new version of WordPress for iOS is now available", @"Generic popup message to highlight a new version of the app being available.") - delegate:self - cancelButtonTitle:NSLocalizedString(@"Dismiss", @"Dismiss button label.") - otherButtonTitles:NSLocalizedString(@"Update Now", @"Popup 'update' button to highlight a new version of the app being available. The button takes you to the app store on the device, and should be actionable."), nil]; - alert.tag = 102; - [alert show]; - } - } failure:nil]; - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSDate *theDate = [NSDate date]; - [defaults setObject:theDate forKey:@"statsDate"]; - [defaults synchronize]; -} - -- (void)checkIfFeedbackShouldBeEnabled -{ - [[NSUserDefaults standardUserDefaults] registerDefaults:@{kWPUserDefaultsFeedbackEnabled: @YES}]; - NSURL *url = [NSURL URLWithString:@"http://api.wordpress.org/iphoneapp/feedback-check/1.0/"]; - NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url]; - AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) { - DDLogVerbose(@"Feedback response received: %@", JSON); - NSNumber *feedbackEnabled = JSON[@"feedback-enabled"]; - if (feedbackEnabled == nil) { - feedbackEnabled = @YES; - } - - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults setBool:feedbackEnabled.boolValue forKey:kWPUserDefaultsFeedbackEnabled]; - [defaults synchronize]; - } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON) { - DDLogError(@"Error received while checking feedback enabled status: %@", error); - - // Lets be optimistic and turn on feedback by default if this call doesn't work - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - [defaults setBool:YES forKey:kWPUserDefaultsFeedbackEnabled]; - [defaults synchronize]; - }]; - - [operation start]; -} - - -#pragma mark - Crash reporting - -- (void)configureCrashlytics { -#if DEBUG - return; -#endif -#ifdef INTERNAL_BUILD - return; -#endif - - if ([[WordPressComApiCredentials crashlyticsApiKey] length] == 0) { - return; - } - - [Crashlytics startWithAPIKey:[WordPressComApiCredentials crashlyticsApiKey]]; - [[Crashlytics sharedInstance] setDelegate:self]; - - BOOL hasCredentials = ([WPAccount defaultWordPressComAccount] != nil); - [self setCommonCrashlyticsParameters]; - - if (hasCredentials && [[WPAccount defaultWordPressComAccount] username] != nil) { - [Crashlytics setUserName:[[WPAccount defaultWordPressComAccount] username]]; - } - - void (^accountChangedBlock)(NSNotification *) = ^(NSNotification *note) { - [Crashlytics setUserName:[[WPAccount defaultWordPressComAccount] username]]; - [self setCommonCrashlyticsParameters]; - }; - [[NSNotificationCenter defaultCenter] addObserverForName:WPAccountDefaultWordPressComAccountChangedNotification object:nil queue:nil usingBlock:accountChangedBlock]; -} - -- (void)crashlytics:(Crashlytics *)crashlytics didDetectCrashDuringPreviousExecution:(id)crash -{ - WPFLogMethod(); - NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; - NSInteger crashCount = [defaults integerForKey:@"crashCount"]; - crashCount += 1; - [defaults setInteger:crashCount forKey:@"crashCount"]; - [defaults synchronize]; - [WPMobileStats trackEventForSelfHostedAndWPCom:@"Crashed" properties:@{@"crash_id": crash.identifier}]; -} - -- (void)setCommonCrashlyticsParameters -{ -<<<<<<< HEAD - BOOL loggedIn = [WPAccount defaultWordPressComAccount] != nil; - [Crashlytics setObjectValue:@(loggedIn) forKey:@"logged_in"]; - [Crashlytics setObjectValue:@(loggedIn) forKey:@"connected_to_dotcom"]; - [Crashlytics setObjectValue:@([Blog countWithContext:[self managedObjectContext]]) forKey:@"number_of_blogs"]; -======= - [Crashlytics setObjectValue:[NSNumber numberWithBool:[[WordPressComApi sharedApi] hasCredentials]] forKey:@"logged_in"]; - [Crashlytics setObjectValue:@([[WordPressComApi sharedApi] hasCredentials]) forKey:@"connected_to_dotcom"]; - [Crashlytics setObjectValue:@([Blog countWithContext:[[ContextManager sharedInstance] mainContext]]) forKey:@"number_of_blogs"]; ->>>>>>> refs/heads/develop -} - -- (void)configureHockeySDK { -#ifndef INTERNAL_BUILD - return; -#endif - [[BITHockeyManager sharedHockeyManager] configureWithIdentifier:[WordPressComApiCredentials hockeyappAppId] - delegate:self]; - [[BITHockeyManager sharedHockeyManager].authenticator setIdentificationType:BITAuthenticatorIdentificationTypeDevice]; - [[BITHockeyManager sharedHockeyManager] startManager]; - [[BITHockeyManager sharedHockeyManager].authenticator authenticateInstallation]; -} - -#pragma mark - BITCrashManagerDelegate - -- (NSString *)applicationLogForCrashManager:(BITCrashManager *)crashManager { - NSString *description = [self getLogFilesContentWithMaxSize:5000]; // 5000 bytes should be enough! - if ([description length] == 0) { - return nil; - } else { - return description; - } -} - -#pragma mark - Media cleanup - -- (void)cleanUnusedMediaFileFromTmpDir { - DDLogInfo(@"%@ %@", self, NSStringFromSelector(_cmd)); - - NSManagedObjectContext *context = [[ContextManager sharedInstance] backgroundContext]; - [context performBlock:^{ - NSError *error; - NSMutableArray *mediaToKeep = [NSMutableArray array]; - - NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; - [fetchRequest setEntity:[NSEntityDescription entityForName:@"Media" inManagedObjectContext:context]]; - NSPredicate *predicate = [NSPredicate predicateWithFormat:@"ANY posts.blog != NULL AND remoteStatusNumber <> %@", @(MediaRemoteStatusSync)]; - [fetchRequest setPredicate:predicate]; - NSArray *mediaObjectsToKeep = [context executeFetchRequest:fetchRequest error:&error]; - if (error != nil) { - DDLogError(@"Error cleaning up tmp files: %@", [error localizedDescription]); - } - //get a references to media files linked in a post - DDLogInfo(@"%i media items to check for cleanup", [mediaObjectsToKeep count]); - for (Media *media in mediaObjectsToKeep) { - [mediaToKeep addObject:media.localURL]; - } - - //searches for jpg files within the app temp file - NSFileManager *fileManager = [NSFileManager defaultManager]; - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSArray *contentsOfDir = [fileManager contentsOfDirectoryAtPath:documentsDirectory error:NULL]; - - NSError *regexpError = NULL; - NSRegularExpression *jpeg = [NSRegularExpression regularExpressionWithPattern:@".jpg$" options:NSRegularExpressionCaseInsensitive error:®expError]; - - for (NSString *currentPath in contentsOfDir) { - if([jpeg numberOfMatchesInString:currentPath options:0 range:NSMakeRange(0, [currentPath length])] > 0) { - NSString *filepath = [documentsDirectory stringByAppendingPathComponent:currentPath]; - - BOOL keep = NO; - //if the file is not referenced in any post we can delete it - for (NSString *currentMediaToKeepPath in mediaToKeep) { - if([currentMediaToKeepPath isEqualToString:filepath]) { - keep = YES; - break; - } - } - - if(keep == NO) { - [fileManager removeItemAtPath:filepath error:NULL]; - } - } - } - }]; -} - - -#pragma mark - Networking setup, User agents - -- (void)setupUserAgent { - // Keep a copy of the original userAgent for use with certain webviews in the app. - UIWebView *webView = [[UIWebView alloc] init]; - NSString *defaultUA = [webView stringByEvaluatingJavaScriptFromString:@"navigator.userAgent"]; - - NSString *appVersion = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"]; - [[NSUserDefaults standardUserDefaults] setObject:appVersion forKey:@"version_preference"]; - NSString *appUA = [NSString stringWithFormat:@"wp-iphone/%@ (%@ %@, %@) Mobile", - appVersion, - [[UIDevice currentDevice] systemName], - [[UIDevice currentDevice] systemVersion], - [[UIDevice currentDevice] model] - ]; - NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys: appUA, @"UserAgent", defaultUA, @"DefaultUserAgent", appUA, @"AppUserAgent", nil]; - [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary]; -} - -- (void)useDefaultUserAgent { - NSString *ua = [[NSUserDefaults standardUserDefaults] stringForKey:@"DefaultUserAgent"]; - NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:ua, @"UserAgent", nil]; - // We have to call registerDefaults else the change isn't picked up by UIWebViews. - [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary]; - DDLogVerbose(@"User-Agent set to: %@", ua); -} - -- (void)useAppUserAgent { - NSString *ua = [[NSUserDefaults standardUserDefaults] stringForKey:@"AppUserAgent"]; - NSDictionary *dictionary = [[NSDictionary alloc] initWithObjectsAndKeys:ua, @"UserAgent", nil]; - // We have to call registerDefaults else the change isn't picked up by UIWebViews. - [[NSUserDefaults standardUserDefaults] registerDefaults:dictionary]; - - DDLogVerbose(@"User-Agent set to: %@", ua); -} - -- (NSString *)applicationUserAgent { - return [[NSUserDefaults standardUserDefaults] objectForKey:@"UserAgent"]; -} - -- (void)setupSingleSignOn { - if ([[WPAccount defaultWordPressComAccount] username]) { - [[WPComOAuthController sharedController] setWordPressComUsername:[[WPAccount defaultWordPressComAccount] username]]; - [[WPComOAuthController sharedController] setWordPressComPassword:[[WPAccount defaultWordPressComAccount] password]]; - } -} - -- (void)setupReachability { -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Warc-retain-cycles" - // Set the wpcom availability to YES to avoid issues with lazy reachibility notifier - self.wpcomAvailable = YES; - // Same for general internet connection - self.connectionAvailable = YES; - - // allocate the internet reachability object - _internetReachability = [Reachability reachabilityForInternetConnection]; - - self.connectionAvailable = [_internetReachability isReachable]; - // set the blocks - _internetReachability.reachableBlock = ^(Reachability*reach) - { - DDLogInfo(@"Internet connection is back"); - self.connectionAvailable = YES; - }; - _internetReachability.unreachableBlock = ^(Reachability*reach) - { - DDLogInfo(@"No internet connection"); - self.connectionAvailable = NO; - }; - // start the notifier which will cause the reachability object to retain itself! - [_internetReachability startNotifier]; - - // allocate the WP.com reachability object - _wpcomReachability = [Reachability reachabilityWithHostname:@"wordpress.com"]; - // set the blocks - _wpcomReachability.reachableBlock = ^(Reachability*reach) - { - DDLogInfo(@"Connection to WordPress.com is back"); - self.wpcomAvailable = YES; - }; - _wpcomReachability.unreachableBlock = ^(Reachability*reach) - { - DDLogInfo(@"No connection to WordPress.com"); - self.wpcomAvailable = NO; - }; - // start the notifier which will cause the reachability object to retain itself! - [_wpcomReachability startNotifier]; -#pragma clang diagnostic pop -} - -- (void)checkWPcomAuthentication { - if ([[NSUserDefaults standardUserDefaults] objectForKey:@"wpcom_authenticated_flag"] != nil) { - NSString *tempIsAuthenticated = (NSString *)[[NSUserDefaults standardUserDefaults] objectForKey:@"wpcom_authenticated_flag"]; - if ([tempIsAuthenticated isEqualToString:@"1"]) { - self.isWPcomAuthenticated = YES; - } - } - - NSString *authURL = @"https://wordpress.com/xmlrpc.php"; - WPAccount *account = [WPAccount defaultWordPressComAccount]; - if (account) { - WPXMLRPCClient *client = [WPXMLRPCClient clientWithXMLRPCEndpoint:[NSURL URLWithString:authURL]]; - [client callMethod:@"wp.getUsersBlogs" - parameters:[NSArray arrayWithObjects:account.username, account.password, nil] - success:^(AFHTTPRequestOperation *operation, id responseObject) { - self.isWPcomAuthenticated = YES; - DDLogInfo(@"Logged in to WordPress.com as %@", account.username); - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if ([error.domain isEqualToString:@"XMLRPC"] && error.code == 403) { - self.isWPcomAuthenticated = NO; - } - DDLogError(@"Error authenticating %@ with WordPress.com: %@", account.username, [error description]); - }]; - } else { - self.isWPcomAuthenticated = NO; - } - - if (self.isWPcomAuthenticated) { - [[NSUserDefaults standardUserDefaults] setObject:@"1" forKey:@"wpcom_authenticated_flag"]; - } else { - [[NSUserDefaults standardUserDefaults] setObject:@"0" forKey:@"wpcom_authenticated_flag"]; - } -} - - -#pragma mark - Keychain - -+ (void)wipeAllKeychainItems -{ - NSArray *secItemClasses = @[(__bridge id)kSecClassGenericPassword, - (__bridge id)kSecClassInternetPassword, - (__bridge id)kSecClassCertificate, - (__bridge id)kSecClassKey, - (__bridge id)kSecClassIdentity]; - for (id secItemClass in secItemClasses) { - NSDictionary *spec = @{(__bridge id)kSecClass : secItemClass}; - SecItemDelete((__bridge CFDictionaryRef)spec); - } -} - -+ (void)fixKeychainAccess -{ - NSDictionary *query = @{ - (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, - (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenUnlocked, - (__bridge id)kSecReturnAttributes: @YES, - (__bridge id)kSecMatchLimit: (__bridge id)kSecMatchLimitAll - }; - - CFTypeRef result = NULL; - OSStatus status = SecItemCopyMatching((__bridge CFDictionaryRef)query, &result); - if (status != errSecSuccess) { - return; - } - DDLogVerbose(@"Fixing keychain items with wrong access requirements"); - for (NSDictionary *item in (__bridge_transfer NSArray *)result) { - NSDictionary *itemQuery = @{ - (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, - (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenUnlocked, - (__bridge id)kSecAttrService: item[(__bridge id)kSecAttrService], - (__bridge id)kSecAttrAccount: item[(__bridge id)kSecAttrAccount], - (__bridge id)kSecReturnAttributes: @YES, - (__bridge id)kSecReturnData: @YES, - }; - - CFTypeRef itemResult = NULL; - status = SecItemCopyMatching((__bridge CFDictionaryRef)itemQuery, &itemResult); - if (status == errSecSuccess) { - NSDictionary *itemDictionary = (__bridge NSDictionary *)itemResult; - NSDictionary *updateQuery = @{ - (__bridge id)kSecClass: (__bridge id)kSecClassGenericPassword, - (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleWhenUnlocked, - (__bridge id)kSecAttrService: item[(__bridge id)kSecAttrService], - (__bridge id)kSecAttrAccount: item[(__bridge id)kSecAttrAccount], - }; - NSDictionary *updatedAttributes = @{ - (__bridge id)kSecValueData: itemDictionary[(__bridge id)kSecValueData], - (__bridge id)kSecAttrAccessible: (__bridge id)kSecAttrAccessibleAfterFirstUnlock, - }; - status = SecItemUpdate((__bridge CFDictionaryRef)updateQuery, (__bridge CFDictionaryRef)updatedAttributes); - if (status == errSecSuccess) { - DDLogInfo(@"Migrated keychain item %@", item); - } else { - DDLogError(@"Error migrating keychain item: %d", status); - } - } else { - DDLogError(@"Error migrating keychain item: %d", status); - } - } - DDLogVerbose(@"End keychain fixing"); -} - - -#pragma mark - Debugging and logging - -- (void)printDebugLaunchInfo { - UIDevice *device = [UIDevice currentDevice]; - NSInteger crashCount = [[NSUserDefaults standardUserDefaults] integerForKey:@"crashCount"]; - NSArray *languages = [[NSUserDefaults standardUserDefaults] objectForKey:@"AppleLanguages"]; - NSString *currentLanguage = [languages objectAtIndex:0]; - BOOL extraDebug = [[NSUserDefaults standardUserDefaults] boolForKey:@"extra_debug"]; - - DDLogInfo(@"==========================================================================="); - DDLogInfo(@"Launching WordPress for iOS %@...", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]); - DDLogInfo(@"Crash count: %d", crashCount); -#ifdef DEBUG - DDLogInfo(@"Debug mode: Debug"); -#else - DDLogInfo(@"Debug mode: Production"); -#endif - DDLogInfo(@"Extra debug: %@", extraDebug ? @"YES" : @"NO"); - DDLogInfo(@"Device model: %@ (%@)", [UIDeviceHardware platformString], [UIDeviceHardware platform]); - DDLogInfo(@"OS: %@ %@", [device systemName], [device systemVersion]); - DDLogInfo(@"Language: %@", currentLanguage); - DDLogInfo(@"UDID: %@", [device wordpressIdentifier]); - DDLogInfo(@"APN token: %@", [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]); - DDLogInfo(@"==========================================================================="); -} - -- (void)removeCredentialsForDebug { -#if DEBUG - /* - A dictionary containing the credentials for all available protection spaces. - The dictionary has keys corresponding to the NSURLProtectionSpace objects. - The values for the NSURLProtectionSpace keys consist of dictionaries where the keys are user name strings, and the value is the corresponding NSURLCredential object. - */ - [[[NSURLCredentialStorage sharedCredentialStorage] allCredentials] enumerateKeysAndObjectsUsingBlock:^(NSURLProtectionSpace *ps, NSDictionary *dict, BOOL *stop) { - [dict enumerateKeysAndObjectsUsingBlock:^(id key, NSURLCredential *credential, BOOL *stop) { - DDLogVerbose(@"Removing credential %@ for %@", [credential user], [ps host]); - [[NSURLCredentialStorage sharedCredentialStorage] removeCredential:credential forProtectionSpace:ps]; - }]; - }]; -#endif -} - -- (void)configureLogging -{ - // Remove the old Documents/wordpress.log if it exists - NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); - NSString *documentsDirectory = [paths objectAtIndex:0]; - NSString *filePath = [documentsDirectory stringByAppendingPathComponent:@"wordpress.log"]; - NSFileManager *fileManager = [NSFileManager defaultManager]; - - if ([fileManager fileExistsAtPath:filePath]) { - [fileManager removeItemAtPath:filePath error:nil]; - } - - // Sets up the CocoaLumberjack logging; debug output to console and file -#ifdef DEBUG - [DDLog addLogger:[DDASLLogger sharedInstance]]; - [DDLog addLogger:[DDTTYLogger sharedInstance]]; -#endif - -#ifndef INTERNAL_BUILD - [DDLog addLogger:[CrashlyticsLogger sharedInstance]]; -#endif - - BOOL extraDebug = [[NSUserDefaults standardUserDefaults] boolForKey:@"extra_debug"]; - if (extraDebug) { - ddLogLevel = LOG_LEVEL_VERBOSE; - } -} - -- (DDFileLogger *)fileLogger { - if (_fileLogger) { - return _fileLogger; - } - _fileLogger = [[DDFileLogger alloc] init]; - _fileLogger.rollingFrequency = 60 * 60 * 24; // 24 hour rolling - _fileLogger.logFileManager.maximumNumberOfLogFiles = 7; - [DDLog addLogger:_fileLogger]; - return _fileLogger; -} - -// get the log content with a maximum byte size -- (NSString *) getLogFilesContentWithMaxSize:(NSInteger)maxSize { - NSMutableString *description = [NSMutableString string]; - - NSArray *sortedLogFileInfos = [[self.fileLogger logFileManager] sortedLogFileInfos]; - NSInteger count = [sortedLogFileInfos count]; - - // we start from the last one - for (NSInteger index = 0; index < count; index++) { - DDLogFileInfo *logFileInfo = [sortedLogFileInfos objectAtIndex:index]; - - NSData *logData = [[NSFileManager defaultManager] contentsAtPath:[logFileInfo filePath]]; - if ([logData length] > 0) { - NSString *result = [[NSString alloc] initWithBytes:[logData bytes] - length:[logData length] - encoding: NSUTF8StringEncoding]; - - [description appendString:result]; - } - } - - if ([description length] > maxSize) { - description = (NSMutableString *)[description substringWithRange:NSMakeRange([description length] - maxSize - 1, maxSize)]; - } - - return description; -} - -- (void)toggleExtraDebuggingIfNeeded { - if (!_listeningForBlogChanges) { - _listeningForBlogChanges = YES; - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleDefaultAccountChangedNotification:) name:WPAccountDefaultWordPressComAccountChangedNotification object:nil]; - } - - int num_blogs = [Blog countWithContext:[[ContextManager sharedInstance] mainContext]]; - BOOL authed = [[[NSUserDefaults standardUserDefaults] objectForKey:@"wpcom_authenticated_flag"] boolValue]; - if (num_blogs == 0 && !authed) { - // When there are no blogs in the app the settings screen is unavailable. - // In this case, enable extra_debugging by default to help troubleshoot any issues. - if([[NSUserDefaults standardUserDefaults] objectForKey:@"orig_extra_debug"] != nil) { - return; // Already saved. Don't save again or we could loose the original value. - } - - NSString *origExtraDebug = [[NSUserDefaults standardUserDefaults] boolForKey:@"extra_debug"] ? @"YES" : @"NO"; - [[NSUserDefaults standardUserDefaults] setObject:origExtraDebug forKey:@"orig_extra_debug"]; - [[NSUserDefaults standardUserDefaults] setBool:YES forKey:@"extra_debug"]; - ddLogLevel = LOG_LEVEL_VERBOSE; - [NSUserDefaults resetStandardUserDefaults]; - } else { - NSString *origExtraDebug = [[NSUserDefaults standardUserDefaults] stringForKey:@"orig_extra_debug"]; - if(origExtraDebug == nil) { - return; - } - - // Restore the original setting and remove orig_extra_debug. - [[NSUserDefaults standardUserDefaults] setBool:[origExtraDebug boolValue] forKey:@"extra_debug"]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"orig_extra_debug"]; - [NSUserDefaults resetStandardUserDefaults]; - - if ([origExtraDebug boolValue]) { - ddLogLevel = LOG_LEVEL_VERBOSE; - } - } -} - -- (void)handleDefaultAccountChangedNotification:(NSNotification *)notification { - [self toggleExtraDebuggingIfNeeded]; - [NotificationsManager registerForPushNotifications]; - [self showWelcomeScreenIfNeededAnimated:NO]; -} - -@end diff --git a/WordPress/WordPressApi/WordPressComApi.m.orig b/WordPress/WordPressApi/WordPressComApi.m.orig deleted file mode 100644 index 363d0aa00a13..000000000000 --- a/WordPress/WordPressApi/WordPressComApi.m.orig +++ /dev/null @@ -1,888 +0,0 @@ -// -// WordPressComApi.m -// WordPress -// -// Created by Jorge Bernal on 6/4/12. -// Copyright (c) 2012 WordPress. All rights reserved. -// - -#import "WordPressComApi.h" -#import "WordPressComApiCredentials.h" -#import "SFHFKeychainUtils.h" -#import "WordPressAppDelegate.h" -#import "Constants.h" -#import "Note.h" -#import "NSString+Helpers.h" -#import "WPToast.h" -#import -#import -#import "UIDevice+WordPressIdentifier.h" -<<<<<<< HEAD -#import "WPAccount.h" -#import "NotificationsManager.h" -======= -#import "ContextManager.h" ->>>>>>> refs/heads/develop -#import - - -NSString *const WordPressComApiClientEndpointURL = @"https://public-api.wordpress.com/rest/v1/"; -NSString *const WordPressComApiOauthBaseUrl = @"https://public-api.wordpress.com/oauth2"; -NSString *const WordPressComApiOauthServiceName = @"public-api.wordpress.com"; -NSString *const WordPressComApiOauthRedirectUrl = @"http://wordpress.com/"; -NSString *const WordPressComApiNotificationFields = @"id,type,unread,body,subject,timestamp"; -NSString *const WordPressComApiUnseenNotesNotification = @"WordPressComUnseenNotes"; -NSString *const WordPressComApiNotesUserInfoKey = @"notes"; -NSString *const WordPressComApiUnseenNoteCountInfoKey = @"note_count"; -NSString *const WordPressComApiLoginUrl = @"https://wordpress.com/wp-login.php"; -NSString *const WordPressComApiErrorDomain = @"com.wordpress.api"; -NSString *const WordPressComApiErrorCodeKey = @"WordPressComApiErrorCodeKey"; -NSString *const WordPressComApiErrorMessageKey = @"WordPressComApiErrorMessageKey"; - - -#define UnfollowedBlogEvent @"UnfollowedBlogEvent" - - -// AFJSONRequestOperation requires that a URI end with .json in order to match -// This will match all public-api.wordpress.com/rest/v1/ URI's and parse them as JSON -@interface WPJSONRequestOperation : AFJSONRequestOperation -@end -@implementation WPJSONRequestOperation -+(BOOL)canProcessRequest:(NSURLRequest *)urlRequest { - NSURL *testURL = [NSURL URLWithString:WordPressComApiOauthBaseUrl]; - if ([urlRequest.URL.host isEqualToString:testURL.host] && [urlRequest.URL.path rangeOfString:testURL.path].location == 0) - return YES; - - testURL = [NSURL URLWithString:WordPressComApiClientEndpointURL]; - if ([urlRequest.URL.host isEqualToString:testURL.host] && [urlRequest.URL.path rangeOfString:testURL.path].location == 0) - return YES; - - return NO; -} - -- (NSError *)error { - if (self.response.statusCode >= 400) { - NSString *errorMessage = [self.responseJSON objectForKey:@"message"]; - NSUInteger errorCode = WordPressComApiErrorJSON; - if ([self.responseJSON objectForKey:@"error"] && errorMessage) { - NSString *error = [self.responseJSON objectForKey:@"error"]; - if ([error isEqualToString:@"invalid_token"]) { - errorCode = WordPressComApiErrorInvalidToken; - } else if ([error isEqualToString:@"authorization_required"]) { - errorCode = WordPressComApiErrorAuthorizationRequired; - } - return [NSError errorWithDomain:WordPressComApiErrorDomain code:errorCode userInfo:@{NSLocalizedDescriptionKey: errorMessage, WordPressComApiErrorCodeKey: error}]; - } - } - return [super error]; -} -@end - -@interface WordPressComApi () -@property (readwrite, nonatomic, strong) NSString *username; -@property (readwrite, nonatomic, strong) NSString *password; -@property (nonatomic, strong) NSString *authToken; - -- (void)clearWpcomCookies; - -@end - -@implementation WordPressComApi { - NSString *_authToken; -} - -+ (WordPressComApi *)sharedApi { - DDLogWarn(@"Called obsolete [WordPressComApi sharedApi]"); - return [[WPAccount defaultWordPressComAccount] restApi]; -} - -+ (WordPressComApi *)anonymousApi { - static WordPressComApi *_anonymousApi = nil; - static dispatch_once_t oncePredicate; - dispatch_once(&oncePredicate, ^{ - DDLogVerbose(@"Initializing anonymous API"); - _anonymousApi = [[self alloc] initWithBaseURL:[NSURL URLWithString:WordPressComApiClientEndpointURL] ]; - [_anonymousApi registerHTTPOperationClass:[WPJSONRequestOperation class]]; - [_anonymousApi setDefaultHeader:@"User-Agent" value:[[WordPressAppDelegate sharedWordPressApplicationDelegate] applicationUserAgent]]; - }); - - return _anonymousApi; -} - -- (id)initWithOAuthToken:(NSString *)authToken { - self = [super initWithBaseURL:[NSURL URLWithString:WordPressComApiClientEndpointURL]]; - if (self) { - _authToken = authToken; - [self setAuthorizationHeaderWithToken:_authToken]; - [self registerHTTPOperationClass:[WPJSONRequestOperation class]]; - [self setDefaultHeader:@"User-Agent" value:[[WordPressAppDelegate sharedWordPressApplicationDelegate] applicationUserAgent]]; - } - return self; -} - -#pragma mark - Account management - -- (void)signInWithUsername:(NSString *)username password:(NSString *)password success:(void (^)())success failure:(void (^)(NSError *error))failure { - NSAssert(username != nil, @"username is nil"); - NSAssert(password != nil, @"password is nil"); - if (self.username && ![username isEqualToString:self.username]) { - [self signOut]; // Only one account supported for now - } - self.username = username; - self.password = password; - - void (^successBlock)(AFHTTPRequestOperation *,id) = ^(AFHTTPRequestOperation *operation, id responseObject) { - /* - responseObject should look like: - { - "access_token": "YOUR_API_TOKEN", - "blog_id": "blog id", - "blog_url": "blog url", - "token_type": "bearer" - } - */ - NSString *accessToken; - if ([responseObject respondsToSelector:@selector(objectForKey:)]) { - accessToken = [responseObject objectForKey:@"access_token"]; - } - if (accessToken == nil) { - WPFLog(@"No access token found on OAuth response: %@", responseObject); - //FIXME: this error message is crappy. Understand the posible reasons why responseObject is not what we expected and return a proper error - NSString *localizedDescription = NSLocalizedString(@"Error authenticating", @""); - NSError *error = [NSError errorWithDomain:WordPressComApiErrorDomain code:WordPressComApiErrorNoAccessToken userInfo:@{NSLocalizedDescriptionKey: localizedDescription}]; - if (failure) { - failure(error); - } - return; - } - self.authToken = accessToken; - NSError *error = nil; - [SFHFKeychainUtils storeUsername:self.username andPassword:self.password forServiceName:kWPcomXMLRPCUrl updateExisting:YES error:&error]; - if (error) { - if (failure) { - failure(error); - } - } else { - WPFLog(@"Signed in as %@", self.username); - [[NSUserDefaults standardUserDefaults] setObject:self.username forKey:@"wpcom_username_preference"]; - [[NSUserDefaults standardUserDefaults] setObject:@"1" forKey:@"wpcom_authenticated_flag"]; - [[NSUserDefaults standardUserDefaults] synchronize]; - [WordPressAppDelegate sharedWordPressApplicationDelegate].isWPcomAuthenticated = YES; - // [NotificationsManager registerForPushNotifications]; - [[NSNotificationCenter defaultCenter] postNotificationName:WordPressComApiDidLoginNotification object:self.username]; - if (success) success(); - } - }; - AFHTTPClient *client = [AFHTTPClient clientWithBaseURL:[NSURL URLWithString:WordPressComApiOauthBaseUrl]]; - [client registerHTTPOperationClass:[WPJSONRequestOperation class]]; - [client setDefaultHeader:@"User-Agent" value:[[WordPressAppDelegate sharedWordPressApplicationDelegate] applicationUserAgent]]; - NSDictionary *params = @{ - @"client_id": [WordPressComApi WordPressAppId], - @"redirect_uri": WordPressComApiOauthRedirectUrl, - @"client_secret": [WordPressComApi WordPressAppSecret], - @"grant_type": @"password", - @"username": username, - @"password": password - }; - - [self postPath:@"/oauth2/token" - parameters:params - success:successBlock - failure:^(AFHTTPRequestOperation *operation, NSError *error) { - WPFLog(@"Couldn't signin the user: %@", error); - self.password = nil; - if (operation.response.statusCode != 400) { - [WPError showAlertWithError:error]; - } - if (failure) failure(error); - }]; -} - -- (void)refreshTokenWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure { - if (self.username == nil || self.password == nil) { - WPFLog(@"-[WordPressComApi refreshTokenWithSuccess:failure:] username or password are nil, don't even try"); - return; - } - [self signInWithUsername:self.username password:self.password success:success failure:failure]; -} - -- (void)signInWithToken:(NSString *)token { - self.authToken = token; -} - -- (void)signOut { - WPFLogMethod(); - NSError *error = nil; - -// [NotificationsManager unregisterDeviceToken]; - - [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:@"WordPress.com" error:&error]; - [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:kWPcomXMLRPCUrl error:&error]; - - [WordPressAppDelegate sharedWordPressApplicationDelegate].isWPcomAuthenticated = NO; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:kApnsDeviceTokenPrefKey]; //Remove the token from Preferences, otherwise the token is never sent to the server on the next login - [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:WordPressComApiOauthServiceName error:&error]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_username_preference"]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_authenticated_flag"]; - [[NSUserDefaults standardUserDefaults] synchronize]; - self.authToken = nil; - self.username = nil; - self.password = nil; - [self clearAuthorizationHeader]; - - [self clearWpcomCookies]; - - // Notify the world - [[NSNotificationCenter defaultCenter] postNotificationName:WordPressComApiDidLogoutNotification object:nil]; -} - -- (BOOL)hasCredentials { - return _authToken != nil; -} - -- (void)validateWPComAccountWithEmail:(NSString *)email andUsername:(NSString *)username andPassword:(NSString *)password success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure -{ - [self createWPComAccountWithEmail:email andUsername:username andPassword:password validate:YES success:success failure:failure]; -} - -- (void)createWPComAccountWithEmail:(NSString *)email andUsername:(NSString *)username andPassword:(NSString *)password success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure -{ - [self createWPComAccountWithEmail:email andUsername:username andPassword:password validate:NO success:success failure:failure]; -} - -- (void)createWPComAccountWithEmail:(NSString *)email andUsername:(NSString *)username andPassword:(NSString *)password validate:(BOOL)validate success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure -{ - NSParameterAssert(email != nil); - NSParameterAssert(username != nil); - NSParameterAssert(password != nil); - - void (^successBlock)(AFHTTPRequestOperation *, id) = ^(AFHTTPRequestOperation *operation, id responseObject) { - success(responseObject); - }; - - void (^failureBlock)(AFHTTPRequestOperation *, NSError *) = ^(AFHTTPRequestOperation *operation, NSError *error){ - NSError *errorWithLocalizedMessage; - // This endpoint is throttled, so check if we've sent too many requests and fill that error in as - // when too many requests occur the API just spits out an html page. - if ([error.userInfo objectForKey:WordPressComApiErrorCodeKey] == nil) { - NSString *responseString = [operation responseString]; - if (responseString != nil && [responseString rangeOfString:@"Limit reached"].location != NSNotFound) { - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:error.userInfo]; - [userInfo setValue:NSLocalizedString(@"Limit reached. You can try again in 1 minute. Trying again before that will only increase the time you have to wait before the ban is lifted. If you think this is in error, contact support.", @"") forKey:WordPressComApiErrorMessageKey]; - [userInfo setValue:@"too_many_requests" forKey:WordPressComApiErrorCodeKey]; - errorWithLocalizedMessage = [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:userInfo]; - } - } else { - NSString *localizedErrorMessage = [self errorMessageForError:error]; - NSString *errorCode = [error.userInfo objectForKey:WordPressComApiErrorCodeKey]; - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:error.userInfo]; - [userInfo setValue:errorCode forKey:WordPressComApiErrorCodeKey]; - [userInfo setValue:localizedErrorMessage forKey:WordPressComApiErrorMessageKey]; - errorWithLocalizedMessage = [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:userInfo]; - } - - failure(errorWithLocalizedMessage); - }; - - NSDictionary *params = @{ - @"email": email, - @"username" : username, - @"password" : password, - @"validate" : @(validate), - @"client_id" : [WordPressComApiCredentials client], - @"client_secret" : [WordPressComApiCredentials secret] - }; - - [self postPath:@"users/new" parameters:params success:successBlock failure:failureBlock]; - -} - -- (void)validateWPComBlogWithUrl:(NSString *)blogUrl andBlogTitle:(NSString *)blogTitle andLanguageId:(NSNumber *)languageId success:(void (^)(id))success failure:(void (^)(NSError *))failure -{ - [self createWPComBlogWithUrl:blogUrl andBlogTitle:blogTitle andLanguageId:languageId andBlogVisibility:WordPressComApiBlogVisibilityPublic validate:YES success:success failure:failure]; -} - -- (void)createWPComBlogWithUrl:(NSString *)blogUrl andBlogTitle:(NSString *)blogTitle andLanguageId:(NSNumber *)languageId andBlogVisibility:(WordPressComApiBlogVisibility)visibility success:(void (^)(id))success failure:(void (^)(NSError *))failure -{ - [self createWPComBlogWithUrl:blogUrl andBlogTitle:blogTitle andLanguageId:languageId andBlogVisibility:visibility validate:NO success:success failure:failure]; -} - -- (void)createWPComBlogWithUrl:(NSString *)blogUrl andBlogTitle:(NSString *)blogTitle andLanguageId:(NSNumber *)languageId andBlogVisibility:(WordPressComApiBlogVisibility)visibility validate:(BOOL)validate success:(void (^)(id))success failure:(void (^)(NSError *))failure -{ - NSParameterAssert(blogUrl != nil); - NSParameterAssert(languageId != nil); - - void (^successBlock)(AFHTTPRequestOperation *, id) = ^(AFHTTPRequestOperation *operation, id responseObject) { - NSDictionary *response = responseObject; - if ([response count] == 0) { - // There was an error creating the blog as a successful call yields a dictionary back. - NSString *localizedErrorMessage = NSLocalizedString(@"Unknown error", nil); - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] init]; - [userInfo setValue:localizedErrorMessage forKey:WordPressComApiErrorMessageKey]; - NSError *errorWithLocalizedMessage = [[NSError alloc] initWithDomain:WordPressComApiErrorDomain code:0 userInfo:userInfo]; - - failure(errorWithLocalizedMessage); - } else { - success(responseObject); - } - }; - - void (^failureBlock)(AFHTTPRequestOperation *, NSError *) = ^(AFHTTPRequestOperation *operation, NSError *error){ - NSError *errorWithLocalizedMessage; - - if ([error.userInfo objectForKey:WordPressComApiErrorCodeKey] == nil) { - NSString *responseString = [operation responseString]; - if (responseString != nil && [responseString rangeOfString:@"Limit reached"].location != NSNotFound) { - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:error.userInfo]; - [userInfo setValue:NSLocalizedString(@"Limit reached. You can try again in 1 minute. Trying again before that will only increase the time you have to wait before the ban is lifted. If you think this is in error, contact support.", @"") forKey:WordPressComApiErrorMessageKey]; - [userInfo setValue:@"too_many_requests" forKey:WordPressComApiErrorCodeKey]; - errorWithLocalizedMessage = [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:userInfo]; - } - } - else { - NSString *errorCode = [error.userInfo objectForKey:WordPressComApiErrorCodeKey]; - NSString *localizedErrorMessage = [self errorMessageForError:error]; - NSMutableDictionary *userInfo = [[NSMutableDictionary alloc] initWithDictionary:error.userInfo]; - [userInfo setValue:errorCode forKey:WordPressComApiErrorCodeKey]; - [userInfo setValue:localizedErrorMessage forKey:WordPressComApiErrorMessageKey]; - errorWithLocalizedMessage = [[NSError alloc] initWithDomain:error.domain code:error.code userInfo:userInfo]; - } - failure(errorWithLocalizedMessage); - }; - - if (blogTitle == nil) { - blogTitle = @""; - } - - int blogVisibility = 1; - if (visibility == WordPressComApiBlogVisibilityPublic) { - blogVisibility = 1; - } else if (visibility == WordPressComApiComBlogVisibilityPrivate) { - blogVisibility = -1; - } else { - // Hidden - blogVisibility = 0; - } - - NSDictionary *params = @{ - @"blog_name": blogUrl, - @"blog_title": blogTitle, - @"lang_id": languageId, - @"public": @(blogVisibility), - @"validate": @(validate), - @"client_id": [WordPressComApiCredentials client], - @"client_secret": [WordPressComApiCredentials secret] - }; - - [self postPath:@"sites/new" parameters:params success:successBlock failure:failureBlock]; -} - - -#pragma mark - Transitional methods - -- (void)updateCredentailsFromStore { - self.username = [[NSUserDefaults standardUserDefaults] objectForKey:@"wpcom_username_preference"]; - NSError *error = nil; - self.password = [SFHFKeychainUtils getPasswordForUsername:self.username - andServiceName:kWPcomXMLRPCUrl - error:&error]; - [self clearWpcomCookies]; - [[NSNotificationCenter defaultCenter] postNotificationName:WordPressComApiDidLogoutNotification object:nil]; - [WordPressAppDelegate sharedWordPressApplicationDelegate].isWPcomAuthenticated = YES; -// [NotificationsManager registerForPushNotifications]; - [[NSNotificationCenter defaultCenter] postNotificationName:WordPressComApiDidLoginNotification object:self.username]; -} - -- (void)clearWpcomCookies { - NSArray *wpcomCookies = [[NSHTTPCookieStorage sharedHTTPCookieStorage] cookies]; - for (NSHTTPCookie *cookie in wpcomCookies) { - if ([cookie.domain hasSuffix:@"wordpress.com"]) { - [[NSHTTPCookieStorage sharedHTTPCookieStorage] deleteCookie:cookie]; - } - } - [[NSURLCache sharedURLCache] removeAllCachedResponses]; -} - -#pragma mark - Notifications - -- (void)saveNotificationSettings:(void (^)())success - failure:(void (^)(NSError *error))failure { - - NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; - if( nil == token ) return; //no apns token available - - if(![[WordPressComApi sharedApi] hasCredentials]) - return; - - NSDictionary *notificationPreferences = [[NSUserDefaults standardUserDefaults] objectForKey:@"notification_preferences"]; - if (!notificationPreferences) - return; - - NSMutableArray *notificationPrefArray = [[notificationPreferences allKeys] mutableCopy]; - if ([notificationPrefArray indexOfObject:@"muted_blogs"] != NSNotFound) - [notificationPrefArray removeObjectAtIndex:[notificationPrefArray indexOfObject:@"muted_blogs"]]; - - // Build the dictionary to send in the API call - NSMutableDictionary *updatedSettings = [[NSMutableDictionary alloc] init]; - for (int i = 0; i < [notificationPrefArray count]; i++) { - NSDictionary *updatedSetting = [notificationPreferences objectForKey:[notificationPrefArray objectAtIndex:i]]; - [updatedSettings setValue:[updatedSetting objectForKey:@"value"] forKey:[notificationPrefArray objectAtIndex:i]]; - } - - //Check and send 'mute_until' value - NSMutableDictionary *muteDictionary = [notificationPreferences objectForKey:@"mute_until"]; - if(muteDictionary != nil && [muteDictionary objectForKey:@"value"] != nil) { - [updatedSettings setValue:[muteDictionary objectForKey:@"value"] forKey:@"mute_until"]; - } else { - [updatedSettings setValue:@"0" forKey:@"mute_until"]; - } - - NSArray *blogsArray = [[notificationPreferences objectForKey:@"muted_blogs"] objectForKey:@"value"]; - NSMutableArray *mutedBlogsArray = [[NSMutableArray alloc] init]; - for (int i=0; i < [blogsArray count]; i++) { - NSDictionary *userBlog = [blogsArray objectAtIndex:i]; - if ([[userBlog objectForKey:@"value"] intValue] == 1) { - [mutedBlogsArray addObject:userBlog]; - } - } - - if ([mutedBlogsArray count] > 0) - [updatedSettings setValue:mutedBlogsArray forKey:@"muted_blogs"]; - - if ([updatedSettings count] == 0) - return; - - NSArray *parameters = @[[self usernameForXmlrpc], - [self passwordForXmlrpc], - updatedSettings, - token, - @"apple", -#ifdef INTERNAL_BUILD - @"org.wordpress.internal", -#endif - ]; - WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:kWPcomXMLRPCUrl]]; - [api setAuthorizationHeaderWithToken:self.authToken]; - //Update supported notifications dictionary - [api callMethod:@"wpcom.set_mobile_push_notification_settings" - parameters:parameters - success:^(AFHTTPRequestOperation *operation, id responseObject) { - // Hooray! - if (success) - success(); - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) - failure(error); - }]; -} - -- (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError *error))failure { - NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; - if( nil == token ) return; //no apns token available - - if(![[WordPressComApi sharedApi] hasCredentials]) - return; - - NSArray *parameters = @[[self usernameForXmlrpc], - [self passwordForXmlrpc], - token, - @"apple", -#ifdef INTERNAL_BUILD - @"org.wordpress.internal", -#endif - ]; - - WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:kWPcomXMLRPCUrl]]; - [api setAuthorizationHeaderWithToken:self.authToken]; - [api callMethod:@"wpcom.get_mobile_push_notification_settings" - parameters:parameters - success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSDictionary *supportedNotifications = (NSDictionary *)responseObject; - [[NSUserDefaults standardUserDefaults] setObject:supportedNotifications forKey:@"notification_preferences"]; - if (success) - success(); - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) - failure(error); - }]; -} - -- (void)syncPushNotificationInfo { - NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; - if( nil == token ) return; //no apns token available - - if(![[WordPressComApi sharedApi] hasCredentials]) - return; - - NSString *authURL = kNotificationAuthURL; - - // Send a multicall for register the token and retrieval of push notification settings - NSMutableArray *operations = [NSMutableArray arrayWithCapacity:2]; - WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:authURL]]; - - [api setAuthorizationHeaderWithToken:self.authToken]; - -#ifdef DEBUG - NSNumber *production = @NO; -#else - NSNumber *production = @YES; -#endif - - NSDictionary *tokenOptions = @{ - @"device_family": @"apple", - @"device_model": [UIDeviceHardware platform], - @"device_name": [[UIDevice currentDevice] name], - @"device_uuid": [[UIDevice currentDevice] wordpressIdentifier], - @"production": production, - @"app_version": [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"], - @"os_version": [[UIDevice currentDevice] systemVersion], -#ifdef INTERNAL_BUILD - @"app_secret_key": @"org.wordpress.internal", -#endif - }; - NSArray *parameters = @[ - [self usernameForXmlrpc], - [self passwordForXmlrpc], - token, - tokenOptions - ]; - WPXMLRPCRequest *tokenRequest = [api XMLRPCRequestWithMethod:@"wpcom.mobile_push_register_token" parameters:parameters]; - WPXMLRPCRequestOperation *tokenOperation = [api XMLRPCRequestOperationWithRequest:tokenRequest success:^(AFHTTPRequestOperation *operation, id responseObject) { - WPFLog(@"Registered token %@" , token); - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - WPFLog(@"Couldn't register token: %@", [error localizedDescription]); - }]; - - [operations addObject:tokenOperation]; - - NSArray *settingsParameters = @[[self usernameForXmlrpc], - [self passwordForXmlrpc], - token, - @"apple", -#ifdef INTERNAL_BUILD - @"org.wordpress.internal", -#endif - ]; - WPXMLRPCRequest *settingsRequest = [api XMLRPCRequestWithMethod:@"wpcom.get_mobile_push_notification_settings" parameters:settingsParameters]; - WPXMLRPCRequestOperation *settingsOperation = [api XMLRPCRequestOperationWithRequest:settingsRequest success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSDictionary *supportedNotifications = (NSDictionary *)responseObject; - [[NSUserDefaults standardUserDefaults] setObject:supportedNotifications forKey:@"notification_preferences"]; - WPFLog(@"Notification settings loaded!"); - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - WPFLog(@"Failed to receive supported notification list: %@", [error localizedDescription]); - }]; - - [operations addObject:settingsOperation]; - - AFHTTPRequestOperation *combinedOperation = [api combinedHTTPRequestOperationWithOperations:operations success:^(AFHTTPRequestOperation *operation, id responseObject) {} failure:^(AFHTTPRequestOperation *operation, NSError *error) {}]; - [api enqueueHTTPRequestOperation:combinedOperation]; -} - -- (void)checkForNewUnseenNotifications { - NSDictionary *params = @{ @"unread":@"true", @"number":@"20", @"num_note_items":@"20", @"fields" : WordPressComApiNotificationFields }; - [self getPath:@"notifications" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSNumber *last_seen_time = [responseObject objectForKey:@"last_seen_time"]; - NSArray *notes = [responseObject objectForKey:@"notes"]; - if ([notes count] > 0) { - NSMutableArray *unseenNotes = [[NSMutableArray alloc] initWithCapacity:[notes count]]; - [notes enumerateObjectsUsingBlock:^(id noteData, NSUInteger idx, BOOL *stop) { - NSNumber *timestamp = [noteData objectForKey:@"timestamp"]; - if ([timestamp compare:last_seen_time] == NSOrderedDescending) { - [unseenNotes addObject:noteData]; - } - }]; - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc postNotificationName:WordPressComApiUnseenNotesNotification - object:self - userInfo:@{ - WordPressComApiNotesUserInfoKey : unseenNotes, - WordPressComApiUnseenNoteCountInfoKey : [NSNumber numberWithInteger:[unseenNotes count]] - }]; - } - - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - - }]; -} - -- (void)checkNotificationsSuccess:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - [self getNotificationsBefore:nil success:success failure:failure]; -} - -- (void)getNotificationsSince:(NSNumber *)timestamp success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - NSDictionary *parameters; - if (timestamp != nil) { - parameters = @{ @"since" : timestamp }; - } - [self getNotificationsWithParameters:parameters success:success failure:failure]; - -} - -- (void)getNotificationsBefore:(NSNumber *)timestamp success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - NSDictionary *parameters; - if (timestamp != nil) { - parameters = @{ @"before" : timestamp }; - } - [self getNotificationsWithParameters:parameters success:success failure:failure]; -} - -- (void)getNotificationsWithParameters:(NSDictionary *)parameters success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - NSMutableDictionary *requestParameters = [NSMutableDictionary dictionaryWithDictionary:parameters]; - - [requestParameters setObject:WordPressComApiNotificationFields forKey:@"fields"]; - [requestParameters setObject:[NSNumber numberWithInt:20] forKey:@"number"]; - [requestParameters setObject:[NSNumber numberWithInt:20] forKey:@"num_note_items"]; - - // TODO: Check for unread notifications and notify with the number of unread notifications - - [self getPath:@"notifications/" parameters:requestParameters success:^(AFHTTPRequestOperation *operation, id responseObject){ - [Note syncNotesWithResponse:[responseObject objectForKey:@"notes"]]; - if (success != nil ) success( operation, responseObject ); - - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) failure(operation, error); - }]; -} - -- (void)refreshNotifications:(NSArray *)notes fields:(NSString *)fields success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - // No notes? Then there's nothing to sync - if ([notes count] == 0) { - return; - } - NSMutableArray *noteIDs = [[NSMutableArray alloc] initWithCapacity:[notes count]]; - [notes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - [noteIDs addObject:[(Note *)obj noteID]]; - }]; - if (fields == nil) { - fields = WordPressComApiNotificationFields; - } - NSDictionary *params = @{ - @"fields" : fields, - @"ids" : noteIDs - }; - NSManagedObjectContext *context = [(Note *)[notes objectAtIndex:0] managedObjectContext]; - [self getPath:@"notifications/" parameters:params success:^(AFHTTPRequestOperation *operation, id response){ - NSError *error; - NSArray *notesData = [response objectForKey:@"notes"]; - for (int i=0; i < [notes count]; i++) { - if ([notesData count] > i) { - Note *note = [notes objectAtIndex:i]; - if (![note isDeleted] && [note managedObjectContext]) { - [note updateAttributes:[notesData objectAtIndex:i]]; - } - } - } - if(![context save:&error]){ - NSLog(@"Unable to update note: %@", error); - } - if (success != nil) success(operation, response); - } failure:failure ]; -} - -- (void)markNoteAsRead:(NSString *)noteID success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - - NSDictionary *params = @{ @"counts" : @{ noteID : @"1" } }; - - [self postPath:@"notifications/read" - parameters:params - success:success - failure:failure]; - -} - -- (void)updateNoteLastSeenTime:(NSNumber *)timestamp success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - - [self postPath:@"notifications/seen" parameters:@{ @"time" : timestamp } success:success failure:failure]; - -} - -- (void)followBlog:(NSUInteger)blogID isFollowing:(bool)following success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - - NSString *followPath = [NSString stringWithFormat: @"sites/%d/follows/new", blogID]; - if (following) - followPath = [followPath stringByReplacingOccurrencesOfString:@"new" withString:@"mine/delete"]; - - NSString *message = following ? NSLocalizedString(@"Unfollowed", @"User unfollowed a blog") : NSLocalizedString(@"Followed", @"User followed a blog"); - NSString *imageName = [NSString stringWithFormat:@"action_icon_%@", (following) ? @"unfollowed" : @"followed"]; - [WPToast showToastWithMessage:message andImage:[UIImage imageNamed:imageName]]; - - [self postPath:followPath - parameters:nil - success:^(AFHTTPRequestOperation *operation, id responseObject){ - if (success != nil) success(operation, responseObject); - } - failure:failure]; -} - -- (void)moderateComment:(NSUInteger)blogID forCommentID:(NSUInteger)commentID withStatus:(NSString *)commentStatus success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - - NSString *commentPath = [NSString stringWithFormat: @"sites/%d/comments/%d", blogID, commentID]; - - [self postPath:commentPath - parameters:@{ @"status" : commentStatus } - success:success - failure:failure]; -} - -- (void)replyToComment:(NSUInteger)blogID forCommentID:(NSUInteger)commentID withReply:(NSString *)reply success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - - NSString *replyPath = [NSString stringWithFormat: @"sites/%d/comments/%d/replies/new", blogID, commentID]; - - [self postPath:replyPath - parameters:@{ @"content" : reply } - success:success - failure:failure]; -} - -/* HACK: temporary fix for cases where password is nil - We believe jetpack settings might be causing this, but since we're actually doing authentication - with the authToken, we don't care that much about username/password in this method - */ -- (NSString *)usernameForXmlrpc { - NSString *username = self.username; - if (!username) - username = @""; - return username; -} - -- (NSString *)passwordForXmlrpc { - NSString *password = self.password; - if (!password) - password = @""; - return password; -} -/* HACK ENDS */ - -#pragma mark - Oauth methods - -- (NSString *)authToken { - return _authToken; -} - -- (void)setAuthToken:(NSString *)authToken { - _authToken = authToken; - NSError *error; - if (_authToken) { - [self setAuthorizationHeaderWithToken:authToken]; - [SFHFKeychainUtils storeUsername:self.username - andPassword:authToken - forServiceName:WordPressComApiOauthServiceName - updateExisting:YES - error:&error]; - } else { - [self clearAuthorizationHeader]; - [SFHFKeychainUtils deleteItemForUsername:self.username - andServiceName:WordPressComApiOauthServiceName - error:&error]; - } -} - -- (void)setAuthorizationHeaderWithToken:(NSString *)token { - [self setDefaultHeader:@"Authorization" value:[NSString stringWithFormat:@"Bearer %@", token]]; -} - -+ (NSString *)WordPressAppId { - return [WordPressComApiCredentials client]; -} - -+ (NSString *)WordPressAppSecret { - return [WordPressComApiCredentials secret]; -} - -- (NSString *)errorMessageForError:(NSError *)error -{ - NSString *errorCode = [error.userInfo objectForKey:WordPressComApiErrorCodeKey]; - NSString *errorMessage = [[error.userInfo objectForKey:NSLocalizedDescriptionKey] stringByStrippingHTML]; - - if ([errorCode isEqualToString:@"username_only_lowercase_letters_and_numbers"]) { - return NSLocalizedString(@"Sorry, usernames can only contain lowercase letters (a-z) and numbers.", nil); - } else if ([errorCode isEqualToString:@"username_required"]) { - return NSLocalizedString(@"Please enter a username.", nil); - } else if ([errorCode isEqualToString:@"username_not_allowed"]) { - return NSLocalizedString(@"That username is not allowed.", nil); - } else if ([errorCode isEqualToString:@"email_cant_be_used_to_signup"]) { - return NSLocalizedString(@"You cannot use that email address to signup. We are having problems with them blocking some of our email. Please use another email provider.", nil); - } else if ([errorCode isEqualToString:@"username_must_be_at_least_four_characters"]) { - return NSLocalizedString(@"Username must be at least 4 characters.", nil); - } else if ([errorCode isEqualToString:@"username_contains_invalid_characters"]) { - return NSLocalizedString(@"Sorry, usernames may not contain the character “_”!", nil); - } else if ([errorCode isEqualToString:@"username_must_include_letters"]) { - return NSLocalizedString(@"Sorry, usernames must have letters (a-z) too!", nil); - } else if ([errorCode isEqualToString:@"email_not_allowed"]) { - return NSLocalizedString(@"Sorry, that email address is not allowed!", nil); - } else if ([errorCode isEqualToString:@"username_exists"]) { - return NSLocalizedString(@"Sorry, that username already exists!", nil); - } else if ([errorCode isEqualToString:@"email_exists"]) { - return NSLocalizedString(@"Sorry, that email address is already being used!", nil); - } else if ([errorCode isEqualToString:@"username_reserved_but_may_be_available"]) { - return NSLocalizedString(@"That username is currently reserved but may be available in a couple of days.", nil); - } else if ([errorCode isEqualToString:@"username_unavailable"]) { - return NSLocalizedString(@"Sorry, that username is unavailable.", nil); - } else if ([errorCode isEqualToString:@"email_reserved"]) { - return NSLocalizedString(@"That email address has already been used. Please check your inbox for an activation email. If you don't activate you can try again in a few days.", nil); - } else if ([errorCode isEqualToString:@"blog_name_required"]) { - return NSLocalizedString(@"Please enter a site address.", nil); - } else if ([errorCode isEqualToString:@"blog_name_not_allowed"]) { - return NSLocalizedString(@"That site address is not allowed.", nil); - } else if ([errorCode isEqualToString:@"blog_name_must_be_at_least_four_characters"]) { - return NSLocalizedString(@"Site address must be at least 4 characters.", nil); - } else if ([errorCode isEqualToString:@"blog_name_must_be_less_than_sixty_four_characters"]) { - return NSLocalizedString(@"The site address must be shorter than 64 characters.", nil); - } else if ([errorCode isEqualToString:@"blog_name_contains_invalid_characters"]) { - return NSLocalizedString(@"Sorry, site addresses may not contain the character “_”!", nil); - } else if ([errorCode isEqualToString:@"blog_name_cant_be_used"]) { - return NSLocalizedString(@"Sorry, you may not use that site address.", nil); - } else if ([errorCode isEqualToString:@"blog_name_only_lowercase_letters_and_numbers"]) { - return NSLocalizedString(@"Sorry, site addresses can only contain lowercase letters (a-z) and numbers.", nil); - } else if ([errorCode isEqualToString:@"blog_name_must_include_letters"]) { - return NSLocalizedString(@"Sorry, site addresses must have letters too!", nil); - } else if ([errorCode isEqualToString:@"blog_name_exists"]) { - return NSLocalizedString(@"Sorry, that site already exists!", nil); - } else if ([errorCode isEqualToString:@"blog_name_reserved"]) { - return NSLocalizedString(@"Sorry, that site is reserved!", nil); - } else if ([errorCode isEqualToString:@"blog_name_reserved_but_may_be_available"]) { - return NSLocalizedString(@"That site is currently reserved but may be available in a couple days.", nil); - } else if ([errorCode isEqualToString:@"password_invalid"]) { - return NSLocalizedString(@"Your password is invalid because it does not meet our security guidelines. Please try a more complex password.", @""); - } else if ([errorCode isEqualToString:@"blog_title_invalid"]) { - return NSLocalizedString(@"Invalid Site Title", @""); - } else if ([errorCode isEqualToString:@"username_illegal_wpcom"]) { - // Try to extract the illegal phrase - NSError *error; - NSRegularExpression *regEx = [NSRegularExpression regularExpressionWithPattern:@"\"([^\"].*)\"" options:NSRegularExpressionCaseInsensitive error:&error]; - NSArray *matches = [regEx matchesInString:errorMessage options:0 range:NSMakeRange(0, [errorMessage length])]; - NSString *invalidPhrase = @""; - for (NSTextCheckingResult *result in matches) { - if ([result numberOfRanges] < 2) - continue; - NSRange invalidTextRange = [result rangeAtIndex:1]; - invalidPhrase = [NSString stringWithFormat:@" (\"%@\")", [errorMessage substringWithRange:invalidTextRange]]; - } - - return [NSString stringWithFormat:NSLocalizedString(@"Sorry, but your username contains an invalid phrase%@.", @"This error message occurs when a user tries to create a username that contains an invalid phrase for WordPress.com. The %@ may include the phrase in question if it was sent down by the API"), invalidPhrase]; - } - - // We have a few ambiguous errors that come back from the api, they sometimes have error messages included so - // attempt to return that if possible. If not fall back to a generic error. - NSDictionary *ambiguousErrors = @{ - @"email_invalid": NSLocalizedString(@"Please enter a valid email address.", nil), - @"blog_name_invalid" : NSLocalizedString(@"Invalid Site Address", @""), - @"username_invalid" : NSLocalizedString(@"Invalid username", @"") - }; - if ([ambiguousErrors.allKeys containsObject:errorCode]) { - if (errorMessage != nil) { - return errorMessage; - } else { - return [ambiguousErrors objectForKey:errorCode]; - } - } - - // Return an error message if there's one included rather than the unhelpful "Unknown Error" - if (errorMessage != nil) { - return errorMessage; - } else { - return NSLocalizedString(@"Unknown error", nil); - } -} - -@end From 4e5869e76930a7a4b40ce1c06907109372185e0b Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 27 Nov 2013 20:20:26 +0100 Subject: [PATCH 35/64] These are not the files you are looking for --- .../HockeySDK.xcodeproj/project.pbxproj.orig | 1319 ----------------- .../WordPress 13.xcdatamodel/contents.orig | 353 ----- 2 files changed, 1672 deletions(-) delete mode 100644 Pods/HockeySDK/Support/HockeySDK.xcodeproj/project.pbxproj.orig delete mode 100644 WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents.orig diff --git a/Pods/HockeySDK/Support/HockeySDK.xcodeproj/project.pbxproj.orig b/Pods/HockeySDK/Support/HockeySDK.xcodeproj/project.pbxproj.orig deleted file mode 100644 index cee7a511fa6f..000000000000 --- a/Pods/HockeySDK/Support/HockeySDK.xcodeproj/project.pbxproj.orig +++ /dev/null @@ -1,1319 +0,0 @@ -// !$*UTF8*$! -{ - archiveVersion = 1; - classes = { - }; - objectVersion = 46; - objects = { - -/* Begin PBXAggregateTarget section */ - 1E4F61E91621AD970033EFC5 /* HockeySDK Framework */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 1E4F61EA1621AD970033EFC5 /* Build configuration list for PBXAggregateTarget "HockeySDK Framework" */; - buildPhases = ( - 1E4F61ED1621ADE70033EFC5 /* Build universal embedded framework */, - ); - dependencies = ( - 1E754E431621F6290070AB92 /* PBXTargetDependency */, - ); - name = "HockeySDK Framework"; - productName = "HockeySDK Framework"; - }; - 1E8E66AD15BC3D7700632A2E /* HockeySDK Documentation */ = { - isa = PBXAggregateTarget; - buildConfigurationList = 1E8E66B015BC3D7700632A2E /* Build configuration list for PBXAggregateTarget "HockeySDK Documentation" */; - buildPhases = ( - 1E8E66B215BC3D8200632A2E /* ShellScript */, - ); - dependencies = ( - ); - name = "HockeySDK Documentation"; - productName = Documentation; - }; -/* End PBXAggregateTarget section */ - -/* Begin PBXBuildFile section */ - 1E0829001708F69A0073050E /* BITStoreUpdateManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E0828FF1708F69A0073050E /* BITStoreUpdateManagerDelegate.h */; }; - 1E0FEE28173BDB260061331F /* BITKeychainUtils.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E0FEE26173BDB260061331F /* BITKeychainUtils.h */; }; - 1E0FEE29173BDB260061331F /* BITKeychainUtils.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E0FEE27173BDB260061331F /* BITKeychainUtils.m */; }; - 1E1127C416580C87007067A2 /* buttonRoundedDelete.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127BC16580C87007067A2 /* buttonRoundedDelete.png */; }; - 1E1127C516580C87007067A2 /* buttonRoundedDelete@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127BD16580C87007067A2 /* buttonRoundedDelete@2x.png */; }; - 1E1127C616580C87007067A2 /* buttonRoundedDeleteHighlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127BE16580C87007067A2 /* buttonRoundedDeleteHighlighted.png */; }; - 1E1127C716580C87007067A2 /* buttonRoundedDeleteHighlighted@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127BF16580C87007067A2 /* buttonRoundedDeleteHighlighted@2x.png */; }; - 1E1127C816580C87007067A2 /* buttonRoundedRegular.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127C016580C87007067A2 /* buttonRoundedRegular.png */; }; - 1E1127C916580C87007067A2 /* buttonRoundedRegular@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127C116580C87007067A2 /* buttonRoundedRegular@2x.png */; }; - 1E1127CA16580C87007067A2 /* buttonRoundedRegularHighlighted.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127C216580C87007067A2 /* buttonRoundedRegularHighlighted.png */; }; - 1E1127CB16580C87007067A2 /* buttonRoundedRegularHighlighted@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E1127C316580C87007067A2 /* buttonRoundedRegularHighlighted@2x.png */; }; - 1E49A43C1612223B00463151 /* BITFeedbackComposeViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A42D1612223B00463151 /* BITFeedbackComposeViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E49A43F1612223B00463151 /* BITFeedbackComposeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A42E1612223B00463151 /* BITFeedbackComposeViewController.m */; }; - 1E49A4421612223B00463151 /* BITFeedbackListViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A42F1612223B00463151 /* BITFeedbackListViewCell.h */; }; - 1E49A4451612223B00463151 /* BITFeedbackListViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4301612223B00463151 /* BITFeedbackListViewCell.m */; }; - 1E49A4481612223B00463151 /* BITFeedbackListViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4311612223B00463151 /* BITFeedbackListViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E49A44B1612223B00463151 /* BITFeedbackListViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4321612223B00463151 /* BITFeedbackListViewController.m */; }; - 1E49A44E1612223B00463151 /* BITFeedbackManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4331612223B00463151 /* BITFeedbackManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E49A4511612223B00463151 /* BITFeedbackManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4341612223B00463151 /* BITFeedbackManager.m */; }; - 1E49A4541612223B00463151 /* BITFeedbackManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4351612223B00463151 /* BITFeedbackManagerPrivate.h */; }; - 1E49A4571612223B00463151 /* BITFeedbackMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4361612223B00463151 /* BITFeedbackMessage.h */; }; - 1E49A45A1612223B00463151 /* BITFeedbackMessage.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4371612223B00463151 /* BITFeedbackMessage.m */; }; - 1E49A45D1612223B00463151 /* BITFeedbackUserDataViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4381612223B00463151 /* BITFeedbackUserDataViewController.h */; }; - 1E49A4601612223B00463151 /* BITFeedbackUserDataViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4391612223B00463151 /* BITFeedbackUserDataViewController.m */; }; - 1E49A46D1612226D00463151 /* BITAppVersionMetaInfo.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4621612226D00463151 /* BITAppVersionMetaInfo.h */; }; - 1E49A4701612226D00463151 /* BITAppVersionMetaInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4631612226D00463151 /* BITAppVersionMetaInfo.m */; }; - 1E49A4731612226D00463151 /* BITUpdateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4641612226D00463151 /* BITUpdateManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E49A4761612226D00463151 /* BITUpdateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4651612226D00463151 /* BITUpdateManager.m */; }; - 1E49A4791612226D00463151 /* BITUpdateManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4661612226D00463151 /* BITUpdateManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E49A47C1612226D00463151 /* BITUpdateManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4671612226D00463151 /* BITUpdateManagerPrivate.h */; }; - 1E49A47F1612226D00463151 /* BITUpdateViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4681612226D00463151 /* BITUpdateViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E49A4821612226D00463151 /* BITUpdateViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4691612226D00463151 /* BITUpdateViewController.m */; }; - 1E49A4851612226D00463151 /* BITUpdateViewControllerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A46A1612226D00463151 /* BITUpdateViewControllerPrivate.h */; }; - 1E49A4AF161222B900463151 /* BITHockeyBaseManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A0161222B900463151 /* BITHockeyBaseManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E49A4B2161222B900463151 /* BITHockeyBaseManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4A1161222B900463151 /* BITHockeyBaseManager.m */; }; - 1E49A4B5161222B900463151 /* BITHockeyBaseManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A2161222B900463151 /* BITHockeyBaseManagerPrivate.h */; }; - 1E49A4B8161222B900463151 /* BITHockeyBaseViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A3161222B900463151 /* BITHockeyBaseViewController.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E49A4BB161222B900463151 /* BITHockeyBaseViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4A4161222B900463151 /* BITHockeyBaseViewController.m */; }; - 1E49A4BE161222B900463151 /* BITHockeyHelper.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A5161222B900463151 /* BITHockeyHelper.h */; }; - 1E49A4C1161222B900463151 /* BITHockeyHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4A6161222B900463151 /* BITHockeyHelper.m */; }; - 1E49A4C4161222B900463151 /* BITAppStoreHeader.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A7161222B900463151 /* BITAppStoreHeader.h */; }; - 1E49A4C7161222B900463151 /* BITAppStoreHeader.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4A8161222B900463151 /* BITAppStoreHeader.m */; }; - 1E49A4CA161222B900463151 /* BITStoreButton.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4A9161222B900463151 /* BITStoreButton.h */; }; - 1E49A4CD161222B900463151 /* BITStoreButton.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4AA161222B900463151 /* BITStoreButton.m */; }; - 1E49A4D0161222B900463151 /* BITWebTableViewCell.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4AB161222B900463151 /* BITWebTableViewCell.h */; }; - 1E49A4D3161222B900463151 /* BITWebTableViewCell.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4AC161222B900463151 /* BITWebTableViewCell.m */; }; - 1E49A4D8161222D400463151 /* HockeySDKPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E49A4D4161222D400463151 /* HockeySDKPrivate.h */; }; - 1E49A4DB161222D400463151 /* HockeySDKPrivate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E49A4D5161222D400463151 /* HockeySDKPrivate.m */; }; - 1E5954D315B6F24A00A03429 /* BITHockeyManager.m in Sources */ = {isa = PBXBuildFile; fileRef = E41EB466148D7BF50015DEDC /* BITHockeyManager.m */; }; - 1E5954DC15B6F24A00A03429 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E400561D148D79B500EB22B9 /* Foundation.framework */; }; - 1E5954DD15B6F24A00A03429 /* CrashReporter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */; }; - 1E59559A15B6FDA500A03429 /* BITHockeyManager.h in Headers */ = {isa = PBXBuildFile; fileRef = E41EB465148D7BF50015DEDC /* BITHockeyManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E59559B15B6FDA500A03429 /* HockeySDK.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E71509A15B5C76F004E88FF /* HockeySDK.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E5955C615B71C8600A03429 /* authorize_denied.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955BB15B71C8600A03429 /* authorize_denied.png */; }; - 1E5955C715B71C8600A03429 /* authorize_denied@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955BC15B71C8600A03429 /* authorize_denied@2x.png */; }; - 1E5955CA15B71C8600A03429 /* bg.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955BF15B71C8600A03429 /* bg.png */; }; - 1E5955CB15B71C8600A03429 /* buttonHighlight.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955C015B71C8600A03429 /* buttonHighlight.png */; }; - 1E5955CC15B71C8600A03429 /* buttonHighlight@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955C115B71C8600A03429 /* buttonHighlight@2x.png */; }; - 1E5955CF15B71C8600A03429 /* IconGradient.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955C415B71C8600A03429 /* IconGradient.png */; }; - 1E5955D015B71C8600A03429 /* IconGradient@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1E5955C515B71C8600A03429 /* IconGradient@2x.png */; }; - 1E5955FD15B7877B00A03429 /* BITHockeyManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E5A459216F0DFC200B55C04 /* SenTestingKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */; }; - 1E5A459416F0DFC200B55C04 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E5A459316F0DFC200B55C04 /* UIKit.framework */; }; - 1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E400561D148D79B500EB22B9 /* Foundation.framework */; }; - 1E5A459B16F0DFC200B55C04 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1E5A459916F0DFC200B55C04 /* InfoPlist.strings */; }; - 1E5A459E16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */; }; - 1E754E5C1621FBB70070AB92 /* BITCrashManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E754E561621FBB70070AB92 /* BITCrashManager.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E754E5D1621FBB70070AB92 /* BITCrashManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E754E571621FBB70070AB92 /* BITCrashManager.m */; }; - 1E754E5E1621FBB70070AB92 /* BITCrashManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E754E581621FBB70070AB92 /* BITCrashManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1E754E601621FBB70070AB92 /* BITCrashReportTextFormatter.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E754E5A1621FBB70070AB92 /* BITCrashReportTextFormatter.h */; }; - 1E754E611621FBB70070AB92 /* BITCrashReportTextFormatter.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E754E5B1621FBB70070AB92 /* BITCrashReportTextFormatter.m */; }; - 1E7A45FC16F54FB5005B08F1 /* OCHamcrestIOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E7A45FA16F54FB5005B08F1 /* OCHamcrestIOS.framework */; }; - 1E7A45FD16F54FB5005B08F1 /* OCMockitoIOS.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E7A45FB16F54FB5005B08F1 /* OCMockitoIOS.framework */; }; - 1E94F9E116E91330006570AD /* BITStoreUpdateManager.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E94F9DF16E91330006570AD /* BITStoreUpdateManager.h */; }; - 1E94F9E216E91330006570AD /* BITStoreUpdateManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 1E94F9E016E91330006570AD /* BITStoreUpdateManager.m */; }; - 1E94F9E416E9136B006570AD /* BITStoreUpdateManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1E94F9E316E9136B006570AD /* BITStoreUpdateManagerPrivate.h */; }; - 1EA1170016F4D32C001C015C /* libHockeySDK.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 1E5954F215B6F24A00A03429 /* libHockeySDK.a */; }; - 1EA1170116F4D354001C015C /* CrashReporter.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */; }; - 1EA1170416F53B49001C015C /* StoreBundleIdentifierUnknown.json in Resources */ = {isa = PBXBuildFile; fileRef = 1EA1170316F53B49001C015C /* StoreBundleIdentifierUnknown.json */; }; - 1EA1170716F53B91001C015C /* BITTestHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EA1170616F53B91001C015C /* BITTestHelper.m */; }; - 1EA1170916F53E3A001C015C /* StoreBundleIdentifierKnown.json in Resources */ = {isa = PBXBuildFile; fileRef = 1EA1170816F53E3A001C015C /* StoreBundleIdentifierKnown.json */; }; - 1EA1170C16F54A64001C015C /* HockeySDKResources.bundle in Resources */ = {isa = PBXBuildFile; fileRef = 1E59550A15B6F45800A03429 /* HockeySDKResources.bundle */; }; - 1EACC97B162F041E007578C5 /* BITAttributedLabel.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EACC979162F041E007578C5 /* BITAttributedLabel.h */; }; - 1EACC97C162F041E007578C5 /* BITAttributedLabel.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EACC97A162F041E007578C5 /* BITAttributedLabel.m */; }; - 1EAF20A8162DC0F600957B1D /* feedbackActivity@2x~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A4162DC0F600957B1D /* feedbackActivity@2x~ipad.png */; }; - 1EAF20A9162DC0F600957B1D /* feedbackActivity~ipad.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A5162DC0F600957B1D /* feedbackActivity~ipad.png */; }; - 1EAF20AA162DC0F600957B1D /* feedbackActiviy.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A6162DC0F600957B1D /* feedbackActiviy.png */; }; - 1EAF20AB162DC0F600957B1D /* feedbackActiviy@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 1EAF20A7162DC0F600957B1D /* feedbackActiviy@2x.png */; }; - 1EB52FD5167B766100C801D5 /* HockeySDK.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1E59555F15B6F80E00A03429 /* HockeySDK.strings */; }; - 1EC69F601615001500808FD9 /* BITHockeyManagerPrivate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EC69F5D1615001500808FD9 /* BITHockeyManagerPrivate.h */; }; - 1EF95CA6162CB037000AE3AD /* BITFeedbackActivity.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */; }; - 1EF95CAA162CB314000AE3AD /* BITFeedbackComposeViewControllerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E405266217A2AD300096359C /* BITFeedbackManagerDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = E405266117A2AD300096359C /* BITFeedbackManagerDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E48A3DEC17B3ED1C00924C3D /* BITAuthenticator.h in Headers */ = {isa = PBXBuildFile; fileRef = E48A3DEA17B3ED1C00924C3D /* BITAuthenticator.h */; settings = {ATTRIBUTES = (Public, ); }; }; - E48A3DED17B3ED1C00924C3D /* BITAuthenticator.m in Sources */ = {isa = PBXBuildFile; fileRef = E48A3DEB17B3ED1C00924C3D /* BITAuthenticator.m */; }; - E48A3DEF17B3EFF100924C3D /* BITAuthenticatorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E48A3DEE17B3EFF100924C3D /* BITAuthenticatorTests.m */; }; - E4933E8017B66CDA00B11ACC /* BITHTTPOperation.h in Headers */ = {isa = PBXBuildFile; fileRef = E4933E7E17B66CDA00B11ACC /* BITHTTPOperation.h */; }; - E4933E8117B66CDA00B11ACC /* BITHTTPOperation.m in Sources */ = {isa = PBXBuildFile; fileRef = E4933E7F17B66CDA00B11ACC /* BITHTTPOperation.m */; }; - E4B4DB7D17B435550099C67F /* BITAuthenticationViewController.h in Headers */ = {isa = PBXBuildFile; fileRef = E4B4DB7B17B435550099C67F /* BITAuthenticationViewController.h */; }; - E4B4DB7E17B435550099C67F /* BITAuthenticationViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E4B4DB7C17B435550099C67F /* BITAuthenticationViewController.m */; }; -/* End PBXBuildFile section */ - -/* Begin PBXContainerItemProxy section */ - 1E59557D15B6F97100A03429 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = E4005611148D79B500EB22B9 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1E59550915B6F45800A03429; - remoteInfo = HockeySDKResources; - }; - 1E754E421621F6290070AB92 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = E4005611148D79B500EB22B9 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1E8E66AD15BC3D7700632A2E; - remoteInfo = "HockeySDK Documentation"; - }; - 1EA116FE16F4D302001C015C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = E4005611148D79B500EB22B9 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1E5954CB15B6F24A00A03429; - remoteInfo = HockeySDK; - }; - 1EA1170A16F54A5C001C015C /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = E4005611148D79B500EB22B9 /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1E59550915B6F45800A03429; - remoteInfo = HockeySDKResources; - }; -/* End PBXContainerItemProxy section */ - -/* Begin PBXFileReference section */ - 1E0828FF1708F69A0073050E /* BITStoreUpdateManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITStoreUpdateManagerDelegate.h; sourceTree = ""; }; - 1E0FEE26173BDB260061331F /* BITKeychainUtils.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITKeychainUtils.h; sourceTree = ""; }; - 1E0FEE27173BDB260061331F /* BITKeychainUtils.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITKeychainUtils.m; sourceTree = ""; }; - 1E1127BC16580C87007067A2 /* buttonRoundedDelete.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buttonRoundedDelete.png; sourceTree = ""; }; - 1E1127BD16580C87007067A2 /* buttonRoundedDelete@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttonRoundedDelete@2x.png"; sourceTree = ""; }; - 1E1127BE16580C87007067A2 /* buttonRoundedDeleteHighlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buttonRoundedDeleteHighlighted.png; sourceTree = ""; }; - 1E1127BF16580C87007067A2 /* buttonRoundedDeleteHighlighted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttonRoundedDeleteHighlighted@2x.png"; sourceTree = ""; }; - 1E1127C016580C87007067A2 /* buttonRoundedRegular.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buttonRoundedRegular.png; sourceTree = ""; }; - 1E1127C116580C87007067A2 /* buttonRoundedRegular@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttonRoundedRegular@2x.png"; sourceTree = ""; }; - 1E1127C216580C87007067A2 /* buttonRoundedRegularHighlighted.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buttonRoundedRegularHighlighted.png; sourceTree = ""; }; - 1E1127C316580C87007067A2 /* buttonRoundedRegularHighlighted@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttonRoundedRegularHighlighted@2x.png"; sourceTree = ""; }; - 1E36D8B816667611000B134C /* hr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hr; path = hr.lproj/HockeySDK.strings; sourceTree = ""; }; - 1E49A42D1612223B00463151 /* BITFeedbackComposeViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackComposeViewController.h; sourceTree = ""; }; - 1E49A42E1612223B00463151 /* BITFeedbackComposeViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackComposeViewController.m; sourceTree = ""; }; - 1E49A42F1612223B00463151 /* BITFeedbackListViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackListViewCell.h; sourceTree = ""; }; - 1E49A4301612223B00463151 /* BITFeedbackListViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackListViewCell.m; sourceTree = ""; }; - 1E49A4311612223B00463151 /* BITFeedbackListViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackListViewController.h; sourceTree = ""; }; - 1E49A4321612223B00463151 /* BITFeedbackListViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackListViewController.m; sourceTree = ""; }; - 1E49A4331612223B00463151 /* BITFeedbackManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackManager.h; sourceTree = ""; }; - 1E49A4341612223B00463151 /* BITFeedbackManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackManager.m; sourceTree = ""; }; - 1E49A4351612223B00463151 /* BITFeedbackManagerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackManagerPrivate.h; sourceTree = ""; }; - 1E49A4361612223B00463151 /* BITFeedbackMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackMessage.h; sourceTree = ""; }; - 1E49A4371612223B00463151 /* BITFeedbackMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackMessage.m; sourceTree = ""; }; - 1E49A4381612223B00463151 /* BITFeedbackUserDataViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackUserDataViewController.h; sourceTree = ""; }; - 1E49A4391612223B00463151 /* BITFeedbackUserDataViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackUserDataViewController.m; sourceTree = ""; }; - 1E49A4621612226D00463151 /* BITAppVersionMetaInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITAppVersionMetaInfo.h; sourceTree = ""; }; - 1E49A4631612226D00463151 /* BITAppVersionMetaInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITAppVersionMetaInfo.m; sourceTree = ""; }; - 1E49A4641612226D00463151 /* BITUpdateManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITUpdateManager.h; sourceTree = ""; }; - 1E49A4651612226D00463151 /* BITUpdateManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITUpdateManager.m; sourceTree = ""; }; - 1E49A4661612226D00463151 /* BITUpdateManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITUpdateManagerDelegate.h; sourceTree = ""; }; - 1E49A4671612226D00463151 /* BITUpdateManagerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITUpdateManagerPrivate.h; sourceTree = ""; }; - 1E49A4681612226D00463151 /* BITUpdateViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITUpdateViewController.h; sourceTree = ""; }; - 1E49A4691612226D00463151 /* BITUpdateViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITUpdateViewController.m; sourceTree = ""; }; - 1E49A46A1612226D00463151 /* BITUpdateViewControllerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITUpdateViewControllerPrivate.h; sourceTree = ""; }; - 1E49A4A0161222B900463151 /* BITHockeyBaseManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyBaseManager.h; sourceTree = ""; }; - 1E49A4A1161222B900463151 /* BITHockeyBaseManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITHockeyBaseManager.m; sourceTree = ""; }; - 1E49A4A2161222B900463151 /* BITHockeyBaseManagerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyBaseManagerPrivate.h; sourceTree = ""; }; - 1E49A4A3161222B900463151 /* BITHockeyBaseViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyBaseViewController.h; sourceTree = ""; }; - 1E49A4A4161222B900463151 /* BITHockeyBaseViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITHockeyBaseViewController.m; sourceTree = ""; }; - 1E49A4A5161222B900463151 /* BITHockeyHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyHelper.h; sourceTree = ""; }; - 1E49A4A6161222B900463151 /* BITHockeyHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITHockeyHelper.m; sourceTree = ""; }; - 1E49A4A7161222B900463151 /* BITAppStoreHeader.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITAppStoreHeader.h; sourceTree = ""; }; - 1E49A4A8161222B900463151 /* BITAppStoreHeader.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITAppStoreHeader.m; sourceTree = ""; }; - 1E49A4A9161222B900463151 /* BITStoreButton.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITStoreButton.h; sourceTree = ""; }; - 1E49A4AA161222B900463151 /* BITStoreButton.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITStoreButton.m; sourceTree = ""; }; - 1E49A4AB161222B900463151 /* BITWebTableViewCell.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITWebTableViewCell.h; sourceTree = ""; }; - 1E49A4AC161222B900463151 /* BITWebTableViewCell.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITWebTableViewCell.m; sourceTree = ""; }; - 1E49A4D4161222D400463151 /* HockeySDKPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HockeySDKPrivate.h; sourceTree = ""; }; - 1E49A4D5161222D400463151 /* HockeySDKPrivate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HockeySDKPrivate.m; sourceTree = ""; }; - 1E5954F215B6F24A00A03429 /* libHockeySDK.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libHockeySDK.a; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E59550A15B6F45800A03429 /* HockeySDKResources.bundle */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HockeySDKResources.bundle; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E59556015B6F80E00A03429 /* de */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = de; path = de.lproj/HockeySDK.strings; sourceTree = ""; }; - 1E59556415B6F81C00A03429 /* es */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = es; path = es.lproj/HockeySDK.strings; sourceTree = ""; }; - 1E59556615B6F82300A03429 /* fr */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/HockeySDK.strings; sourceTree = ""; }; - 1E59556815B6F82A00A03429 /* it */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = it; path = it.lproj/HockeySDK.strings; sourceTree = ""; }; - 1E59556A15B6F83100A03429 /* ja */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ja; path = ja.lproj/HockeySDK.strings; sourceTree = ""; }; - 1E59557015B6F84700A03429 /* pt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = pt; path = pt.lproj/HockeySDK.strings; sourceTree = ""; }; - 1E59557215B6F84D00A03429 /* ru */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.strings; name = ru; path = ru.lproj/HockeySDK.strings; sourceTree = ""; }; - 1E5955BB15B71C8600A03429 /* authorize_denied.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = authorize_denied.png; sourceTree = ""; }; - 1E5955BC15B71C8600A03429 /* authorize_denied@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "authorize_denied@2x.png"; sourceTree = ""; }; - 1E5955BF15B71C8600A03429 /* bg.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = bg.png; sourceTree = ""; }; - 1E5955C015B71C8600A03429 /* buttonHighlight.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = buttonHighlight.png; sourceTree = ""; }; - 1E5955C115B71C8600A03429 /* buttonHighlight@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "buttonHighlight@2x.png"; sourceTree = ""; }; - 1E5955C415B71C8600A03429 /* IconGradient.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = IconGradient.png; sourceTree = ""; }; - 1E5955C515B71C8600A03429 /* IconGradient@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "IconGradient@2x.png"; sourceTree = ""; }; - 1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyManagerDelegate.h; sourceTree = ""; }; - 1E5A459016F0DFC200B55C04 /* HockeySDKTests.octest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = HockeySDKTests.octest; sourceTree = BUILT_PRODUCTS_DIR; }; - 1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SenTestingKit.framework; path = Library/Frameworks/SenTestingKit.framework; sourceTree = DEVELOPER_DIR; }; - 1E5A459316F0DFC200B55C04 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = Library/Frameworks/UIKit.framework; sourceTree = DEVELOPER_DIR; }; - 1E5A459816F0DFC200B55C04 /* HockeySDKTests-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HockeySDKTests-Info.plist"; sourceTree = ""; }; - 1E5A459A16F0DFC200B55C04 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; - 1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BITStoreUpdateManagerTests.m; sourceTree = ""; }; - 1E5A459F16F0DFC200B55C04 /* HockeySDKTests-Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "HockeySDKTests-Prefix.pch"; sourceTree = ""; }; - 1E66CA9115D4100500F35BED /* buildnumber.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = buildnumber.xcconfig; sourceTree = ""; }; - 1E6DDCEE169E290C0076C65D /* ro */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = ro; path = ro.lproj/HockeySDK.strings; sourceTree = ""; }; - 1E6F0450167B5E5600ED1C86 /* pt-PT */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "pt-PT"; path = "pt-PT.lproj/HockeySDK.strings"; sourceTree = ""; }; - 1E71509A15B5C76F004E88FF /* HockeySDK.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = HockeySDK.h; sourceTree = ""; }; - 1E754DC61621BC170070AB92 /* HockeySDK.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; path = HockeySDK.xcconfig; sourceTree = ""; }; - 1E754E561621FBB70070AB92 /* BITCrashManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITCrashManager.h; sourceTree = ""; }; - 1E754E571621FBB70070AB92 /* BITCrashManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITCrashManager.m; sourceTree = ""; }; - 1E754E581621FBB70070AB92 /* BITCrashManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITCrashManagerDelegate.h; sourceTree = ""; }; - 1E754E5A1621FBB70070AB92 /* BITCrashReportTextFormatter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITCrashReportTextFormatter.h; sourceTree = ""; }; - 1E754E5B1621FBB70070AB92 /* BITCrashReportTextFormatter.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITCrashReportTextFormatter.m; sourceTree = ""; }; - 1E7A45FA16F54FB5005B08F1 /* OCHamcrestIOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OCHamcrestIOS.framework; sourceTree = ""; }; - 1E7A45FB16F54FB5005B08F1 /* OCMockitoIOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; path = OCMockitoIOS.framework; sourceTree = ""; }; - 1E94F9DF16E91330006570AD /* BITStoreUpdateManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITStoreUpdateManager.h; sourceTree = ""; }; - 1E94F9E016E91330006570AD /* BITStoreUpdateManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITStoreUpdateManager.m; sourceTree = ""; }; - 1E94F9E316E9136B006570AD /* BITStoreUpdateManagerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITStoreUpdateManagerPrivate.h; sourceTree = ""; }; - 1EA1170316F53B49001C015C /* StoreBundleIdentifierUnknown.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = StoreBundleIdentifierUnknown.json; sourceTree = ""; }; - 1EA1170516F53B91001C015C /* BITTestHelper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITTestHelper.h; sourceTree = ""; }; - 1EA1170616F53B91001C015C /* BITTestHelper.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITTestHelper.m; sourceTree = ""; }; - 1EA1170816F53E3A001C015C /* StoreBundleIdentifierKnown.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = StoreBundleIdentifierKnown.json; sourceTree = ""; }; - 1EA512DF167F7EF000FC9FBA /* zh-Hans */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = "zh-Hans"; path = "zh-Hans.lproj/HockeySDK.strings"; sourceTree = ""; }; - 1EACC979162F041E007578C5 /* BITAttributedLabel.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITAttributedLabel.h; sourceTree = ""; }; - 1EACC97A162F041E007578C5 /* BITAttributedLabel.m */ = {isa = PBXFileReference; fileEncoding = 4; indentWidth = 4; lastKnownFileType = sourcecode.c.objc; path = BITAttributedLabel.m; sourceTree = ""; }; - 1EAF20A4162DC0F600957B1D /* feedbackActivity@2x~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "feedbackActivity@2x~ipad.png"; sourceTree = ""; }; - 1EAF20A5162DC0F600957B1D /* feedbackActivity~ipad.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "feedbackActivity~ipad.png"; sourceTree = ""; }; - 1EAF20A6162DC0F600957B1D /* feedbackActiviy.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = feedbackActiviy.png; sourceTree = ""; }; - 1EAF20A7162DC0F600957B1D /* feedbackActiviy@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "feedbackActiviy@2x.png"; sourceTree = ""; }; - 1EB52FC3167B73D400C801D5 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/HockeySDK.strings; sourceTree = ""; }; - 1EC69F5D1615001500808FD9 /* BITHockeyManagerPrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyManagerPrivate.h; sourceTree = ""; }; - 1EDA60CF15C2C1450032D10B /* HockeySDK-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "HockeySDK-Info.plist"; sourceTree = ""; }; - 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackActivity.h; sourceTree = ""; }; - 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITFeedbackActivity.m; sourceTree = ""; }; - 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackComposeViewControllerDelegate.h; sourceTree = ""; }; - BEE0207C16C5107E004426EA /* hu */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = hu; path = hu.lproj/HockeySDK.strings; sourceTree = ""; }; - E400561D148D79B500EB22B9 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; - E405266117A2AD300096359C /* BITFeedbackManagerDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITFeedbackManagerDelegate.h; sourceTree = ""; }; - E41EB465148D7BF50015DEDC /* BITHockeyManager.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHockeyManager.h; sourceTree = ""; }; - E41EB466148D7BF50015DEDC /* BITHockeyManager.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITHockeyManager.m; sourceTree = ""; }; - E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CrashReporter.framework; path = ../Vendor/CrashReporter.framework; sourceTree = ""; }; - E48A3DEA17B3ED1C00924C3D /* BITAuthenticator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITAuthenticator.h; sourceTree = ""; }; - E48A3DEB17B3ED1C00924C3D /* BITAuthenticator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITAuthenticator.m; sourceTree = ""; }; - E48A3DEE17B3EFF100924C3D /* BITAuthenticatorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITAuthenticatorTests.m; sourceTree = ""; }; - E48A3DF117B408F400924C3D /* BITAuthenticator_Private.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BITAuthenticator_Private.h; sourceTree = ""; }; - E4933E7E17B66CDA00B11ACC /* BITHTTPOperation.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITHTTPOperation.h; sourceTree = ""; }; - E4933E7F17B66CDA00B11ACC /* BITHTTPOperation.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITHTTPOperation.m; sourceTree = ""; }; - E4B4DB7B17B435550099C67F /* BITAuthenticationViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BITAuthenticationViewController.h; sourceTree = ""; }; - E4B4DB7C17B435550099C67F /* BITAuthenticationViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BITAuthenticationViewController.m; sourceTree = ""; }; -/* End PBXFileReference section */ - -/* Begin PBXFrameworksBuildPhase section */ - 1E5954DB15B6F24A00A03429 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E5954DC15B6F24A00A03429 /* Foundation.framework in Frameworks */, - 1E5954DD15B6F24A00A03429 /* CrashReporter.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E59550715B6F45800A03429 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E5A458C16F0DFC200B55C04 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1EA1170016F4D32C001C015C /* libHockeySDK.a in Frameworks */, - 1E5A459216F0DFC200B55C04 /* SenTestingKit.framework in Frameworks */, - 1E5A459416F0DFC200B55C04 /* UIKit.framework in Frameworks */, - 1EA1170116F4D354001C015C /* CrashReporter.framework in Frameworks */, - 1E5A459516F0DFC200B55C04 /* Foundation.framework in Frameworks */, - 1E7A45FC16F54FB5005B08F1 /* OCHamcrestIOS.framework in Frameworks */, - 1E7A45FD16F54FB5005B08F1 /* OCMockitoIOS.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXFrameworksBuildPhase section */ - -/* Begin PBXGroup section */ - 1E5955A415B71BDC00A03429 /* Images */ = { - isa = PBXGroup; - children = ( - 1E5955BB15B71C8600A03429 /* authorize_denied.png */, - 1E5955BC15B71C8600A03429 /* authorize_denied@2x.png */, - 1E5955BF15B71C8600A03429 /* bg.png */, - 1E5955C015B71C8600A03429 /* buttonHighlight.png */, - 1E5955C115B71C8600A03429 /* buttonHighlight@2x.png */, - 1E1127BC16580C87007067A2 /* buttonRoundedDelete.png */, - 1E1127BD16580C87007067A2 /* buttonRoundedDelete@2x.png */, - 1E1127BE16580C87007067A2 /* buttonRoundedDeleteHighlighted.png */, - 1E1127BF16580C87007067A2 /* buttonRoundedDeleteHighlighted@2x.png */, - 1E1127C016580C87007067A2 /* buttonRoundedRegular.png */, - 1E1127C116580C87007067A2 /* buttonRoundedRegular@2x.png */, - 1E1127C216580C87007067A2 /* buttonRoundedRegularHighlighted.png */, - 1E1127C316580C87007067A2 /* buttonRoundedRegularHighlighted@2x.png */, - 1E5955C415B71C8600A03429 /* IconGradient.png */, - 1E5955C515B71C8600A03429 /* IconGradient@2x.png */, - 1EAF20A4162DC0F600957B1D /* feedbackActivity@2x~ipad.png */, - 1EAF20A5162DC0F600957B1D /* feedbackActivity~ipad.png */, - 1EAF20A6162DC0F600957B1D /* feedbackActiviy.png */, - 1EAF20A7162DC0F600957B1D /* feedbackActiviy@2x.png */, - ); - name = Images; - sourceTree = ""; - }; - 1E5A459616F0DFC200B55C04 /* HockeySDKTests */ = { - isa = PBXGroup; - children = ( - 1EA1170216F53B49001C015C /* Fixtures */, - 1E5A459716F0DFC200B55C04 /* Supporting Files */, - 1E5A459D16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m */, - E48A3DEE17B3EFF100924C3D /* BITAuthenticatorTests.m */, - ); - path = HockeySDKTests; - sourceTree = ""; - }; - 1E5A459716F0DFC200B55C04 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 1E7A45FA16F54FB5005B08F1 /* OCHamcrestIOS.framework */, - 1E7A45FB16F54FB5005B08F1 /* OCMockitoIOS.framework */, - 1E5A459816F0DFC200B55C04 /* HockeySDKTests-Info.plist */, - 1E5A459916F0DFC200B55C04 /* InfoPlist.strings */, - 1E5A459F16F0DFC200B55C04 /* HockeySDKTests-Prefix.pch */, - 1EA1170516F53B91001C015C /* BITTestHelper.h */, - 1EA1170616F53B91001C015C /* BITTestHelper.m */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; - 1E66CA8F15D40FF600F35BED /* Support */ = { - isa = PBXGroup; - children = ( - 1E754DC61621BC170070AB92 /* HockeySDK.xcconfig */, - 1E66CA9115D4100500F35BED /* buildnumber.xcconfig */, - ); - name = Support; - sourceTree = ""; - }; - 1E754E441621F95E0070AB92 /* Helper */ = { - isa = PBXGroup; - children = ( - 1E49A4D4161222D400463151 /* HockeySDKPrivate.h */, - 1E49A4D5161222D400463151 /* HockeySDKPrivate.m */, - 1E49A4A0161222B900463151 /* BITHockeyBaseManager.h */, - 1E49A4A1161222B900463151 /* BITHockeyBaseManager.m */, - 1E49A4A2161222B900463151 /* BITHockeyBaseManagerPrivate.h */, - 1E49A4A3161222B900463151 /* BITHockeyBaseViewController.h */, - 1E49A4A4161222B900463151 /* BITHockeyBaseViewController.m */, - 1E49A4A5161222B900463151 /* BITHockeyHelper.h */, - 1E49A4A6161222B900463151 /* BITHockeyHelper.m */, - 1E0FEE26173BDB260061331F /* BITKeychainUtils.h */, - 1E0FEE27173BDB260061331F /* BITKeychainUtils.m */, - 1EACC979162F041E007578C5 /* BITAttributedLabel.h */, - 1EACC97A162F041E007578C5 /* BITAttributedLabel.m */, - 1E49A4A7161222B900463151 /* BITAppStoreHeader.h */, - 1E49A4A8161222B900463151 /* BITAppStoreHeader.m */, - 1E49A4A9161222B900463151 /* BITStoreButton.h */, - 1E49A4AA161222B900463151 /* BITStoreButton.m */, - 1E49A4AB161222B900463151 /* BITWebTableViewCell.h */, - 1E49A4AC161222B900463151 /* BITWebTableViewCell.m */, - ); - name = Helper; - sourceTree = ""; - }; - 1E754E461621FA9A0070AB92 /* Feedback */ = { - isa = PBXGroup; - children = ( - 1E49A4361612223B00463151 /* BITFeedbackMessage.h */, - 1E49A4371612223B00463151 /* BITFeedbackMessage.m */, - 1E49A42D1612223B00463151 /* BITFeedbackComposeViewController.h */, - 1E49A42E1612223B00463151 /* BITFeedbackComposeViewController.m */, - 1EF95CA9162CB313000AE3AD /* BITFeedbackComposeViewControllerDelegate.h */, - 1E49A4381612223B00463151 /* BITFeedbackUserDataViewController.h */, - 1E49A4391612223B00463151 /* BITFeedbackUserDataViewController.m */, - 1E49A42F1612223B00463151 /* BITFeedbackListViewCell.h */, - 1E49A4301612223B00463151 /* BITFeedbackListViewCell.m */, - 1E49A4311612223B00463151 /* BITFeedbackListViewController.h */, - 1E49A4321612223B00463151 /* BITFeedbackListViewController.m */, - 1EF95CA4162CB036000AE3AD /* BITFeedbackActivity.h */, - 1EF95CA5162CB036000AE3AD /* BITFeedbackActivity.m */, - 1E49A4331612223B00463151 /* BITFeedbackManager.h */, - 1E49A4341612223B00463151 /* BITFeedbackManager.m */, - E405266117A2AD300096359C /* BITFeedbackManagerDelegate.h */, - 1E49A4351612223B00463151 /* BITFeedbackManagerPrivate.h */, - ); - name = Feedback; - sourceTree = ""; - }; - 1E754E471621FAD00070AB92 /* Update */ = { - isa = PBXGroup; - children = ( - 1E49A4621612226D00463151 /* BITAppVersionMetaInfo.h */, - 1E49A4631612226D00463151 /* BITAppVersionMetaInfo.m */, - 1E49A4641612226D00463151 /* BITUpdateManager.h */, - 1E49A4651612226D00463151 /* BITUpdateManager.m */, - 1E49A4661612226D00463151 /* BITUpdateManagerDelegate.h */, - 1E49A4671612226D00463151 /* BITUpdateManagerPrivate.h */, - 1E49A4681612226D00463151 /* BITUpdateViewController.h */, - 1E49A4691612226D00463151 /* BITUpdateViewController.m */, - 1E49A46A1612226D00463151 /* BITUpdateViewControllerPrivate.h */, - ); - name = Update; - sourceTree = ""; - }; - 1E754E551621FBAF0070AB92 /* CrashReports */ = { - isa = PBXGroup; - children = ( - 1E754E561621FBB70070AB92 /* BITCrashManager.h */, - 1E754E571621FBB70070AB92 /* BITCrashManager.m */, - 1E754E581621FBB70070AB92 /* BITCrashManagerDelegate.h */, - 1E754E5A1621FBB70070AB92 /* BITCrashReportTextFormatter.h */, - 1E754E5B1621FBB70070AB92 /* BITCrashReportTextFormatter.m */, - ); - name = CrashReports; - sourceTree = ""; - }; - 1E94F9DE16E912DD006570AD /* StoreUpdate */ = { - isa = PBXGroup; - children = ( - 1E94F9DF16E91330006570AD /* BITStoreUpdateManager.h */, - 1E94F9E016E91330006570AD /* BITStoreUpdateManager.m */, - 1E94F9E316E9136B006570AD /* BITStoreUpdateManagerPrivate.h */, - 1E0828FF1708F69A0073050E /* BITStoreUpdateManagerDelegate.h */, - ); - name = StoreUpdate; - sourceTree = ""; - }; - 1EA1170216F53B49001C015C /* Fixtures */ = { - isa = PBXGroup; - children = ( - 1EA1170316F53B49001C015C /* StoreBundleIdentifierUnknown.json */, - 1EA1170816F53E3A001C015C /* StoreBundleIdentifierKnown.json */, - ); - path = Fixtures; - sourceTree = ""; - }; - E400560F148D79B500EB22B9 = { - isa = PBXGroup; - children = ( - E41EB489148D7BF90015DEDC /* HockeySDK */, - 1E5A459616F0DFC200B55C04 /* HockeySDKTests */, - E400561C148D79B500EB22B9 /* Frameworks */, - E4005648148D7A3000EB22B9 /* Resources */, - 1E66CA8F15D40FF600F35BED /* Support */, - E400561B148D79B500EB22B9 /* Products */, - ); - sourceTree = ""; - }; - E400561B148D79B500EB22B9 /* Products */ = { - isa = PBXGroup; - children = ( - 1E5954F215B6F24A00A03429 /* libHockeySDK.a */, - 1E59550A15B6F45800A03429 /* HockeySDKResources.bundle */, - 1E5A459016F0DFC200B55C04 /* HockeySDKTests.octest */, - ); - name = Products; - sourceTree = ""; - }; - E400561C148D79B500EB22B9 /* Frameworks */ = { - isa = PBXGroup; - children = ( - E41EB48B148D7C4E0015DEDC /* CrashReporter.framework */, - E400561D148D79B500EB22B9 /* Foundation.framework */, - 1E5A459116F0DFC200B55C04 /* SenTestingKit.framework */, - 1E5A459316F0DFC200B55C04 /* UIKit.framework */, - ); - name = Frameworks; - sourceTree = ""; - }; - E4005648148D7A3000EB22B9 /* Resources */ = { - isa = PBXGroup; - children = ( - 1EDA60CF15C2C1450032D10B /* HockeySDK-Info.plist */, - 1E5955A415B71BDC00A03429 /* Images */, - 1E59555F15B6F80E00A03429 /* HockeySDK.strings */, - ); - name = Resources; - path = ../Resources; - sourceTree = ""; - }; - E41EB458148D7BF50015DEDC /* Classes */ = { - isa = PBXGroup; - children = ( - E48A3DE917B3ECF900924C3D /* Network */, - 1E754E441621F95E0070AB92 /* Helper */, - 1E754E551621FBAF0070AB92 /* CrashReports */, - 1E754E461621FA9A0070AB92 /* Feedback */, - 1E754E471621FAD00070AB92 /* Update */, - 1E94F9DE16E912DD006570AD /* StoreUpdate */, - E41EB465148D7BF50015DEDC /* BITHockeyManager.h */, - E41EB466148D7BF50015DEDC /* BITHockeyManager.m */, - 1EC69F5D1615001500808FD9 /* BITHockeyManagerPrivate.h */, - 1E5955FA15B7877A00A03429 /* BITHockeyManagerDelegate.h */, - 1E71509A15B5C76F004E88FF /* HockeySDK.h */, - ); - name = Classes; - path = ../Classes; - sourceTree = ""; - }; - E41EB489148D7BF90015DEDC /* HockeySDK */ = { - isa = PBXGroup; - children = ( - E41EB458148D7BF50015DEDC /* Classes */, - ); - name = HockeySDK; - sourceTree = ""; - }; - E48A3DE917B3ECF900924C3D /* Network */ = { - isa = PBXGroup; - children = ( - E48A3DF017B408D800924C3D /* private */, - E48A3DEA17B3ED1C00924C3D /* BITAuthenticator.h */, - E48A3DEB17B3ED1C00924C3D /* BITAuthenticator.m */, - ); - name = Network; - sourceTree = ""; - }; - E48A3DF017B408D800924C3D /* private */ = { - isa = PBXGroup; - children = ( - E48A3DF117B408F400924C3D /* BITAuthenticator_Private.h */, - E4B4DB7B17B435550099C67F /* BITAuthenticationViewController.h */, - E4B4DB7C17B435550099C67F /* BITAuthenticationViewController.m */, - E4933E7E17B66CDA00B11ACC /* BITHTTPOperation.h */, - E4933E7F17B66CDA00B11ACC /* BITHTTPOperation.m */, - ); - name = private; - sourceTree = ""; - }; -/* End PBXGroup section */ - -/* Begin PBXHeadersBuildPhase section */ - 1E59558B15B6FD8800A03429 /* Headers */ = { - isa = PBXHeadersBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E59559B15B6FDA500A03429 /* HockeySDK.h in Headers */, - 1E59559A15B6FDA500A03429 /* BITHockeyManager.h in Headers */, - 1E5955FD15B7877B00A03429 /* BITHockeyManagerDelegate.h in Headers */, - 1E754E5C1621FBB70070AB92 /* BITCrashManager.h in Headers */, - 1E754E5E1621FBB70070AB92 /* BITCrashManagerDelegate.h in Headers */, - 1E49A4731612226D00463151 /* BITUpdateManager.h in Headers */, - 1E49A4791612226D00463151 /* BITUpdateManagerDelegate.h in Headers */, - 1E49A44E1612223B00463151 /* BITFeedbackManager.h in Headers */, - E4B4DB7D17B435550099C67F /* BITAuthenticationViewController.h in Headers */, - 1E49A4481612223B00463151 /* BITFeedbackListViewController.h in Headers */, - 1E49A47F1612226D00463151 /* BITUpdateViewController.h in Headers */, - 1E49A43C1612223B00463151 /* BITFeedbackComposeViewController.h in Headers */, - 1EF95CAA162CB314000AE3AD /* BITFeedbackComposeViewControllerDelegate.h in Headers */, - 1EF95CA6162CB037000AE3AD /* BITFeedbackActivity.h in Headers */, - 1E49A4AF161222B900463151 /* BITHockeyBaseManager.h in Headers */, - 1E49A4B8161222B900463151 /* BITHockeyBaseViewController.h in Headers */, - 1E49A4421612223B00463151 /* BITFeedbackListViewCell.h in Headers */, - 1E49A4541612223B00463151 /* BITFeedbackManagerPrivate.h in Headers */, - 1E49A4571612223B00463151 /* BITFeedbackMessage.h in Headers */, - 1E49A45D1612223B00463151 /* BITFeedbackUserDataViewController.h in Headers */, - 1E49A46D1612226D00463151 /* BITAppVersionMetaInfo.h in Headers */, - 1E49A47C1612226D00463151 /* BITUpdateManagerPrivate.h in Headers */, - 1E49A4851612226D00463151 /* BITUpdateViewControllerPrivate.h in Headers */, - 1E49A4B5161222B900463151 /* BITHockeyBaseManagerPrivate.h in Headers */, - E4933E8017B66CDA00B11ACC /* BITHTTPOperation.h in Headers */, - 1E49A4BE161222B900463151 /* BITHockeyHelper.h in Headers */, - 1E49A4C4161222B900463151 /* BITAppStoreHeader.h in Headers */, - 1E49A4CA161222B900463151 /* BITStoreButton.h in Headers */, - E405266217A2AD300096359C /* BITFeedbackManagerDelegate.h in Headers */, - 1E49A4D0161222B900463151 /* BITWebTableViewCell.h in Headers */, - 1E49A4D8161222D400463151 /* HockeySDKPrivate.h in Headers */, - 1EC69F601615001500808FD9 /* BITHockeyManagerPrivate.h in Headers */, -<<<<<<< HEAD - 1E754E5F1621FBB70070AB92 /* BITCrashManagerPrivate.h in Headers */, - E48A3DEC17B3ED1C00924C3D /* BITAuthenticator.h in Headers */, -======= ->>>>>>> develop - 1E754E601621FBB70070AB92 /* BITCrashReportTextFormatter.h in Headers */, - 1EACC97B162F041E007578C5 /* BITAttributedLabel.h in Headers */, - 1E0FEE28173BDB260061331F /* BITKeychainUtils.h in Headers */, - 1E94F9E116E91330006570AD /* BITStoreUpdateManager.h in Headers */, - 1E94F9E416E9136B006570AD /* BITStoreUpdateManagerPrivate.h in Headers */, - 1E0829001708F69A0073050E /* BITStoreUpdateManagerDelegate.h in Headers */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXHeadersBuildPhase section */ - -/* Begin PBXNativeTarget section */ - 1E5954CB15B6F24A00A03429 /* HockeySDK */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E5954EF15B6F24A00A03429 /* Build configuration list for PBXNativeTarget "HockeySDK" */; - buildPhases = ( - 1E5954CC15B6F24A00A03429 /* Sources */, - 1E5954DB15B6F24A00A03429 /* Frameworks */, - 1E59558B15B6FD8800A03429 /* Headers */, - 1EE9071A16F6871F003DDE1D /* ShellScript */, - ); - buildRules = ( - ); - dependencies = ( - 1E59557E15B6F97100A03429 /* PBXTargetDependency */, - ); - name = HockeySDK; - productName = HockeySDK; - productReference = 1E5954F215B6F24A00A03429 /* libHockeySDK.a */; - productType = "com.apple.product-type.library.static"; - }; - 1E59550915B6F45800A03429 /* HockeySDKResources */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E59551415B6F45800A03429 /* Build configuration list for PBXNativeTarget "HockeySDKResources" */; - buildPhases = ( - 1E59550615B6F45800A03429 /* Sources */, - 1E59550715B6F45800A03429 /* Frameworks */, - 1E59550815B6F45800A03429 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - ); - name = HockeySDKResources; - productName = HockeySDKBundle; - productReference = 1E59550A15B6F45800A03429 /* HockeySDKResources.bundle */; - productType = "com.apple.product-type.bundle"; - }; - 1E5A458F16F0DFC200B55C04 /* HockeySDKTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1E5A45A216F0DFC200B55C04 /* Build configuration list for PBXNativeTarget "HockeySDKTests" */; - buildPhases = ( - 1E5A458B16F0DFC200B55C04 /* Sources */, - 1E5A458C16F0DFC200B55C04 /* Frameworks */, - 1E5A458D16F0DFC200B55C04 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 1EA1170B16F54A5C001C015C /* PBXTargetDependency */, - 1EA116FF16F4D302001C015C /* PBXTargetDependency */, - ); - name = HockeySDKTests; - productName = HockeySDKTests; - productReference = 1E5A459016F0DFC200B55C04 /* HockeySDKTests.octest */; - productType = "com.apple.product-type.bundle"; - }; -/* End PBXNativeTarget section */ - -/* Begin PBXProject section */ - E4005611148D79B500EB22B9 /* Project object */ = { - isa = PBXProject; - attributes = { - LastUpgradeCheck = 0440; - }; - buildConfigurationList = E4005614148D79B500EB22B9 /* Build configuration list for PBXProject "HockeySDK" */; - compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; - hasScannedForEncodings = 0; - knownRegions = ( - en, - de, - es, - fr, - it, - ja, - nl, - "pt-PT", - pt, - ru, - sv, - tr, - hr, - zh, - "zh-Hans", - ro, - hu, - ); - mainGroup = E400560F148D79B500EB22B9; - productRefGroup = E400561B148D79B500EB22B9 /* Products */; - projectDirPath = ""; - projectRoot = ""; - targets = ( - 1E5954CB15B6F24A00A03429 /* HockeySDK */, - 1E59550915B6F45800A03429 /* HockeySDKResources */, - 1E8E66AD15BC3D7700632A2E /* HockeySDK Documentation */, - 1E4F61E91621AD970033EFC5 /* HockeySDK Framework */, - 1E5A458F16F0DFC200B55C04 /* HockeySDKTests */, - ); - }; -/* End PBXProject section */ - -/* Begin PBXResourcesBuildPhase section */ - 1E59550815B6F45800A03429 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E5955C615B71C8600A03429 /* authorize_denied.png in Resources */, - 1E5955C715B71C8600A03429 /* authorize_denied@2x.png in Resources */, - 1E5955CA15B71C8600A03429 /* bg.png in Resources */, - 1E5955CB15B71C8600A03429 /* buttonHighlight.png in Resources */, - 1E5955CC15B71C8600A03429 /* buttonHighlight@2x.png in Resources */, - 1E5955CF15B71C8600A03429 /* IconGradient.png in Resources */, - 1E5955D015B71C8600A03429 /* IconGradient@2x.png in Resources */, - 1EAF20A8162DC0F600957B1D /* feedbackActivity@2x~ipad.png in Resources */, - 1EAF20A9162DC0F600957B1D /* feedbackActivity~ipad.png in Resources */, - 1EAF20AA162DC0F600957B1D /* feedbackActiviy.png in Resources */, - 1EAF20AB162DC0F600957B1D /* feedbackActiviy@2x.png in Resources */, - 1E1127C416580C87007067A2 /* buttonRoundedDelete.png in Resources */, - 1E1127C516580C87007067A2 /* buttonRoundedDelete@2x.png in Resources */, - 1E1127C616580C87007067A2 /* buttonRoundedDeleteHighlighted.png in Resources */, - 1E1127C716580C87007067A2 /* buttonRoundedDeleteHighlighted@2x.png in Resources */, - 1E1127C816580C87007067A2 /* buttonRoundedRegular.png in Resources */, - 1E1127C916580C87007067A2 /* buttonRoundedRegular@2x.png in Resources */, - 1E1127CA16580C87007067A2 /* buttonRoundedRegularHighlighted.png in Resources */, - 1E1127CB16580C87007067A2 /* buttonRoundedRegularHighlighted@2x.png in Resources */, - 1EB52FD5167B766100C801D5 /* HockeySDK.strings in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E5A458D16F0DFC200B55C04 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1EA1170C16F54A64001C015C /* HockeySDKResources.bundle in Resources */, - 1E5A459B16F0DFC200B55C04 /* InfoPlist.strings in Resources */, - 1EA1170416F53B49001C015C /* StoreBundleIdentifierUnknown.json in Resources */, - 1EA1170916F53E3A001C015C /* StoreBundleIdentifierKnown.json in Resources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXResourcesBuildPhase section */ - -/* Begin PBXShellScriptBuildPhase section */ - 1E4F61ED1621ADE70033EFC5 /* Build universal embedded framework */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - name = "Build universal embedded framework"; - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "# Sets the target folders and the final framework product.\nFMK_NAME=HockeySDK\nFMK_VERSION=A\nFMK_RESOURCE_BUNDLE=HockeySDKResources\n\n# Documentation\nHOCKEYSDK_DOCSET_VERSION_NAME=\"de.bitstadium.${HOCKEYSDK_DOCSET_NAME}-${VERSION_STRING}\"\n\n# Install dir will be the final output to the framework.\n# The following line create it in the root folder of the current project.\nPRODUCTS_DIR=${SRCROOT}/../Products\nTEMP_DIR=${PRODUCTS_DIR}/Temp\nINSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.framework\n\n# Working dir will be deleted after the framework creation.\nWRK_DIR=build\nDEVICE_DIR=${WRK_DIR}/Release-iphoneos\nSIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator\nHEADERS_DIR=${WRK_DIR}/Release-iphoneos/usr/local/include\n\n# Building both architectures.\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphoneos\nxcodebuild -project \"HockeySDK.xcodeproj\" -configuration \"Release\" -target \"${FMK_NAME}\" -sdk iphonesimulator\n\n# Cleaning the oldest.\nif [ -d \"${TEMP_DIR}\" ]\nthen\nrm -rf \"${TEMP_DIR}\"\nfi\n\n# Creates and renews the final product folder.\nmkdir -p \"${INSTALL_DIR}\"\nmkdir -p \"${INSTALL_DIR}/Versions\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources\"\nmkdir -p \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers\"\n\n# Creates the internal links.\n# It MUST uses relative path, otherwise will not work when the folder is copied/moved.\nln -s \"${FMK_VERSION}\" \"${INSTALL_DIR}/Versions/Current\"\nln -s \"Versions/Current/Headers\" \"${INSTALL_DIR}/Headers\"\nln -s \"Versions/Current/Resources\" \"${INSTALL_DIR}/Resources\"\nln -s \"Versions/Current/${FMK_NAME}\" \"${INSTALL_DIR}/${FMK_NAME}\"\n\n# Copies the headers and resources files to the final product folder.\ncp -R \"${SRCROOT}/build/Release-iphoneos/include/HockeySDK/\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Headers/\"\ncp -R \"${DEVICE_DIR}/${FMK_RESOURCE_BUNDLE}.bundle\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\ncp -f \"${SRCROOT}/${FMK_NAME}.xcconfig\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/Resources/\"\n\n# Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.\nlipo -create \"${DEVICE_DIR}/lib${FMK_NAME}.a\" \"${SIMULATOR_DIR}/lib${FMK_NAME}.a\" -output \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\"\n\n# Combine the CrashReporter static library into a new Hockey static library file if they are not already present and copy the public headers too\nif [ -z $(otool -L \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" | grep 'libCrashReporter') ]\nthen\nlibtool -static -o \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${INSTALL_DIR}/Versions/${FMK_VERSION}/${FMK_NAME}\" \"${SRCROOT}/../Vendor/CrashReporter.framework/Versions/A/CrashReporter\"\nfi\n\nrm -r \"${WRK_DIR}\"\n\n# build embeddedframework folder and move framework into it\nmkdir \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework\"\nmv \"${INSTALL_DIR}\" \"${INSTALL_DIR}/../${FMK_NAME}.embeddedframework/${FMK_NAME}.framework\"\n\n# link Resources\nNEW_INSTALL_DIR=${TEMP_DIR}/${FMK_NAME}.embeddedframework\nmkdir \"${NEW_INSTALL_DIR}/Resources\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_RESOURCE_BUNDLE}.bundle\" \"${NEW_INSTALL_DIR}/Resources/${FMK_RESOURCE_BUNDLE}.bundle\"\nln -s \"../${FMK_NAME}.framework/Resources/${FMK_NAME}.xcconfig\" \"${NEW_INSTALL_DIR}/Resources/${FMK_NAME}.xcconfig\"\n\n# copy license, changelog, documentation\ncp -f \"${SRCROOT}/../Docs/Changelog-template.md\" \"${TEMP_DIR}/CHANGELOG\"\ncp -f \"${SRCROOT}/../Docs/Guide-Installation-Setup-template.md\" \"${TEMP_DIR}/README.md\"\ncp -f \"${SRCROOT}/../LICENSE\" \"${TEMP_DIR}\"\nmkdir \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\ncp -R \"${SRCROOT}/../documentation/docset/Contents\" \"${TEMP_DIR}/${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\"\n\n# build zip\ncd \"${PRODUCTS_DIR}\"\nrm -f \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\ncd \"${TEMP_DIR}\"\nzip -yr \"../${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"./${FMK_NAME}.embeddedframework\" \"./CHANGELOG\" \"./README.md\" \"./LICENSE\" \"./${HOCKEYSDK_DOCSET_VERSION_NAME}.docset\" -x \\*/.*\n\n#copy to output dir on cisimple\nif [ $CISIMPLE ]; then\n if [ ! -d \"${CONFIGURATION_BUILD_DIR}\" ]; then\n mkdir \"${CONFIGURATION_BUILD_DIR}\"\n fi\n cd \"${PRODUCTS_DIR}\"\n cp \"${FMK_NAME}-iOS-${VERSION_STRING}.zip\" \"${CONFIGURATION_BUILD_DIR}/${FMK_NAME}-iOS-${VERSION_STRING}.zip\"\nfi"; - }; - 1E8E66B215BC3D8200632A2E /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "/usr/local/bin/appledoc \\\n --output \"${SOURCE_ROOT}/../documentation\" \\\n --ignore Vendor \\\n --ignore Products \\\n --ignore .m \\\n --create-html \\\n --create-docset \\\n --install-docset \\\n --keep-intermediate-files \\\n --project-name \"${HOCKEYSDK_DOCSET_NAME} ${VERSION_STRING}\" \\\n --project-version \"${VERSION_STRING}\" \\\n --project-company \"BitStadium GmbH\" \\\n --company-id \"de.bitstadium\" \\\n --docset-bundle-name \"${HOCKEYSDK_DOCSET_NAME} ${VERSION_STRING}\" \\\n --docset-feed-name \"${HOCKEYSDK_DOCSET_NAME}\" \\\n --docset-desc \"\" \\\n --docset-platform-family \"iphoneos\" \\\n --index-desc \"${SOURCE_ROOT}/../docs/index.md\" \\\n --include \"${SOURCE_ROOT}/../docs/index.html\" \\\n --include \"${SOURCE_ROOT}/../docs/\" \\\n --merge-categories \\\n --no-repeat-first-par \\\n --warn-undocumented-object \\\n --warn-undocumented-member \\\n --warn-empty-description \\\n --warn-unknown-directive \\\n --warn-invalid-crossref \\\n --warn-missing-arg \\\n --logformat xcode \\\n --exit-threshold 2 \\\n \"${SOURCE_ROOT}/../\"\n"; - }; - 1EE9071A16F6871F003DDE1D /* ShellScript */ = { - isa = PBXShellScriptBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - inputPaths = ( - ); - outputPaths = ( - ); - runOnlyForDeploymentPostprocessing = 0; - shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/../Vendor/XcodeCoverage/exportenv.sh\""; - }; -/* End PBXShellScriptBuildPhase section */ - -/* Begin PBXSourcesBuildPhase section */ - 1E5954CC15B6F24A00A03429 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E5954D315B6F24A00A03429 /* BITHockeyManager.m in Sources */, - 1E49A43F1612223B00463151 /* BITFeedbackComposeViewController.m in Sources */, - 1E49A4451612223B00463151 /* BITFeedbackListViewCell.m in Sources */, - 1E49A44B1612223B00463151 /* BITFeedbackListViewController.m in Sources */, - 1E49A4511612223B00463151 /* BITFeedbackManager.m in Sources */, - E4933E8117B66CDA00B11ACC /* BITHTTPOperation.m in Sources */, - 1E49A45A1612223B00463151 /* BITFeedbackMessage.m in Sources */, - 1E49A4601612223B00463151 /* BITFeedbackUserDataViewController.m in Sources */, - 1E49A4701612226D00463151 /* BITAppVersionMetaInfo.m in Sources */, - 1E49A4761612226D00463151 /* BITUpdateManager.m in Sources */, - 1E49A4821612226D00463151 /* BITUpdateViewController.m in Sources */, - E4B4DB7E17B435550099C67F /* BITAuthenticationViewController.m in Sources */, - 1E49A4B2161222B900463151 /* BITHockeyBaseManager.m in Sources */, - 1E49A4BB161222B900463151 /* BITHockeyBaseViewController.m in Sources */, - 1E49A4C1161222B900463151 /* BITHockeyHelper.m in Sources */, - 1E49A4C7161222B900463151 /* BITAppStoreHeader.m in Sources */, - 1E49A4CD161222B900463151 /* BITStoreButton.m in Sources */, - 1E49A4D3161222B900463151 /* BITWebTableViewCell.m in Sources */, - E48A3DED17B3ED1C00924C3D /* BITAuthenticator.m in Sources */, - 1E49A4DB161222D400463151 /* HockeySDKPrivate.m in Sources */, - 1E754E5D1621FBB70070AB92 /* BITCrashManager.m in Sources */, - 1E754E611621FBB70070AB92 /* BITCrashReportTextFormatter.m in Sources */, - 1EF95CA7162CB037000AE3AD /* BITFeedbackActivity.m in Sources */, - 1EACC97C162F041E007578C5 /* BITAttributedLabel.m in Sources */, - 1E0FEE29173BDB260061331F /* BITKeychainUtils.m in Sources */, - 1E94F9E216E91330006570AD /* BITStoreUpdateManager.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E59550615B6F45800A03429 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; - 1E5A458B16F0DFC200B55C04 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1E5A459E16F0DFC200B55C04 /* BITStoreUpdateManagerTests.m in Sources */, - E48A3DEF17B3EFF100924C3D /* BITAuthenticatorTests.m in Sources */, - 1EA1170716F53B91001C015C /* BITTestHelper.m in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; -/* End PBXSourcesBuildPhase section */ - -/* Begin PBXTargetDependency section */ - 1E59557E15B6F97100A03429 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1E59550915B6F45800A03429 /* HockeySDKResources */; - targetProxy = 1E59557D15B6F97100A03429 /* PBXContainerItemProxy */; - }; - 1E754E431621F6290070AB92 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1E8E66AD15BC3D7700632A2E /* HockeySDK Documentation */; - targetProxy = 1E754E421621F6290070AB92 /* PBXContainerItemProxy */; - }; - 1EA116FF16F4D302001C015C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1E5954CB15B6F24A00A03429 /* HockeySDK */; - targetProxy = 1EA116FE16F4D302001C015C /* PBXContainerItemProxy */; - }; - 1EA1170B16F54A5C001C015C /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1E59550915B6F45800A03429 /* HockeySDKResources */; - targetProxy = 1EA1170A16F54A5C001C015C /* PBXContainerItemProxy */; - }; -/* End PBXTargetDependency section */ - -/* Begin PBXVariantGroup section */ - 1E59555F15B6F80E00A03429 /* HockeySDK.strings */ = { - isa = PBXVariantGroup; - children = ( - 1E59556015B6F80E00A03429 /* de */, - 1E59556415B6F81C00A03429 /* es */, - 1E59556615B6F82300A03429 /* fr */, - 1E59556815B6F82A00A03429 /* it */, - 1E59556A15B6F83100A03429 /* ja */, - 1E59557015B6F84700A03429 /* pt */, - 1E59557215B6F84D00A03429 /* ru */, - 1E36D8B816667611000B134C /* hr */, - 1E6F0450167B5E5600ED1C86 /* pt-PT */, - 1EB52FC3167B73D400C801D5 /* en */, - 1EA512DF167F7EF000FC9FBA /* zh-Hans */, - 1E6DDCEE169E290C0076C65D /* ro */, - BEE0207C16C5107E004426EA /* hu */, - ); - name = HockeySDK.strings; - sourceTree = ""; - }; - 1E5A459916F0DFC200B55C04 /* InfoPlist.strings */ = { - isa = PBXVariantGroup; - children = ( - 1E5A459A16F0DFC200B55C04 /* en */, - ); - name = InfoPlist.strings; - sourceTree = ""; - }; -/* End PBXVariantGroup section */ - -/* Begin XCBuildConfiguration section */ - 1E4F61EB1621AD970033EFC5 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = HockeySDK.framework; - }; - name = Debug; - }; - 1E4F61EC1621AD970033EFC5 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = HockeySDK.framework; - }; - name = Release; - }; - 1E5954F015B6F24A00A03429 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - DSTROOT = /tmp/HockeySDK.dst; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../Vendor\"", - ); - GCC_THUMB_SUPPORT = NO; - PRODUCT_NAME = HockeySDK; - PUBLIC_HEADERS_FOLDER_PATH = "include/$(PRODUCT_NAME)"; - SKIP_INSTALL = YES; - }; - name = Debug; - }; - 1E5954F115B6F24A00A03429 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - DSTROOT = /tmp/HockeySDK.dst; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../Vendor\"", - ); - GCC_THUMB_SUPPORT = NO; - PRODUCT_NAME = HockeySDK; - PUBLIC_HEADERS_FOLDER_PATH = "include/$(PRODUCT_NAME)"; - SKIP_INSTALL = YES; - }; - name = Release; - }; - 1E59551515B6F45800A03429 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_THUMB_SUPPORT = NO; - INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - WRAPPER_EXTENSION = bundle; - }; - name = Debug; - }; - 1E59551615B6F45800A03429 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; - GCC_THUMB_SUPPORT = NO; - INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - WRAPPER_EXTENSION = bundle; - }; - name = Release; - }; - 1E5A45A016F0DFC200B55C04 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - FRAMEWORK_SEARCH_PATHS = ( - "\"$(SDKROOT)/Developer/Library/Frameworks\"", - "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", - "\"$(SRCROOT)/../Vendor\"", - "\"$(SRCROOT)/HockeySDKTests\"", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "HockeySDKTests/HockeySDKTests-Prefix.pch"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_UNINITIALIZED_AUTOS = YES; - INFOPLIST_FILE = "HockeySDKTests/HockeySDKTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 6.1; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/HockeySDKTests\"", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = octest; - }; - name = Debug; - }; - 1E5A45A116F0DFC200B55C04 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - COPY_PHASE_STRIP = YES; - FRAMEWORK_SEARCH_PATHS = ( - "\"$(SDKROOT)/Developer/Library/Frameworks\"", - "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", - "\"$(SRCROOT)/../Vendor\"", - "\"$(SRCROOT)/HockeySDKTests\"", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "HockeySDKTests/HockeySDKTests-Prefix.pch"; - GCC_WARN_UNINITIALIZED_AUTOS = YES; - INFOPLIST_FILE = "HockeySDKTests/HockeySDKTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 6.1; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/HockeySDKTests\"", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - VALIDATE_PRODUCT = YES; - WRAPPER_EXTENSION = octest; - }; - name = Release; - }; - 1E68F4A716F7843F00053706 /* CodeCoverage */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1E66CA9115D4100500F35BED /* buildnumber.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_GENERATE_TEST_COVERAGE_FILES = YES; - GCC_INSTRUMENT_PROGRAM_FLOW_ARCS = YES; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "BITHOCKEY_STATIC_LIBRARY=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_THUMB_SUPPORT = NO; - GCC_VERSION = ""; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_STRICT_SELECTOR_MATCH = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - MACOSX_DEPLOYMENT_TARGET = 10.5; - RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = iphoneos; - }; - name = CodeCoverage; - }; - 1E68F4A816F7843F00053706 /* CodeCoverage */ = { - isa = XCBuildConfiguration; - buildSettings = { - DSTROOT = /tmp/HockeySDK.dst; - FRAMEWORK_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/../Vendor\"", - ); - GCC_THUMB_SUPPORT = NO; - PRODUCT_NAME = HockeySDK; - PUBLIC_HEADERS_FOLDER_PATH = "include/$(PRODUCT_NAME)"; - SKIP_INSTALL = YES; - }; - name = CodeCoverage; - }; - 1E68F4A916F7843F00053706 /* CodeCoverage */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_THUMB_SUPPORT = NO; - INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Bundles"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SKIP_INSTALL = YES; - WRAPPER_EXTENSION = bundle; - }; - name = CodeCoverage; - }; - 1E68F4AA16F7843F00053706 /* CodeCoverage */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_THUMB_SUPPORT = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = CodeCoverage; - }; - 1E68F4AB16F7843F00053706 /* CodeCoverage */ = { - isa = XCBuildConfiguration; - buildSettings = { - PRODUCT_NAME = HockeySDK.framework; - }; - name = CodeCoverage; - }; - 1E68F4AC16F7843F00053706 /* CodeCoverage */ = { - isa = XCBuildConfiguration; - buildSettings = { - CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; - CLANG_CXX_LIBRARY = "libc++"; - CLANG_WARN_CONSTANT_CONVERSION = YES; - CLANG_WARN_EMPTY_BODY = YES; - CLANG_WARN_ENUM_CONVERSION = YES; - CLANG_WARN_INT_CONVERSION = YES; - CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; - FRAMEWORK_SEARCH_PATHS = ( - "\"$(SDKROOT)/Developer/Library/Frameworks\"", - "\"$(DEVELOPER_LIBRARY_DIR)/Frameworks\"", - "\"$(SRCROOT)/../Vendor\"", - "\"$(SRCROOT)/HockeySDKTests\"", - ); - GCC_PRECOMPILE_PREFIX_HEADER = YES; - GCC_PREFIX_HEADER = "HockeySDKTests/HockeySDKTests-Prefix.pch"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - GCC_WARN_UNINITIALIZED_AUTOS = YES; - INFOPLIST_FILE = "HockeySDKTests/HockeySDKTests-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 6.1; - LIBRARY_SEARCH_PATHS = ( - "$(inherited)", - "\"$(SRCROOT)/HockeySDKTests\"", - ); - PRODUCT_NAME = "$(TARGET_NAME)"; - WRAPPER_EXTENSION = octest; - }; - name = CodeCoverage; - }; - 1E8E66AE15BC3D7700632A2E /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_THUMB_SUPPORT = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Debug; - }; - 1E8E66AF15BC3D7700632A2E /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_THUMB_SUPPORT = NO; - PRODUCT_NAME = "$(TARGET_NAME)"; - }; - name = Release; - }; - E400563C148D79B500EB22B9 /* Debug */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1E66CA9115D4100500F35BED /* buildnumber.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_DYNAMIC_NO_PIC = NO; - GCC_OPTIMIZATION_LEVEL = 0; - GCC_PREPROCESSOR_DEFINITIONS = ( - "BITHOCKEY_STATIC_LIBRARY=1", - "DEBUG=1", - "$(inherited)", - ); - GCC_SYMBOLS_PRIVATE_EXTERN = NO; - GCC_THUMB_SUPPORT = NO; - GCC_VERSION = ""; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_STRICT_SELECTOR_MATCH = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - MACOSX_DEPLOYMENT_TARGET = 10.5; - RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = iphoneos; - }; - name = Debug; - }; - E400563D148D79B500EB22B9 /* Release */ = { - isa = XCBuildConfiguration; - baseConfigurationReference = 1E66CA9115D4100500F35BED /* buildnumber.xcconfig */; - buildSettings = { - ALWAYS_SEARCH_USER_PATHS = NO; - ARCHS = "$(ARCHS_STANDARD_32_BIT)"; - CLANG_ENABLE_OBJC_ARC = YES; - COPY_PHASE_STRIP = NO; - DEAD_CODE_STRIPPING = NO; - GCC_C_LANGUAGE_STANDARD = gnu99; - GCC_PREPROCESSOR_DEFINITIONS = ( - "BITHOCKEY_STATIC_LIBRARY=1", - "$(inherited)", - ); - GCC_THUMB_SUPPORT = NO; - GCC_VERSION = ""; - GCC_WARN_ABOUT_MISSING_NEWLINE = YES; - GCC_WARN_ABOUT_MISSING_PROTOTYPES = YES; - GCC_WARN_ABOUT_RETURN_TYPE = YES; - GCC_WARN_STRICT_SELECTOR_MATCH = YES; - GCC_WARN_UNDECLARED_SELECTOR = YES; - GCC_WARN_UNUSED_VARIABLE = YES; - INFOPLIST_FILE = "../Resources/HockeySDK-Info.plist"; - IPHONEOS_DEPLOYMENT_TARGET = 5.0; - MACOSX_DEPLOYMENT_TARGET = 10.5; - RUN_CLANG_STATIC_ANALYZER = YES; - SDKROOT = iphoneos; - VALIDATE_PRODUCT = NO; - }; - name = Release; - }; -/* End XCBuildConfiguration section */ - -/* Begin XCConfigurationList section */ - 1E4F61EA1621AD970033EFC5 /* Build configuration list for PBXAggregateTarget "HockeySDK Framework" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E4F61EB1621AD970033EFC5 /* Debug */, - 1E68F4AB16F7843F00053706 /* CodeCoverage */, - 1E4F61EC1621AD970033EFC5 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E5954EF15B6F24A00A03429 /* Build configuration list for PBXNativeTarget "HockeySDK" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E5954F015B6F24A00A03429 /* Debug */, - 1E68F4A816F7843F00053706 /* CodeCoverage */, - 1E5954F115B6F24A00A03429 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E59551415B6F45800A03429 /* Build configuration list for PBXNativeTarget "HockeySDKResources" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E59551515B6F45800A03429 /* Debug */, - 1E68F4A916F7843F00053706 /* CodeCoverage */, - 1E59551615B6F45800A03429 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E5A45A216F0DFC200B55C04 /* Build configuration list for PBXNativeTarget "HockeySDKTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E5A45A016F0DFC200B55C04 /* Debug */, - 1E68F4AC16F7843F00053706 /* CodeCoverage */, - 1E5A45A116F0DFC200B55C04 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - 1E8E66B015BC3D7700632A2E /* Build configuration list for PBXAggregateTarget "HockeySDK Documentation" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1E8E66AE15BC3D7700632A2E /* Debug */, - 1E68F4AA16F7843F00053706 /* CodeCoverage */, - 1E8E66AF15BC3D7700632A2E /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; - E4005614148D79B500EB22B9 /* Build configuration list for PBXProject "HockeySDK" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - E400563C148D79B500EB22B9 /* Debug */, - 1E68F4A716F7843F00053706 /* CodeCoverage */, - E400563D148D79B500EB22B9 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; -/* End XCConfigurationList section */ - }; - rootObject = E4005611148D79B500EB22B9 /* Project object */; -} diff --git a/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents.orig b/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents.orig deleted file mode 100644 index 1ceb0b656cf5..000000000000 --- a/WordPress/Classes/WordPress.xcdatamodeld/WordPress 13.xcdatamodel/contents.orig +++ /dev/null @@ -1,353 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -<<<<<<< HEAD -======= - - - ->>>>>>> refs/heads/develop - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file From b8d97fc2ab202c7d2315b516f9e3fa966b770dff Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 27 Nov 2013 11:28:46 -0800 Subject: [PATCH 36/64] Adjusted header heights in the blog list --- WordPress/Classes/BlogListViewController.m | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index e73962e53eb1..a52d2340dd81 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -233,14 +233,14 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { // No top margin on iPhone - if (section == [self sectionForAddSite]) { + if ([self hasDotComAndSelfHosted]) { + return 40.0; + } else { return 20.0; } - if (IS_IPHONE && section == 0) { - return 36.0; - } - - return 40.0; +} +- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { + return 1.0; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { From adb141e1d346de03b100b7653ed55b43ea5cfc96 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 27 Nov 2013 11:40:50 -0800 Subject: [PATCH 37/64] Changed modal transition style when showing login form from blogs list --- WordPress/Classes/BlogListViewController.m | 19 +----- .../Classes/FakePushTransitionAnimator.h | 13 ---- .../Classes/FakePushTransitionAnimator.m | 60 ------------------- WordPress/Classes/LoginViewController.m | 4 +- WordPress/WordPress.xcodeproj/project.pbxproj | 7 --- 5 files changed, 4 insertions(+), 99 deletions(-) delete mode 100644 WordPress/Classes/FakePushTransitionAnimator.h delete mode 100644 WordPress/Classes/FakePushTransitionAnimator.m diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index a52d2340dd81..357c0cd43b91 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -17,12 +17,11 @@ #import "ContextManager.h" #import "Blog.h" #import "WPAccount.h" -#import "FakePushTransitionAnimator.h" #import "ManageBlogsViewController.h" CGFloat const blavatarImageSize = 50.f; -@interface BlogListViewController () +@interface BlogListViewController () @property (nonatomic, strong) NSFetchedResultsController *resultsController; @property (nonatomic, strong) UIBarButtonItem *settingsButton; @@ -259,14 +258,13 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath LoginViewController *loginViewController = [[LoginViewController alloc] init]; if (![WPAccount defaultWordPressComAccount]) { + loginViewController.prefersSelfHosted = YES; } loginViewController.dismissBlock = ^{ [self dismissViewControllerAnimated:YES completion:nil]; }; UINavigationController *loginNavigationController = [[UINavigationController alloc] initWithRootViewController:loginViewController]; - loginNavigationController.transitioningDelegate = self; - loginNavigationController.modalTransitionStyle = UIModalPresentationCustom; [self presentViewController:loginNavigationController animated:YES completion:nil]; } } @@ -383,17 +381,4 @@ - (NSString *)controller:(NSFetchedResultsController *)controller sectionIndexTi return NSLocalizedString(@"Self Hosted", @"Section header for self hosted blogs"); } -#pragma mark - UIViewControllerTransitioningDelegate - -- (id )animationControllerForPresentedController:(UIViewController *)presented presentingController:(UIViewController *)presenting sourceController:(UIViewController *)source { - FakePushTransitionAnimator *animator = [FakePushTransitionAnimator new]; - animator.presenting = YES; - return animator; -} - -- (id )animationControllerForDismissedController:(UIViewController *)dismissed { - FakePushTransitionAnimator *animator = [FakePushTransitionAnimator new]; - return animator; -} - @end diff --git a/WordPress/Classes/FakePushTransitionAnimator.h b/WordPress/Classes/FakePushTransitionAnimator.h deleted file mode 100644 index 7db11813ac16..000000000000 --- a/WordPress/Classes/FakePushTransitionAnimator.h +++ /dev/null @@ -1,13 +0,0 @@ -// -// FakePushTransitionAnimator.h -// WordPress -// -// Created by Jorge Bernal on 21/11/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import - -@interface FakePushTransitionAnimator : NSObject -@property (nonatomic, assign, getter = isPresenting) BOOL presenting; -@end diff --git a/WordPress/Classes/FakePushTransitionAnimator.m b/WordPress/Classes/FakePushTransitionAnimator.m deleted file mode 100644 index c47dffe3dd2a..000000000000 --- a/WordPress/Classes/FakePushTransitionAnimator.m +++ /dev/null @@ -1,60 +0,0 @@ -// -// FakePushTransitionAnimator.m -// WordPress -// -// Created by Jorge Bernal on 21/11/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import "FakePushTransitionAnimator.h" - -@implementation FakePushTransitionAnimator - -- (NSTimeInterval)transitionDuration:(id )transitionContext { - return 0.3; -} - -- (void)animateTransition:(id )transitionContext { - // Grab the from and to view controllers from the context - UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey]; - UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey]; - - // Set our ending frame. We'll modify this later if we have to - CGRect endFrame = fromViewController.view.frame; - - if (self.presenting) { - fromViewController.view.userInteractionEnabled = NO; - - [transitionContext.containerView addSubview:fromViewController.view]; - [transitionContext.containerView addSubview:toViewController.view]; - - CGRect startFrame = endFrame; - startFrame.origin.x += endFrame.size.width; - - toViewController.view.frame = startFrame; - - [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ - fromViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeDimmed; - toViewController.view.frame = endFrame; - } completion:^(BOOL finished) { - [transitionContext completeTransition:YES]; - }]; - } - else { - toViewController.view.userInteractionEnabled = YES; - - [transitionContext.containerView addSubview:toViewController.view]; - [transitionContext.containerView addSubview:fromViewController.view]; - - endFrame.origin.x += endFrame.size.width; - - [UIView animateWithDuration:[self transitionDuration:transitionContext] animations:^{ - toViewController.view.tintAdjustmentMode = UIViewTintAdjustmentModeAutomatic; - fromViewController.view.frame = endFrame; - } completion:^(BOOL finished) { - [transitionContext completeTransition:YES]; - }]; - } -} - -@end diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 7d59de6f306c..7f227a9d7afc 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -42,7 +42,7 @@ @interface LoginViewController () < WPWalkthroughTextField *_passwordText; WPWalkthroughTextField *_siteUrlText; WPNUXMainButton *_signInButton; - WPNUXBackButton *_cancelButton; + WPNUXSecondaryButton *_cancelButton; UILabel *_statusLabel; @@ -413,7 +413,7 @@ - (void)addControls // Add Cancel Button if (self.dismissBlock && _cancelButton == nil) { - _cancelButton = [[WPNUXBackButton alloc] init]; + _cancelButton = [[WPNUXSecondaryButton alloc] init]; [_cancelButton setTitle:NSLocalizedString(@"Cancel", nil) forState:UIControlStateNormal]; [_cancelButton addTarget:self action:@selector(cancelButtonAction:) forControlEvents:UIControlEventTouchUpInside]; [_cancelButton sizeToFit]; diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 995e8a2abe5a..68e005999632 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -879,7 +879,6 @@ E19DF741141F7BDD000002F3 /* libz.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = E19DF740141F7BDD000002F3 /* libz.dylib */; }; E1A03EE217422DCF0085D192 /* BlogToAccount.m in Sources */ = {isa = PBXBuildFile; fileRef = E1A03EE117422DCE0085D192 /* BlogToAccount.m */; }; E1A03F48174283E10085D192 /* BlogToJetpackAccount.m in Sources */ = {isa = PBXBuildFile; fileRef = E1A03F47174283E00085D192 /* BlogToJetpackAccount.m */; }; - E1A0E3C9183EC0FE005E911E /* FakePushTransitionAnimator.m in Sources */ = {isa = PBXBuildFile; fileRef = E1A0E3C8183EC0FE005E911E /* FakePushTransitionAnimator.m */; }; E1A0FAE7162F11CF0063B098 /* UIDevice+WordPressIdentifier.m in Sources */ = {isa = PBXBuildFile; fileRef = E1A0FAE6162F11CE0063B098 /* UIDevice+WordPressIdentifier.m */; }; E1A386C814DB05C300954CF8 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1A386C714DB05C300954CF8 /* AVFoundation.framework */; }; E1A386CA14DB05F700954CF8 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E1A386C914DB05F700954CF8 /* CoreMedia.framework */; }; @@ -1296,7 +1295,6 @@ 46F8714E1838C41600BC149B /* NSDate+StringFormatting.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSDate+StringFormatting.m"; sourceTree = ""; }; 46F871501839528C00BC149B /* reader-postaction-time.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "reader-postaction-time.png"; path = "Resources/Images/reader-postaction-time.png"; sourceTree = ""; }; 46F871511839528C00BC149B /* reader-postaction-time@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "reader-postaction-time@2x.png"; path = "Resources/Images/reader-postaction-time@2x.png"; sourceTree = ""; }; - 46F871551839802100BC149B /* WordPress 13.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "WordPress 13.xcdatamodel"; sourceTree = ""; }; 5D0077A5182AE9DF00F865DB /* ReaderMediaQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderMediaQueue.h; sourceTree = ""; }; 5D0077A6182AE9DF00F865DB /* ReaderMediaQueue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReaderMediaQueue.m; sourceTree = ""; }; 5D119DA1176FBE040073D83A /* UIImageView+AFNetworkingExtra.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIImageView+AFNetworkingExtra.h"; sourceTree = ""; }; @@ -2038,8 +2036,6 @@ E1A03EE117422DCE0085D192 /* BlogToAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlogToAccount.m; sourceTree = ""; }; E1A03F46174283DF0085D192 /* BlogToJetpackAccount.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BlogToJetpackAccount.h; sourceTree = ""; }; E1A03F47174283E00085D192 /* BlogToJetpackAccount.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = BlogToJetpackAccount.m; sourceTree = ""; }; - E1A0E3C7183EC0FE005E911E /* FakePushTransitionAnimator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FakePushTransitionAnimator.h; sourceTree = ""; }; - E1A0E3C8183EC0FE005E911E /* FakePushTransitionAnimator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FakePushTransitionAnimator.m; sourceTree = ""; }; E1A0FAE5162F11CE0063B098 /* UIDevice+WordPressIdentifier.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "UIDevice+WordPressIdentifier.h"; sourceTree = ""; }; E1A0FAE6162F11CE0063B098 /* UIDevice+WordPressIdentifier.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "UIDevice+WordPressIdentifier.m"; sourceTree = ""; }; E1A386C714DB05C300954CF8 /* AVFoundation.framework */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; @@ -3030,8 +3026,6 @@ 857F961417D950AB0071D9D1 /* WPTableViewSectionHeaderView.m */, 857F961617D95F530071D9D1 /* WPTableViewSectionFooterView.h */, 857F961717D95F530071D9D1 /* WPTableViewSectionFooterView.m */, - E1A0E3C7183EC0FE005E911E /* FakePushTransitionAnimator.h */, - E1A0E3C8183EC0FE005E911E /* FakePushTransitionAnimator.m */, ); name = "iOS 7"; sourceTree = ""; @@ -5115,7 +5109,6 @@ 5D2A8FF2175EC15800263144 /* ReaderTextFormView.m in Sources */, 5D477099175F73CA0086C6A3 /* ReaderCommentFormView.m in Sources */, 5D5A953B1760DDE0000F7A1E /* ReaderReblogFormView.m in Sources */, - E1A0E3C9183EC0FE005E911E /* FakePushTransitionAnimator.m in Sources */, 857F961817D95F530071D9D1 /* WPTableViewSectionFooterView.m in Sources */, 5D8572BA17611B36004CC20D /* ReaderUsersBlogsViewController.m in Sources */, E174F6E6172A73960004F23A /* WPAccount.m in Sources */, From 3a92bd2f1a81c0fbc253954876ef0405e68ee065 Mon Sep 17 00:00:00 2001 From: Tom Date: Wed, 27 Nov 2013 14:22:58 -0800 Subject: [PATCH 38/64] Adjusted section spacing in blog list --- WordPress/Classes/BlogListViewController.m | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 357c0cd43b91..a4e4fcd0efa3 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -239,7 +239,11 @@ - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSIntege } } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { - return 1.0; + if (section == [self sectionForAddSite]) { + return UITableViewAutomaticDimension; + } else { + return 1.0; + } } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { From 748abb6a04b081813fd5a7b3ed92d855b4f05988 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 2 Dec 2013 09:50:40 -0800 Subject: [PATCH 39/64] Fixed issue where blog list could appear empty when adding blogs with multiple accounts --- WordPress/Classes/Blog.m | 6 +----- WordPress/Classes/BlogListViewController.m | 6 ++---- 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/WordPress/Classes/Blog.m b/WordPress/Classes/Blog.m index c034db2b1e6a..78e7f183255f 100644 --- a/WordPress/Classes/Blog.m +++ b/WordPress/Classes/Blog.m @@ -221,11 +221,7 @@ - (NSArray *)sortedPostFormatNames { } - (BOOL)isWPcom { - if ([[self getOptionValue:@"wordpress.com"] boolValue]) { - return YES; - } - NSRange range = [self.xmlrpc rangeOfString:@"wordpress.com"]; - return (range.location != NSNotFound); + return self.account.isWpcom; } //WP.COM private blog. diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index a4e4fcd0efa3..f832c78c36b0 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -289,10 +289,8 @@ - (NSFetchedResultsController *)resultsController { NSManagedObjectContext *moc = [[ContextManager sharedInstance] mainContext]; NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Blog"]; [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"visible = YES"]]; - [fetchRequest setSortDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]]; - - // For some reasons, the cache sometimes gets corrupted - // Since we don't really use sections we skip the cache here + [fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"account.isWpcom" ascending:NO], [NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]]; + _resultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc From 3879a46d4233bd3b8224b627763269800e001869 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 2 Dec 2013 11:18:39 -0800 Subject: [PATCH 40/64] Moved blog management from settings to blog list --- WordPress/Classes/BlogListViewController.m | 107 ++++++++++--- WordPress/Classes/ManageBlogsViewController.h | 17 --- WordPress/Classes/ManageBlogsViewController.m | 140 ------------------ WordPress/Classes/SettingsViewController.m | 21 +-- WordPress/WordPress.xcodeproj/project.pbxproj | 6 - 5 files changed, 90 insertions(+), 201 deletions(-) delete mode 100644 WordPress/Classes/ManageBlogsViewController.h delete mode 100644 WordPress/Classes/ManageBlogsViewController.m diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index f832c78c36b0..ff149a48affe 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -17,14 +17,12 @@ #import "ContextManager.h" #import "Blog.h" #import "WPAccount.h" -#import "ManageBlogsViewController.h" CGFloat const blavatarImageSize = 50.f; @interface BlogListViewController () @property (nonatomic, strong) NSFetchedResultsController *resultsController; @property (nonatomic, strong) UIBarButtonItem *settingsButton; - @end @implementation BlogListViewController @@ -62,12 +60,8 @@ - (void)viewDidLoad } [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; - - // Uncomment the following line to preserve selection between presentations. - // self.clearsSelectionOnViewWillAppear = NO; - // Uncomment the following line to display an Edit button in the navigation bar for this view controller. - // self.navigationItem.rightBarButtonItem = self.editButtonItem; + self.navigationItem.leftBarButtonItem = self.editButtonItem; } - (void)viewWillAppear:(BOOL)animated { @@ -117,7 +111,7 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { if (section == [self sectionForAddSite]) { - return 1; + return tableView.isEditing ? 0 : 1; } id sectionInfo = [[self.resultsController sections] objectAtIndex:section]; return sectionInfo.numberOfObjects; @@ -154,17 +148,20 @@ - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButto } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section == [self sectionForAddSite]) { + if (indexPath.section == [self sectionForSelfHosted]) { + return YES; + } else { return NO; } +} - - id sectionInfo = [[self.resultsController sections] objectAtIndex:indexPath.section]; - if ([[sectionInfo name] isEqualToString:@"0"]) { - return YES; +- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { + + if (indexPath.section == [self sectionForSelfHosted] && tableView.editing ) { + return UITableViewCellEditingStyleDelete; + } else { + return UITableViewCellEditingStyleNone; } - - return NO; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { @@ -201,6 +198,28 @@ - (NSInteger)sectionForAddSite { return [self.resultsController.sections count]; } +- (NSInteger)sectionForDotCom { + + id sectionInfo = [[self.resultsController sections] objectAtIndex:0]; + if ([[sectionInfo name] isEqualToString:@"1"]) { + return 0; + } else { + return -1; + } +} + +- (NSInteger)sectionForSelfHosted { + + NSInteger sectionsCount = [self.resultsController sections].count; + if (sectionsCount > 1) { + return 1; + } else if (sectionsCount > 0 && [[[[self.resultsController sections] objectAtIndex:0] name] isEqualToString:@"0"]) { + return 0; + } else { + return -1; + } +} + - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { cell.textLabel.textAlignment = NSTextAlignmentLeft; cell.accessoryType = UITableViewCellAccessoryNone; @@ -226,7 +245,21 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa } [cell.imageView setImageWithBlavatarUrl:blog.blavatarUrl isWPcom:blog.isWPcom]; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + if ([self.tableView isEditing] && blog.isWPcom) { + UISwitch *visibilitySwitch = [UISwitch new]; + visibilitySwitch.on = blog.visible; + visibilitySwitch.tag = indexPath.row; + [visibilitySwitch addTarget:self action:@selector(switchDidChange:) forControlEvents:UIControlEventValueChanged]; + cell.accessoryView = visibilitySwitch; + + // Make textLabel light gray if blog is not-visible + if (!visibilitySwitch.on) { + [cell.textLabel setTextColor:[WPStyleGuide readGrey]]; + } + + } else { + cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; + } } } @@ -277,6 +310,27 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa return 54; } +- (void)setEditing:(BOOL)editing animated:(BOOL)animated { + [self.tableView beginUpdates]; + [super setEditing:editing animated:animated]; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[self sectionForAddSite]] withRowAnimation:UITableViewRowAnimationAutomatic]; + + // Reload the .com section + NSInteger sectionForDotCom = [self sectionForDotCom]; + if (sectionForDotCom >= 0) { + [self updateFetchRequest]; + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:sectionForDotCom] withRowAnimation:UITableViewRowAnimationAutomatic]; + } + [self.tableView endUpdates]; +} + +- (void)switchDidChange:(id)sender { + + UISwitch *switcher = (UISwitch *)sender; + Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:switcher.tag inSection:0]]; + blog.visible = switcher.on; + [blog dataSave]; +} #pragma mark - #pragma mark NSFetchedResultsController @@ -288,9 +342,9 @@ - (NSFetchedResultsController *)resultsController { NSManagedObjectContext *moc = [[ContextManager sharedInstance] mainContext]; NSFetchRequest *fetchRequest = [NSFetchRequest fetchRequestWithEntityName:@"Blog"]; - [fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"visible = YES"]]; [fetchRequest setSortDescriptors:@[[NSSortDescriptor sortDescriptorWithKey:@"account.isWpcom" ascending:NO], [NSSortDescriptor sortDescriptorWithKey:@"blogName" ascending:YES selector:@selector(localizedCaseInsensitiveCompare:)]]]; - + [fetchRequest setPredicate:[self fetchRequestPredicate]]; + _resultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:moc @@ -306,6 +360,23 @@ - (NSFetchedResultsController *)resultsController { return _resultsController; } +- (NSPredicate *)fetchRequestPredicate { + if ([self.tableView isEditing]) { + return nil; + } else { + return [NSPredicate predicateWithFormat:@"visible = YES"]; + } +} + +- (void)updateFetchRequest { + self.resultsController.fetchRequest.predicate = [self fetchRequestPredicate]; + + NSError *error = nil; + if (![self.resultsController performFetch:&error]) { + DDLogError(@"Couldn't fetch blogs: %@", [error localizedDescription]); + } +} + - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { [self.tableView beginUpdates]; } diff --git a/WordPress/Classes/ManageBlogsViewController.h b/WordPress/Classes/ManageBlogsViewController.h deleted file mode 100644 index b5b9c90729ca..000000000000 --- a/WordPress/Classes/ManageBlogsViewController.h +++ /dev/null @@ -1,17 +0,0 @@ -// -// ManageBlogsViewController.h -// WordPress -// -// Created by Jorge Bernal on 27/11/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import -#import "WPAccount.h" - -/** - An interface to manage which blogs are visible for a given account - */ -@interface ManageBlogsViewController : UITableViewController -- (id)initWithAccount:(WPAccount *)account; -@end diff --git a/WordPress/Classes/ManageBlogsViewController.m b/WordPress/Classes/ManageBlogsViewController.m deleted file mode 100644 index f9a9c6ba8206..000000000000 --- a/WordPress/Classes/ManageBlogsViewController.m +++ /dev/null @@ -1,140 +0,0 @@ -// -// ManageBlogsViewController.m -// WordPress -// -// Created by Jorge Bernal on 27/11/13. -// Copyright (c) 2013 WordPress. All rights reserved. -// - -#import "ManageBlogsViewController.h" -#import "Blog.h" -#import "UIImageView+Gravatar.h" - -static NSString * const CellIdentifier = @"ManageBlogsCell"; - -@implementation ManageBlogsViewController { - WPAccount *_account; - NSArray *_blogs; - UIActivityIndicatorView *_activityIndicator; -} - -- (id)initWithAccount:(WPAccount *)account { - self = [super initWithStyle:UITableViewStyleGrouped]; - if (self) { - _account = account; - } - return self; -} - -- (void)viewDidLoad { - [super viewDidLoad]; - self.title = NSLocalizedString(@"Visible Blogs", nil); - [self.tableView registerClass:[UITableViewCell class] forCellReuseIdentifier:CellIdentifier]; - - _activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; - self.tableView.tableFooterView = _activityIndicator; - - [self buildToolbar]; - [self updateBlogs]; -} - -- (void)viewWillAppear:(BOOL)animated { - [super viewWillAppear:animated]; - - [self refreshBlogs]; -} - -- (void)viewWillDisappear:(BOOL)animated { - [super viewWillDisappear:animated]; - - [self.navigationController setToolbarHidden:YES animated:animated]; -} - -- (void)buildToolbar { - UIBarButtonItem *showAll = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Show All", @"Show all blogs (Manage Blogs)") style:UIBarButtonItemStyleBordered target:self action:@selector(showAll:)]; - UIBarButtonItem *separator = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; - UIBarButtonItem *hideAll = [[UIBarButtonItem alloc] initWithTitle:NSLocalizedString(@"Hide All", @"Hide all blogs (Manage Blogs)") style:UIBarButtonItemStyleBordered target:self action:@selector(hideAll:)]; - [self setToolbarItems:@[showAll, separator, hideAll]]; -} - -- (void)updateBlogs { - _blogs = [[_account.blogs allObjects] sortedArrayUsingSelector:@selector(blogName)]; - if ([_blogs count] > 2) { - [self.navigationController setToolbarHidden:NO animated:YES]; - } else { - [self.navigationController setToolbarHidden:YES animated:YES]; - } -} - -- (void)refreshBlogs { - [_activityIndicator startAnimating]; - [_account syncBlogsWithSuccess:^{ - [self updateBlogs]; - [self.tableView reloadData]; - [_activityIndicator stopAnimating]; - } failure:^(NSError *error) { - [_activityIndicator stopAnimating]; - }]; -} - -- (void)setAllBlogsVisible:(BOOL)visible { - [_blogs enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - Blog *blog = (Blog *)obj; - blog.visible = visible; - }]; - [_account.managedObjectContext save:nil]; - [self.tableView reloadData]; -} - -- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { - return 1; -} - -- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { - return [_blogs count]; -} - -- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section { - return NSLocalizedString(@"Visible Blogs", nil); -} - -- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; - Blog *blog = [_blogs objectAtIndex:indexPath.row]; - [cell.imageView setImageWithBlavatarUrl:blog.blavatarUrl isWPcom:YES]; - cell.textLabel.text = blog.blogName; - UISwitch *visibilitySwitch = [UISwitch new]; - visibilitySwitch.on = blog.visible; - visibilitySwitch.tag = indexPath.row; - [visibilitySwitch addTarget:self action:@selector(switchChanged:) forControlEvents:UIControlEventValueChanged]; - cell.accessoryView = visibilitySwitch; - - return cell; -} - -- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath]; - UISwitch *switcher = (UISwitch *)cell.accessoryView; - if ([switcher isKindOfClass:[UISwitch class]]) { - [switcher setOn:!switcher.on animated:YES]; - [self switchChanged:switcher]; - } - [tableView deselectRowAtIndexPath:indexPath animated:YES]; -} - -- (void)switchChanged:(id)sender { - UISwitch *switcher = (UISwitch *)sender; - Blog *blog = [_blogs objectAtIndex:switcher.tag]; - blog.visible = switcher.on; - [blog dataSave]; -} - -- (void)showAll:(id)sender { - [self setAllBlogsVisible:YES]; -} - -- (void)hideAll:(id)sender { - [self setAllBlogsVisible:NO]; -} - -@end diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index f62788aff721..1dd2c6938508 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -38,7 +38,6 @@ #import "SupportViewController.h" #import "WPAccount.h" #import "WPTableViewSectionHeaderView.h" -#import "ManageBlogsViewController.h" #import "SupportViewController.h" #import "ContextManager.h" @@ -153,10 +152,6 @@ - (BOOL)supportsNotifications { return nil != [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; } -- (BOOL)supportsManageBlogs { - return [[[WPAccount defaultWordPressComAccount] blogs] count] > 1; -} - #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { @@ -169,23 +164,16 @@ - (NSInteger)rowForSignOut { if ([self supportsNotifications]) { rowForSignOut += 1; } - if ([self supportsManageBlogs]) { - rowForSignOut += 1; - } return rowForSignOut; } - (NSInteger)rowForNotifications { if ([self supportsNotifications]) { - return [self supportsManageBlogs] ? 2 : 1; + return 1; } return -1; } -- (NSInteger)rowForManageBlogs { - return [self supportsManageBlogs] ? 1 : -1; -} - - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { switch (section) { case SettingsSectionWpcom: @@ -246,10 +234,6 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa cell.detailTextLabel.textColor = [UIColor UIColorFromHex:0x888888]; cell.selectionStyle = UITableViewCellSelectionStyleNone; cell.accessibilityIdentifier = @"wpcom-username"; - } else if (indexPath.row == [self rowForManageBlogs]) { - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; - cell.textLabel.text = NSLocalizedString(@"Manage Blogs", @""); - cell.accessibilityIdentifier = @"wpcom-manage-blogs"; } else if (indexPath.row == [self rowForNotifications]) { cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; cell.textLabel.text = NSLocalizedString(@"Manage Notifications", @""); @@ -383,9 +367,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath destructiveButtonTitle:NSLocalizedString(@"Sign Out", @"")otherButtonTitles:nil, nil ]; actionSheet.actionSheetStyle = UIActionSheetStyleDefault; [actionSheet showInView:self.view]; - } else if (indexPath.row == [self rowForManageBlogs]) { - ManageBlogsViewController *manageBlogsViewController = [[ManageBlogsViewController alloc] initWithAccount:[WPAccount defaultWordPressComAccount]]; - [self.navigationController pushViewController:manageBlogsViewController animated:YES]; } else if (indexPath.row == [self rowForNotifications]) { [WPMobileStats trackEventForWPCom:StatsEventSettingsClickedManageNotifications]; diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 68e005999632..55fb109998c3 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -911,7 +911,6 @@ E1D95EB817A28F5E00A3E9F3 /* WPActivityDefaults.m in Sources */ = {isa = PBXBuildFile; fileRef = E1D95EB717A28F5E00A3E9F3 /* WPActivityDefaults.m */; }; E1D95EBF17A2AB7400A3E9F3 /* video_play.png in Resources */ = {isa = PBXBuildFile; fileRef = E1D95EBD17A2AB7400A3E9F3 /* video_play.png */; }; E1D95EC017A2AB7400A3E9F3 /* video_play@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = E1D95EBE17A2AB7400A3E9F3 /* video_play@2x.png */; }; - E1E38AF118460AF600A0F954 /* ManageBlogsViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = E1E38AF018460AF600A0F954 /* ManageBlogsViewController.m */; }; E1E4CE0417739E3300430844 /* WPImageSourceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E1E4CE0317739E3300430844 /* WPImageSourceTest.m */; }; E1E4CE0617739FAB00430844 /* test-image.jpg in Resources */ = {isa = PBXBuildFile; fileRef = E1E4CE0517739FAB00430844 /* test-image.jpg */; }; E1E4CE081773AB4200430844 /* WPTableImageSourceTest.m in Sources */ = {isa = PBXBuildFile; fileRef = E1E4CE071773AB4200430844 /* WPTableImageSourceTest.m */; }; @@ -2085,8 +2084,6 @@ E1D95EB717A28F5E00A3E9F3 /* WPActivityDefaults.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPActivityDefaults.m; sourceTree = ""; }; E1D95EBD17A2AB7400A3E9F3 /* video_play.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = video_play.png; path = Resources/Images/video_play.png; sourceTree = ""; }; E1D95EBE17A2AB7400A3E9F3 /* video_play@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "video_play@2x.png"; path = "Resources/Images/video_play@2x.png"; sourceTree = ""; }; - E1E38AEF18460AF600A0F954 /* ManageBlogsViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ManageBlogsViewController.h; sourceTree = ""; }; - E1E38AF018460AF600A0F954 /* ManageBlogsViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ManageBlogsViewController.m; sourceTree = ""; }; E1E4CE0317739E3300430844 /* WPImageSourceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPImageSourceTest.m; sourceTree = ""; }; E1E4CE0517739FAB00430844 /* test-image.jpg */ = {isa = PBXFileReference; lastKnownFileType = image.jpeg; path = "test-image.jpg"; sourceTree = ""; }; E1E4CE071773AB4200430844 /* WPTableImageSourceTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WPTableImageSourceTest.m; sourceTree = ""; }; @@ -3266,8 +3263,6 @@ 83FEFC7411FF6C5A0078B462 /* EditSiteViewController.m */, 85D8055B171631F10075EEAC /* SelectWPComLanguageViewController.h */, 85D8055C171631F10075EEAC /* SelectWPComLanguageViewController.m */, - E1E38AEF18460AF600A0F954 /* ManageBlogsViewController.h */, - E1E38AF018460AF600A0F954 /* ManageBlogsViewController.m */, ); name = Blog; sourceTree = ""; @@ -5016,7 +5011,6 @@ E12F95B9155820A40067A653 /* NSObject+BlockObservation.m in Sources */, A25EBD87156E330600530E3D /* WPTableViewController.m in Sources */, 5DEB61B4156FCD3400242C35 /* WPWebView.m in Sources */, - E1E38AF118460AF600A0F954 /* ManageBlogsViewController.m in Sources */, 5DEB61B8156FCD5200242C35 /* WPChromelessWebViewController.m in Sources */, CC24E5EF1577D1EA00A6D5B5 /* WPFriendFinderViewController.m in Sources */, E1AB07AD1578D34300D6AD64 /* SettingsViewController.m in Sources */, From 85b1ce8c22ba52d74ef255ce5ea97a352dd4e91b Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 2 Dec 2013 14:01:03 -0800 Subject: [PATCH 41/64] Prevented unnecessary refresh of blogs list --- WordPress/Classes/BlogListViewController.m | 30 +++++++++++++--------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index ff149a48affe..46b8fa46bb07 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -23,6 +23,7 @@ @interface BlogListViewController () @property (nonatomic, strong) NSFetchedResultsController *resultsController; @property (nonatomic, strong) UIBarButtonItem *settingsButton; +@property (nonatomic) BOOL controllerDidDeleteSection; @end @implementation BlogListViewController @@ -384,18 +385,22 @@ - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView endUpdates]; - /* - This covers the corner case when the only self hosted blog is removed and - there's a WordPress.com account. - - Since we only show the section title if there are multiple blog sections, - the section header wouldn't change when the section count changed, and it - would still display the wordpress.com header. - - It's not a big deal but it wouldn't be consistent with future appearances - of the same view. - */ - [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; + if (self.controllerDidDeleteSection) { + /* + This covers the corner case when the only self hosted blog is removed and + there's a WordPress.com account. + + Since we only show the section title if there are multiple blog sections, + the section header wouldn't change when the section count changed, and it + would still display the wordpress.com header. + + It's not a big deal but it wouldn't be consistent with future appearances + of the same view. + */ + + [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; + self.controllerDidDeleteSection = NO; + } } - (void)controller:(NSFetchedResultsController *)controller @@ -440,6 +445,7 @@ - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; + self.controllerDidDeleteSection = YES; break; default: From 57c5f2b998155c7ebb1269350d8c7f8eff77ddc5 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 2 Dec 2013 14:01:25 -0800 Subject: [PATCH 42/64] Fixed crash when hiding all of an accounts blogs --- WordPress/Classes/BlogListViewController.m | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 46b8fa46bb07..96dd56e4c1a2 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -312,17 +312,8 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa } - (void)setEditing:(BOOL)editing animated:(BOOL)animated { - [self.tableView beginUpdates]; [super setEditing:editing animated:animated]; - [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:[self sectionForAddSite]] withRowAnimation:UITableViewRowAnimationAutomatic]; - - // Reload the .com section - NSInteger sectionForDotCom = [self sectionForDotCom]; - if (sectionForDotCom >= 0) { - [self updateFetchRequest]; - [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:sectionForDotCom] withRowAnimation:UITableViewRowAnimationAutomatic]; - } - [self.tableView endUpdates]; + [self updateFetchRequest]; } - (void)switchDidChange:(id)sender { @@ -376,6 +367,8 @@ - (void)updateFetchRequest { if (![self.resultsController performFetch:&error]) { DDLogError(@"Couldn't fetch blogs: %@", [error localizedDescription]); } + + [self.tableView reloadData]; } - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { From 32b1b000bd0adec57fd3c8f723aed1000b863f74 Mon Sep 17 00:00:00 2001 From: Tom Date: Mon, 2 Dec 2013 14:02:17 -0800 Subject: [PATCH 43/64] Prevented saving visibility of blog if no changes were made --- WordPress/Classes/BlogListViewController.m | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 96dd56e4c1a2..4b29c0ba524f 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -320,8 +320,10 @@ - (void)switchDidChange:(id)sender { UISwitch *switcher = (UISwitch *)sender; Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:switcher.tag inSection:0]]; - blog.visible = switcher.on; - [blog dataSave]; + if (switcher.on != blog.visible) { + blog.visible = switcher.on; + [blog dataSave]; + } } #pragma mark - From ec918a1447fee2b17b016884d05b38eac2b99104 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 09:21:39 -0800 Subject: [PATCH 44/64] Added animated transition when entering edit mode in the blogs list --- WordPress/Classes/BlogListViewController.m | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index f5d0017e643d..68ecb065576f 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -341,7 +341,21 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa - (void)setEditing:(BOOL)editing animated:(BOOL)animated { [super setEditing:editing animated:animated]; + + // Animate view to editing mode + __block UIView *snapshot = [self.view snapshotViewAfterScreenUpdates:NO]; + snapshot.frame = [self.view convertRect:self.view.frame fromView:self.view.superview]; + [self.view addSubview:snapshot]; + + // Update results controller to show hidden blogs [self updateFetchRequest]; + + [UIView animateWithDuration:0.2 animations:^{ + snapshot.alpha = 0.0; + } completion:^(BOOL finished) { + [snapshot removeFromSuperview]; + snapshot = nil; + }]; } - (void)switchDidChange:(id)sender { From 241af7d6e38e60cb83b3236237ca67d9b0288370 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:06:12 -0800 Subject: [PATCH 45/64] Renamed boolean with better naming convention --- WordPress/Classes/BlogListViewController.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 68ecb065576f..a945b2c556d7 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -24,7 +24,7 @@ @interface BlogListViewController () @property (nonatomic, strong) NSFetchedResultsController *resultsController; @property (nonatomic, strong) UIBarButtonItem *settingsButton; -@property (nonatomic) BOOL controllerDidDeleteSection; +@property (nonatomic) BOOL sectionDeletedByController; @end @implementation BlogListViewController @@ -422,7 +422,7 @@ - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { [self.tableView endUpdates]; - if (self.controllerDidDeleteSection) { + if (self.sectionDeletedByController) { /* This covers the corner case when the only self hosted blog is removed and there's a WordPress.com account. @@ -436,7 +436,7 @@ - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller { */ [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; - self.controllerDidDeleteSection = NO; + self.sectionDeletedByController = NO; } } @@ -482,7 +482,7 @@ - (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id case NSFetchedResultsChangeDelete: [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade]; - self.controllerDidDeleteSection = YES; + self.sectionDeletedByController = YES; break; default: From 9c1bd7df3054dbbccc7c047c15272531487a889c Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:09:51 -0800 Subject: [PATCH 46/64] Blog list cleanup --- WordPress/Classes/BlogListViewController.m | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index a945b2c556d7..a13f3378ff2d 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -177,11 +177,7 @@ - (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButto } - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { - if (indexPath.section == [self sectionForSelfHosted]) { - return YES; - } else { - return NO; - } + return indexPath.section == [self sectionForSelfHosted]; } - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath { From 6143af07df0b8e3dcfe0826d08c2c12129373645 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:14:15 -0800 Subject: [PATCH 47/64] Renamed blog list visibility switch action --- WordPress/Classes/BlogListViewController.m | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index a13f3378ff2d..ff47ccd4707c 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -274,7 +274,7 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa UISwitch *visibilitySwitch = [UISwitch new]; visibilitySwitch.on = blog.visible; visibilitySwitch.tag = indexPath.row; - [visibilitySwitch addTarget:self action:@selector(switchDidChange:) forControlEvents:UIControlEventValueChanged]; + [visibilitySwitch addTarget:self action:@selector(visibilitySwitchAction:) forControlEvents:UIControlEventValueChanged]; cell.accessoryView = visibilitySwitch; // Make textLabel light gray if blog is not-visible @@ -354,8 +354,7 @@ - (void)setEditing:(BOOL)editing animated:(BOOL)animated { }]; } -- (void)switchDidChange:(id)sender { - +- (void)visibilitySwitchAction:(id)sender { UISwitch *switcher = (UISwitch *)sender; Blog *blog = [self.resultsController objectAtIndexPath:[NSIndexPath indexPathForRow:switcher.tag inSection:0]]; if (switcher.on != blog.visible) { From 720421ab0f32ef61698d43f00f4655782986c6f5 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:17:33 -0800 Subject: [PATCH 48/64] Additional Blog list cleanup --- WordPress/Classes/BlogListViewController.m | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index ff47ccd4707c..e52eae98e3c2 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -289,19 +289,10 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa } - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section { - // No top margin on iPhone - if ([self hasDotComAndSelfHosted]) { - return 40.0; - } else { - return 20.0; - } + return [self hasDotComAndSelfHosted] ? 40.0 : 20.0; } - (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section { - if (section == [self sectionForAddSite]) { - return UITableViewAutomaticDimension; - } else { - return 1.0; - } + return section == [self sectionForAddSite] ? UITableViewAutomaticDimension : 1.0; } - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { From f966a13f32e26ac64287e3aa1a5f2e261bfd6dbe Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:34:12 -0800 Subject: [PATCH 49/64] Renamed methods in NUX to remove "click" handlers --- WordPress/Classes/LoginViewController.m | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 7301c09c93c8..b0056ce090b4 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -266,13 +266,13 @@ - (void)helpButtonAction:(id)sender [self.navigationController presentViewController:nc animated:YES completion:nil]; } -- (void)clickedSkipToCreate:(id)sender +- (void)skipToCreateAction:(id)sender { [WPMobileStats trackEventForSelfHostedAndWPCom:StatsEventNUXFirstWalkthroughClickedCreateAccount]; [self showCreateAccountView]; } -- (void)clickedBackground:(UITapGestureRecognizer *)tapGestureRecognizer +- (void)backgroundTapGestureAction:(UITapGestureRecognizer *)tapGestureRecognizer { [self.view endEditing:YES]; @@ -328,7 +328,7 @@ - (void)addMainView _mainView.autoresizingMask = UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth; [self.view addSubview:_mainView]; - UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(clickedBackground:)]; + UITapGestureRecognizer *gestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(backgroundTapGestureAction:)]; gestureRecognizer.numberOfTapsRequired = 1; gestureRecognizer.cancelsTouchesInView = YES; [_mainView addGestureRecognizer:gestureRecognizer]; @@ -461,7 +461,7 @@ - (void)addControls if (_skipToCreateAccount == nil) { _skipToCreateAccount = [[WPNUXSecondaryButton alloc] init]; [_skipToCreateAccount setTitle:NSLocalizedString(@"Create Account", nil) forState:UIControlStateNormal]; - [_skipToCreateAccount addTarget:self action:@selector(clickedSkipToCreate:) forControlEvents:UIControlEventTouchUpInside]; + [_skipToCreateAccount addTarget:self action:@selector(skipToCreateAction:) forControlEvents:UIControlEventTouchUpInside]; [_mainView addSubview:_skipToCreateAccount]; } } From 2c6d01a6650ddadd38db50e6bc7813e95ed40aa1 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:36:39 -0800 Subject: [PATCH 50/64] Removed ternary operator from NUX for clarity --- WordPress/Classes/LoginViewController.m | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index b0056ce090b4..f8d0c27d081c 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -415,7 +415,13 @@ - (void)addControls [_mainView addSubview:_signInButton]; _signInButton.enabled = NO; } - NSString *signInTitle = _userIsDotCom ? NSLocalizedString(@"Sign In", nil) : NSLocalizedString(@"Add Site", nil); + + NSString *signInTitle; + if (_userIsDotCom) { + signInTitle = NSLocalizedString(@"Sign In", nil); + } else { + signInTitle = NSLocalizedString(@"Add Site", nil); + } [_signInButton setTitle:signInTitle forState:UIControlStateNormal]; // Add Cancel Button From 0c44fefda5ab85e463c81c3cf7ec903cebaafd4f Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:39:10 -0800 Subject: [PATCH 51/64] Fixed method capitilization in NUX --- WordPress/Classes/LoginViewController.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index f8d0c27d081c..65a7572ec52e 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -303,7 +303,7 @@ - (void)signInButtonAction:(id)sender [self signIn]; } -- (void)toggleSignInformAction:(id)sender { +- (void)toggleSignInFormAction:(id)sender { _userIsDotCom = !_userIsDotCom; // Controls are layed out in initializeView. Calling this method in an animation block will animate the controls to their new positions. @@ -447,7 +447,7 @@ - (void)addControls // Add Account type toggle if (_toggleSignInForm == nil) { _toggleSignInForm = [[WPNUXSecondaryButton alloc] init]; - [_toggleSignInForm addTarget:self action:@selector(toggleSignInformAction:) forControlEvents:UIControlEventTouchUpInside]; + [_toggleSignInForm addTarget:self action:@selector(toggleSignInFormAction:) forControlEvents:UIControlEventTouchUpInside]; _toggleSignInForm.autoresizingMask = UIViewAutoresizingFlexibleRightMargin | UIViewAutoresizingFlexibleLeftMargin; [_mainView addSubview:_toggleSignInForm]; } @@ -455,7 +455,7 @@ - (void)addControls // Add Account type toggle if (_toggleSignInForm == nil) { _toggleSignInForm = [[WPNUXSecondaryButton alloc] init]; - [_toggleSignInForm addTarget:self action:@selector(toggleSignInformAction:) forControlEvents:UIControlEventTouchUpInside]; + [_toggleSignInForm addTarget:self action:@selector(toggleSignInFormAction:) forControlEvents:UIControlEventTouchUpInside]; [_mainView addSubview:_toggleSignInForm]; } NSString *toggleTitle = _userIsDotCom ? NSLocalizedString(@"Add Self-Hosted Site", nil) : NSLocalizedString(@"Sign in to WordPress.com", nil); From a80b3969fac5f5e527d3e26b2fb5fd65a8b6c109 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:40:22 -0800 Subject: [PATCH 52/64] Additional ternary operator removal for clarity in NUX --- WordPress/Classes/LoginViewController.m | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 65a7572ec52e..86129e5b4cae 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -458,7 +458,12 @@ - (void)addControls [_toggleSignInForm addTarget:self action:@selector(toggleSignInFormAction:) forControlEvents:UIControlEventTouchUpInside]; [_mainView addSubview:_toggleSignInForm]; } - NSString *toggleTitle = _userIsDotCom ? NSLocalizedString(@"Add Self-Hosted Site", nil) : NSLocalizedString(@"Sign in to WordPress.com", nil); + NSString *toggleTitle; + if (_userIsDotCom) { + toggleTitle = NSLocalizedString(@"Add Self-Hosted Site", nil); + } else { + toggleTitle = NSLocalizedString(@"Sign in to WordPress.com", nil); + } [_toggleSignInForm setTitle:toggleTitle forState:UIControlStateNormal]; } From 84a620e3ef5e7b869642706e39e91fd3ac0c7962 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:41:18 -0800 Subject: [PATCH 53/64] Removed iOS 7 check from LoginViewController --- WordPress/Classes/LoginViewController.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 86129e5b4cae..3f945e9a9577 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -485,7 +485,7 @@ - (void)layoutControls UIImage *infoButtonImage = [UIImage imageNamed:@"btn-about"]; y = 0; - if (IS_IOS7 && IS_IPHONE) { + if (IS_IPHONE) { y = GeneralWalkthroughiOS7StatusBarOffset; } _helpButton.frame = CGRectMake(viewWidth - infoButtonImage.size.width, y, infoButtonImage.size.width, infoButtonImage.size.height); @@ -493,7 +493,7 @@ - (void)layoutControls // Layout Cancel Button x = 0; y = 0.5 * GeneralWalkthroughStandardOffset; - if (IS_IOS7 && IS_IPHONE) { + if (IS_IPHONE) { y += GeneralWalkthroughiOS7StatusBarOffset; } _cancelButton.frame = CGRectMake(x, y, CGRectGetWidth(_cancelButton.frame), CGRectGetHeight(_cancelButton.frame)); From 43365382a6c28d1270c1b826a76387c84220c766 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:43:45 -0800 Subject: [PATCH 54/64] Cleanup in LoginViewController --- WordPress/Classes/LoginViewController.m | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 3f945e9a9577..43d34566711a 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -645,11 +645,7 @@ - (BOOL)isSiteUrlFilled - (BOOL)isSignInEnabled { - if (_userIsDotCom) { - return [self areDotComFieldsFilled]; - } else { - return [self areSelfHostedFieldsFilled]; - } + return _userIsDotCom ? [self areDotComFieldsFilled] : [self areSelfHostedFieldsFilled]; } - (BOOL)areDotComFieldsFilled From c42bbad7baa5876023ff7ca1341a6d9ab01f95d6 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 10:44:39 -0800 Subject: [PATCH 55/64] Renamed method with better naming convention --- WordPress/Classes/ReaderUsersBlogsViewController.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/Classes/ReaderUsersBlogsViewController.m b/WordPress/Classes/ReaderUsersBlogsViewController.m index a483171121b9..7776be28752b 100644 --- a/WordPress/Classes/ReaderUsersBlogsViewController.m +++ b/WordPress/Classes/ReaderUsersBlogsViewController.m @@ -84,7 +84,7 @@ - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interface #pragma mark - Instance Methods -- (NSString *)getCellTitleForBlog:(Blog *)blog { +- (NSString *)cellTitleForBlog:(Blog *)blog { if ([[blog.blogName trim] length] == 0) { return blog.hostURL; } else { @@ -123,7 +123,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N Blog *blog = [_blogs objectAtIndex:indexPath.row]; cell.showTopSeparator = ( indexPath.row == 0 ) ? YES : NO; - cell.title = [self getCellTitleForBlog:blog]; + cell.title = [self cellTitleForBlog:blog]; cell.blavatarUrl = [blog blavatarUrl]; return cell; @@ -132,7 +132,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { Blog *blog = [_blogs objectAtIndex:indexPath.row]; - return [AddUsersBlogCell rowHeightWithText:[self getCellTitleForBlog:blog]]; + return [AddUsersBlogCell rowHeightWithText:[self cellTitleForBlog:blog]]; } From 6725810f6697fb30ec21477da896e5726edb05f1 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 11:32:26 -0800 Subject: [PATCH 56/64] Fixed possible crash from calling nil completion block --- WordPress/Classes/WPAccount.m | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index dbf87ed0d8d2..199b5208f80e 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -207,7 +207,9 @@ - (void)mergeBlogs:(NSArray *)blogs withCompletion:(void (^)())completion { [parentMOC save:nil]; }]; - dispatch_async(dispatch_get_main_queue(), completion); + if (completion != nil) { + dispatch_async(dispatch_get_main_queue(), completion); + } }]; } From 7ccdc145f628d0210783bdeb8078d3c904be7edb Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 12:47:32 -0800 Subject: [PATCH 57/64] Fixed use of ContextManager when syncing an account's blog list --- WordPress/Classes/WPAccount.m | 13 ++----------- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index 199b5208f80e..5de42e571b4d 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -189,8 +189,7 @@ - (void)syncBlogsWithSuccess:(void (^)())success failure:(void (^)(NSError *erro } - (void)mergeBlogs:(NSArray *)blogs withCompletion:(void (^)())completion { - NSManagedObjectContext *backgroundMOC = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; - backgroundMOC.parentContext = self.managedObjectContext; + NSManagedObjectContext *backgroundMOC = [[ContextManager sharedInstance] backgroundContext]; NSManagedObjectID *accountID = self.objectID; [backgroundMOC performBlock:^{ @@ -198,15 +197,7 @@ - (void)mergeBlogs:(NSArray *)blogs withCompletion:(void (^)())completion { for (NSDictionary *blog in blogs) { [account findOrCreateBlogFromDictionary:blog withContext:backgroundMOC]; } - NSError *error; - if (![backgroundMOC save:&error]) { - DDLogError(@"Unresolved core data save error: %@", error); - } - NSManagedObjectContext *parentMOC = backgroundMOC.parentContext; - [parentMOC performBlockAndWait:^{ - [parentMOC save:nil]; - }]; - + [[ContextManager sharedInstance] saveContext:backgroundMOC]; if (completion != nil) { dispatch_async(dispatch_get_main_queue(), completion); } From 143d631281b14fbe5c98f9cc5a133681cc9c0266 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 12:49:01 -0800 Subject: [PATCH 58/64] Changed outdated code to modern objective-c syntax --- WordPress/Classes/ReaderUsersBlogsViewController.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/WordPress/Classes/ReaderUsersBlogsViewController.m b/WordPress/Classes/ReaderUsersBlogsViewController.m index 7776be28752b..266817af6913 100644 --- a/WordPress/Classes/ReaderUsersBlogsViewController.m +++ b/WordPress/Classes/ReaderUsersBlogsViewController.m @@ -121,7 +121,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell.isWPCom = YES; } - Blog *blog = [_blogs objectAtIndex:indexPath.row]; + Blog *blog = _blogs[indexPath.row]; cell.showTopSeparator = ( indexPath.row == 0 ) ? YES : NO; cell.title = [self cellTitleForBlog:blog]; cell.blavatarUrl = [blog blavatarUrl]; @@ -131,7 +131,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - Blog *blog = [_blogs objectAtIndex:indexPath.row]; + Blog *blog = _blogs[indexPath.row]; return [AddUsersBlogCell rowHeightWithText:[self cellTitleForBlog:blog]]; } @@ -139,7 +139,7 @@ - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPa #pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - NSDictionary *dict = [_blogs objectAtIndex:indexPath.row]; + NSDictionary *dict = _blogs[indexPath.row]; [self.delegate userDidSelectBlog:dict]; [self dismissViewControllerAnimated:YES completion:nil]; From 50343305c4ec4966f5e7dc9397cfaee8ea1ea646 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 13:11:58 -0800 Subject: [PATCH 59/64] Disabled dismiss button on login screen during authentication --- WordPress/Classes/LoginViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 43d34566711a..b87c3ec190d2 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -683,6 +683,7 @@ - (void)setAuthenticating:(BOOL)authenticating withStatusMessage:(NSString *)sta _signInButton.enabled = !authenticating; _toggleSignInForm.hidden = authenticating; _skipToCreateAccount.hidden = authenticating; + _cancelButton.enabled = !authenticating; [_signInButton showActivityIndicator:authenticating]; } From e2313489258768c5fb95313842106e53e33fa036 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 13:19:46 -0800 Subject: [PATCH 60/64] Fixed issue where blog list edit button could become disabled --- WordPress/Classes/BlogListViewController.m | 26 +++++++++++++--------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index e52eae98e3c2..343489c24d9f 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -207,8 +207,7 @@ - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEd // Update the UI in the next run loop after the resultsController has updated // (otherwise row insertion/deletion logic won't work) dispatch_async(dispatch_get_main_queue(), ^{ - self.editButtonItem.enabled = NO; - [self setEditing:NO animated:YES]; + [self setEditing:NO animated:NO]; // No blogs and signed out, show NUX if (![WPAccount defaultWordPressComAccount]) { @@ -330,19 +329,24 @@ - (void)setEditing:(BOOL)editing animated:(BOOL)animated { [super setEditing:editing animated:animated]; // Animate view to editing mode - __block UIView *snapshot = [self.view snapshotViewAfterScreenUpdates:NO]; - snapshot.frame = [self.view convertRect:self.view.frame fromView:self.view.superview]; - [self.view addSubview:snapshot]; + __block UIView *snapshot; + if (animated) { + snapshot = [self.view snapshotViewAfterScreenUpdates:NO]; + snapshot.frame = [self.view convertRect:self.view.frame fromView:self.view.superview]; + [self.view addSubview:snapshot]; + } // Update results controller to show hidden blogs [self updateFetchRequest]; - [UIView animateWithDuration:0.2 animations:^{ - snapshot.alpha = 0.0; - } completion:^(BOOL finished) { - [snapshot removeFromSuperview]; - snapshot = nil; - }]; + if (animated) { + [UIView animateWithDuration:0.2 animations:^{ + snapshot.alpha = 0.0; + } completion:^(BOOL finished) { + [snapshot removeFromSuperview]; + snapshot = nil; + }]; + } } - (void)visibilitySwitchAction:(id)sender { From 981b27702785637e1b65cda15c0c6801311f7e30 Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 14:49:13 -0800 Subject: [PATCH 61/64] Removed disclosure indicator from Add Site row in blogs list --- WordPress/Classes/BlogListViewController.m | 1 - 1 file changed, 1 deletion(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 343489c24d9f..e723775a0a4f 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -252,7 +252,6 @@ - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPa if (indexPath.section == [self sectionForAddSite]) { cell.textLabel.text = NSLocalizedString(@"Add a Site", @""); cell.selectionStyle = UITableViewCellSelectionStyleBlue; - cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; // To align the label, create and add a blank image UIGraphicsBeginImageContextWithOptions(CGSizeMake(blavatarImageSize, blavatarImageSize), NO, 0.0); From f6ad0ac1bdb2385f2398475a52d2327f054d0f7e Mon Sep 17 00:00:00 2001 From: Tom Date: Tue, 3 Dec 2013 14:49:28 -0800 Subject: [PATCH 62/64] Moved dismiss button in NUX to the correct side --- WordPress/Classes/LoginViewController.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index b87c3ec190d2..61363903d041 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -491,7 +491,7 @@ - (void)layoutControls _helpButton.frame = CGRectMake(viewWidth - infoButtonImage.size.width, y, infoButtonImage.size.width, infoButtonImage.size.height); // Layout Cancel Button - x = 0; + x = viewWidth - CGRectGetWidth(_cancelButton.frame); y = 0.5 * GeneralWalkthroughStandardOffset; if (IS_IPHONE) { y += GeneralWalkthroughiOS7StatusBarOffset; From 58b701e20db08b6884ac9640d91f406dbeb8ea6b Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 4 Dec 2013 18:49:46 +0100 Subject: [PATCH 63/64] Added comment on why the extra section --- WordPress/Classes/BlogListViewController.m | 1 + 1 file changed, 1 insertion(+) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index e723775a0a4f..3f98b2078d68 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -135,6 +135,7 @@ - (void)showSettings:(id)sender { #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { + // Adding an extra section for "Add Site" return [self.resultsController.sections count] + 1; } From fd55376065187c829c7637be770c9bf07c15bffd Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Wed, 4 Dec 2013 18:54:10 +0100 Subject: [PATCH 64/64] Moved reader refresh to the app delegate I don't feel much better about this than the login controller triggering it, but let's fix it properly on #22 --- WordPress/Classes/LoginViewController.m | 2 -- WordPress/Classes/WordPressAppDelegate.m | 5 +++++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index 61363903d041..577aa8a53e9d 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -26,7 +26,6 @@ #import "WPNUXUtility.h" #import "WPNUXBackButton.h" #import "WPAccount.h" -#import "ReaderPost.h" #import "Note.h" @interface LoginViewController () < @@ -768,7 +767,6 @@ - (void)createWordPressComAccountForUsername:(NSString *)username password:(NSSt [self setAuthenticating:NO withStatusMessage:nil]; [self displayRemoteError:error]; }]; - [ReaderPost fetchPostsWithCompletionHandler:nil]; [account.restApi getNotificationsSince:nil success:nil failure:nil]; } diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index e09166b738c4..ec3ffd2e57d6 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -32,6 +32,7 @@ #import #import #import "ContextManager.h" +#import "ReaderPost.h" #import #import @@ -1041,6 +1042,10 @@ - (void)handleDefaultAccountChangedNotification:(NSNotification *)notification { [self toggleExtraDebuggingIfNeeded]; [NotificationsManager registerForPushNotifications]; [self showWelcomeScreenIfNeededAnimated:NO]; + // If the notification object is not nil, then it's a login + if (notification.object) { + [ReaderPost fetchPostsWithCompletionHandler:nil]; + } } @end