From 72125ae0a452972630822fc030873b485d4ad2c3 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 5 Dec 2013 18:15:03 +0100 Subject: [PATCH 01/23] Get authToken from account --- WordPress/Classes/Blog.m | 2 +- WordPress/Classes/NotificationsManager.m | 2 +- WordPress/Classes/WPAccount.h | 5 +++++ 3 files changed, 7 insertions(+), 2 deletions(-) diff --git a/WordPress/Classes/Blog.m b/WordPress/Classes/Blog.m index 5ec7e7f41f7f..fbe40d368101 100644 --- a/WordPress/Classes/Blog.m +++ b/WordPress/Classes/Blog.m @@ -518,7 +518,7 @@ - (WPXMLRPCClient *)api { // Enable compression for wp.com only, as some self hosted have connection issues if (self.isWPcom) { [_api setDefaultHeader:@"gzip, deflate" value:@"Accept-Encoding"]; - [_api setAuthorizationHeaderWithToken:[WordPressComApi sharedApi].authToken]; + [_api setAuthorizationHeaderWithToken:self.account.authToken]; } } return _api; diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index 33e806f464d4..4f6c47636ddd 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -75,7 +75,7 @@ + (void)unregisterDeviceToken { ]; WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:authURL]]; - [api setAuthorizationHeaderWithToken:[[WordPressComApi sharedApi] authToken]]; + [api setAuthorizationHeaderWithToken:account.authToken]; [api callMethod:@"wpcom.mobile_push_unregister_token" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { diff --git a/WordPress/Classes/WPAccount.h b/WordPress/Classes/WPAccount.h index b69769cec77a..c76d8ffb19f9 100644 --- a/WordPress/Classes/WPAccount.h +++ b/WordPress/Classes/WPAccount.h @@ -37,6 +37,11 @@ extern NSString * const WPAccountDefaultWordPressComAccountChangedNotification; */ @property (nonatomic, retain) NSString *password; +/** + The OAuth2 auth token for WordPress.com accounts + */ +@property (nonatomic, readonly) NSString *authToken; + ///------------------------------------ /// @name Default WordPress.com account ///------------------------------------ From 5083e71b4ff896dc10619e6b44ae049ef229fe52 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 5 Dec 2013 18:47:18 +0100 Subject: [PATCH 02/23] Migrated some WordPressComApi calls to WPAccount --- WordPress/Classes/Note.m | 2 +- WordPress/Classes/WPMobileStats.m | 9 +++-- WordPress/Classes/WPcomLoginViewController.m | 41 +++++++++----------- 3 files changed, 25 insertions(+), 27 deletions(-) diff --git a/WordPress/Classes/Note.m b/WordPress/Classes/Note.m index dc704f7ee316..a8e0d858017c 100644 --- a/WordPress/Classes/Note.m +++ b/WordPress/Classes/Note.m @@ -86,7 +86,7 @@ + (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context { NSError *error = nil; NSArray *notes = [context executeFetchRequest:request error:&error]; if ([notes count] > 0) { - [[WordPressComApi sharedApi] refreshNotifications:notes fields:@"id,unread" success:nil failure:nil]; + [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:notes fields:@"id,unread" success:nil failure:nil]; } } diff --git a/WordPress/Classes/WPMobileStats.m b/WordPress/Classes/WPMobileStats.m index c68327e3bd68..4c42c98cfbf7 100644 --- a/WordPress/Classes/WPMobileStats.m +++ b/WordPress/Classes/WPMobileStats.m @@ -249,16 +249,17 @@ + (void)initializeStats // Tracking session count will help us isolate users who just installed the app NSUInteger sessionCount = [[[[Mixpanel sharedInstance] currentSuperProperties] objectForKey:@"session_count"] intValue]; sessionCount++; - + + WPAccount *account = [WPAccount defaultWordPressComAccount]; NSDictionary *properties = @{ @"platform": @"iOS", @"session_count": @(sessionCount), - @"connected_to_dotcom": @([[WordPressComApi sharedApi] hasCredentials]), + @"connected_to_dotcom": @(account != nil), @"number_of_blogs" : @([Blog countWithContext:[[ContextManager sharedInstance] mainContext]]) }; [[Mixpanel sharedInstance] registerSuperProperties:properties]; - NSString *username = [[WPAccount defaultWordPressComAccount] username]; - if ([[WordPressComApi sharedApi] hasCredentials] && [username length] > 0) { + NSString *username = account.username; + if (account && [username length] > 0) { [[Mixpanel sharedInstance] identify:username]; [[Mixpanel sharedInstance].people increment:@"Application Opened" by:@(1)]; [[Mixpanel sharedInstance].people set:@{ @"$username": username, @"$first_name" : username }]; diff --git a/WordPress/Classes/WPcomLoginViewController.m b/WordPress/Classes/WPcomLoginViewController.m index 07c219ffebb0..76f350ec6baa 100644 --- a/WordPress/Classes/WPcomLoginViewController.m +++ b/WordPress/Classes/WPcomLoginViewController.m @@ -23,7 +23,6 @@ @interface WPcomLoginViewController () { @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 @@ -32,7 +31,6 @@ @implementation WPcomLoginViewController @synthesize footerText, buttonText, isSigningIn, isCancellable, predefinedUsername; @synthesize delegate; -@synthesize wpComApi = _wpComApi; + (void)presentLoginScreen { UIViewController *rootViewController = [[[UIApplication sharedApplication] keyWindow] rootViewController]; @@ -55,7 +53,6 @@ - (void)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", @""); @@ -339,25 +336,25 @@ - (void)signIn:(id)sender { } else { isSigningIn = YES; self.footerText = @" "; - [self.wpComApi signInWithUsername:username - password:password - success:^{ - 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) { - [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]; - }]; + [[WordPressComApi anonymousApi] signInWithUsername:username + password:password + success:^{ + 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) { + [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]; } From 13b3625663a61df7ddcfedc341d5f37cec6cd95e Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Thu, 5 Dec 2013 18:47:45 +0100 Subject: [PATCH 03/23] Don't sync notification settings on app active --- WordPress/Classes/WordPressAppDelegate.m | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index 33b52b2cff61..3827d8d3da0d 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -229,9 +229,8 @@ - (void)applicationDidBecomeActive:(UIApplication *)application { [WPMobileStats recordAppOpenedForEvent:StatsEventAppOpened]; - // Clear notifications badge and update server + // Clear notifications badge [UIApplication sharedApplication].applicationIconBadgeNumber = 0; - [[WordPressComApi sharedApi] syncPushNotificationInfo]; } - (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder From 3c2ad67b31dbda064350c0397a26184aa863a0b6 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Mon, 9 Dec 2013 13:36:36 -0500 Subject: [PATCH 04/23] Remove calls to [WordPressComApi sharedApi] For #22 --- WordPress/Classes/Blog.m | 2 +- .../Classes/CreateAccountAndBlogViewController.m | 2 +- WordPress/Classes/EditSiteViewController.m | 6 +++--- WordPress/Classes/JetpackSettingsViewController.m | 4 ++-- WordPress/Classes/Note.m | 4 ++-- .../Classes/NotificationSettingsViewController.m | 5 +++-- .../NotificationsCommentDetailViewController.m | 2 +- .../NotificationsFollowDetailViewController.m | 2 +- WordPress/Classes/NotificationsManager.m | 10 +++++----- WordPress/Classes/NotificationsViewController.m | 2 +- WordPress/Classes/ReaderCommentFormView.m | 3 ++- WordPress/Classes/ReaderPost.m | 12 ++++++------ WordPress/Classes/ReaderPostsViewController.m | 2 +- WordPress/Classes/SettingsViewController.m | 2 +- WordPress/Classes/WPMobileStats.m | 6 +++--- WordPress/Classes/WPcomLoginViewController.m | 2 +- WordPress/Classes/WordPressAppDelegate.m | 8 ++++---- WordPress/WordPress.xcodeproj/project.pbxproj | 1 - WordPress/WordPressApi/WordPressComApi.h | 1 - WordPress/WordPressApi/WordPressComApi.m | 11 +++-------- 20 files changed, 41 insertions(+), 46 deletions(-) diff --git a/WordPress/Classes/Blog.m b/WordPress/Classes/Blog.m index 5ec7e7f41f7f..76f11a0700f3 100644 --- a/WordPress/Classes/Blog.m +++ b/WordPress/Classes/Blog.m @@ -518,7 +518,7 @@ - (WPXMLRPCClient *)api { // Enable compression for wp.com only, as some self hosted have connection issues if (self.isWPcom) { [_api setDefaultHeader:@"gzip, deflate" value:@"Accept-Encoding"]; - [_api setAuthorizationHeaderWithToken:[WordPressComApi sharedApi].authToken]; + [_api setAuthorizationHeaderWithToken:[[WPAccount defaultWordPressComAccount] restApi].authToken]; } } return _api; diff --git a/WordPress/Classes/CreateAccountAndBlogViewController.m b/WordPress/Classes/CreateAccountAndBlogViewController.m index 7409c4d6f8e8..c6f7d6fc8b31 100644 --- a/WordPress/Classes/CreateAccountAndBlogViewController.m +++ b/WordPress/Classes/CreateAccountAndBlogViewController.m @@ -661,7 +661,7 @@ - (void)createUserAndSite }; NSNumber *languageId = [_currentLanguage objectForKey:@"lang_id"]; - [[WordPressComApi sharedApi] validateWPComBlogWithUrl:[self getSiteAddressWithoutWordPressDotCom] + [[[WPAccount defaultWordPressComAccount] restApi] validateWPComBlogWithUrl:[self getSiteAddressWithoutWordPressDotCom] andBlogTitle:[self generateSiteTitleFromUsername:_usernameField.text] andLanguageId:languageId success:blogValidationSuccess diff --git a/WordPress/Classes/EditSiteViewController.m b/WordPress/Classes/EditSiteViewController.m index 100529d9faed..77563e30b6ae 100644 --- a/WordPress/Classes/EditSiteViewController.m +++ b/WordPress/Classes/EditSiteViewController.m @@ -70,7 +70,7 @@ - (void)viewDidLoad { _notificationPreferences = [[[NSUserDefaults standardUserDefaults] objectForKey:@"notification_preferences"] mutableCopy]; if (!_notificationPreferences) { - [[WordPressComApi sharedApi] fetchNotificationSettings:^{ + [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationSettings:^{ [self reloadNotificationSettings]; } failure:^(NSError *error) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"") @@ -135,7 +135,7 @@ - (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)sectio case 0: return 3; // URL, username, password case 1: // Settings: Geolocation, [ Push Notifications ] - if (self.blog && ( [self.blog isWPcom] || [self.blog hasJetpack] ) && [[WordPressComApi sharedApi] hasCredentials] && [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey] != nil) + if (self.blog && ( [self.blog isWPcom] || [self.blog hasJetpack] ) && [[[WPAccount defaultWordPressComAccount] restApi] hasCredentials] && [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey] != nil) return 2; else return 1; @@ -448,7 +448,7 @@ - (void)togglePushNotifications:(id)sender { [[NSUserDefaults standardUserDefaults] setValue:_notificationPreferences forKey:@"notification_preferences"]; // Send these settings optimistically since they're low-impact (not ideal but works for now) - [[WordPressComApi sharedApi] saveNotificationSettings:nil failure:nil]; + [[[WPAccount defaultWordPressComAccount] restApi] saveNotificationSettings:nil failure:nil]; return; } } diff --git a/WordPress/Classes/JetpackSettingsViewController.m b/WordPress/Classes/JetpackSettingsViewController.m index dc8e52cc90c0..def914fba06f 100644 --- a/WordPress/Classes/JetpackSettingsViewController.m +++ b/WordPress/Classes/JetpackSettingsViewController.m @@ -310,8 +310,8 @@ - (void)saveAction:(id)sender { [_blog validateJetpackUsername:_usernameField.text password:_passwordField.text success:^{ - if (![[WordPressComApi sharedApi] hasCredentials]) { - [[WordPressComApi sharedApi] signInWithUsername:_usernameField.text password:_passwordField.text success:nil failure:nil]; + if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) { + [[[WPAccount defaultWordPressComAccount] restApi] signInWithUsername:_usernameField.text password:_passwordField.text success:nil failure:nil]; } [self setAuthenticating:NO]; if (self.completionBlock) { diff --git a/WordPress/Classes/Note.m b/WordPress/Classes/Note.m index dc704f7ee316..0268d5840049 100644 --- a/WordPress/Classes/Note.m +++ b/WordPress/Classes/Note.m @@ -86,7 +86,7 @@ + (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context { NSError *error = nil; NSArray *notes = [context executeFetchRequest:request error:&error]; if ([notes count] > 0) { - [[WordPressComApi sharedApi] refreshNotifications:notes fields:@"id,unread" success:nil failure:nil]; + [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:notes fields:@"id,unread" success:nil failure:nil]; } } @@ -131,7 +131,7 @@ + (void)pruneOldNotesBefore:(NSNumber *)timestamp withContext:(NSManagedObjectCo + (void)getNewNotificationswithContext:(NSManagedObjectContext *)context success:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure { NSNumber *timestamp = [self lastNoteTimestampWithContext:context]; - [[WordPressComApi sharedApi] getNotificationsSince:timestamp success:^(AFHTTPRequestOperation *operation, id responseObject) { + [[[WPAccount defaultWordPressComAccount] restApi] getNotificationsSince:timestamp success:^(AFHTTPRequestOperation *operation, id responseObject) { NSArray *notes = [responseObject arrayForKey:@"notes"]; if (success) { success([notes count] > 0); diff --git a/WordPress/Classes/NotificationSettingsViewController.m b/WordPress/Classes/NotificationSettingsViewController.m index 824139291598..580e9b9b5f72 100644 --- a/WordPress/Classes/NotificationSettingsViewController.m +++ b/WordPress/Classes/NotificationSettingsViewController.m @@ -15,6 +15,7 @@ #import "NSString+XMLExtensions.h" #import "DateUtils.h" #import "WPTableViewSectionHeaderView.h" +#import "WPAccount.h" @interface NotificationSettingsViewController () @@ -74,7 +75,7 @@ - (void)viewWillAppear:(BOOL)animated { } - (void)getNotificationSettings { - [[WordPressComApi sharedApi] fetchNotificationSettings:^{ + [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationSettings:^{ [self notificationsDidFinishRefreshingWithError: nil]; } failure:^(NSError *error) { [self notificationsDidFinishRefreshingWithError: error]; @@ -252,7 +253,7 @@ - (void)dismiss { - (void)viewWillDisappear:(BOOL)animated { self.navigationController.toolbarHidden = YES; if (hasChanges) - [[WordPressComApi sharedApi] saveNotificationSettings:nil failure:nil]; + [[[WPAccount defaultWordPressComAccount] restApi] saveNotificationSettings:nil failure:nil]; [super viewWillDisappear:animated]; } diff --git a/WordPress/Classes/NotificationsCommentDetailViewController.m b/WordPress/Classes/NotificationsCommentDetailViewController.m index 04bff42306b9..c01b80132e45 100644 --- a/WordPress/Classes/NotificationsCommentDetailViewController.m +++ b/WordPress/Classes/NotificationsCommentDetailViewController.m @@ -375,7 +375,7 @@ - (IBAction)moderateComment:(id)sender { NSDictionary *response = (NSDictionary *)responseObject; if (response) { NSArray *noteArray = [NSArray arrayWithObject:_note]; - [[WordPressComApi sharedApi] refreshNotifications:noteArray fields:nil success:^(AFHTTPRequestOperation *operation, id refreshResponseObject) { + [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:noteArray fields:nil success:^(AFHTTPRequestOperation *operation, id refreshResponseObject) { [spinner stopAnimating]; [self displayNote]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { diff --git a/WordPress/Classes/NotificationsFollowDetailViewController.m b/WordPress/Classes/NotificationsFollowDetailViewController.m index cb99c67d09cb..1204dba22e37 100644 --- a/WordPress/Classes/NotificationsFollowDetailViewController.m +++ b/WordPress/Classes/NotificationsFollowDetailViewController.m @@ -246,7 +246,7 @@ - (void)followBlog:(id)sender { NSUInteger blogID = [[noteDetails objectForKey:@"site_id"] intValue]; if (blogID) { - [[WordPressComApi sharedApi] followBlog:blogID isFollowing:isFollowing success:^(AFHTTPRequestOperation *operation, id responseObject) { + [[[WPAccount defaultWordPressComAccount] restApi] followBlog:blogID isFollowing:isFollowing success:^(AFHTTPRequestOperation *operation, id responseObject) { NSDictionary *followResponse = (NSDictionary *)responseObject; if (followResponse && [[followResponse objectForKey:@"success"] intValue] == 1) { if ([[followResponse objectForKey:@"is_following"] intValue] == 1) { diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index 33e806f464d4..721635bb8ad4 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -43,7 +43,7 @@ + (void)registerDeviceToken:(NSData *)deviceToken { if (![previousToken isEqualToString:myToken]) { DDLogInfo(@"Device Token has changed! OLD Value %@, NEW value %@", previousToken, myToken); [[NSUserDefaults standardUserDefaults] setObject:myToken forKey:kApnsDeviceTokenPrefKey]; - [[WordPressComApi sharedApi] syncPushNotificationInfo]; + [[[WPAccount defaultWordPressComAccount] restApi] syncPushNotificationInfo]; } } @@ -58,7 +58,7 @@ + (void)unregisterDeviceToken { return; } - if (![[WordPressComApi sharedApi] hasCredentials]) { + if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) { return; } @@ -75,7 +75,7 @@ + (void)unregisterDeviceToken { ]; WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:authURL]]; - [api setAuthorizationHeaderWithToken:[[WordPressComApi sharedApi] authToken]]; + [api setAuthorizationHeaderWithToken:[[[WPAccount defaultWordPressComAccount] restApi] authToken]]; [api callMethod:@"wpcom.mobile_push_unregister_token" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) { @@ -94,8 +94,8 @@ + (void)handleNotification:(NSDictionary*)userInfo forState:(UIApplicationState) switch (state) { case UIApplicationStateActive: - [[WordPressComApi sharedApi] checkForNewUnseenNotifications]; - [[WordPressComApi sharedApi] syncPushNotificationInfo]; + [[[WPAccount defaultWordPressComAccount] restApi] checkForNewUnseenNotifications]; + [[[WPAccount defaultWordPressComAccount] restApi] syncPushNotificationInfo]; break; case UIApplicationStateInactive: diff --git a/WordPress/Classes/NotificationsViewController.m b/WordPress/Classes/NotificationsViewController.m index b5cc91d7742b..268c579e63e0 100644 --- a/WordPress/Classes/NotificationsViewController.m +++ b/WordPress/Classes/NotificationsViewController.m @@ -39,7 +39,7 @@ - (id)init { self = [super init]; if (self) { self.title = NSLocalizedString(@"Notifications", @"Notifications View Controller title"); - self.user = [WordPressComApi sharedApi]; + self.user = [[WPAccount defaultWordPressComAccount] restApi]; } return self; } diff --git a/WordPress/Classes/ReaderCommentFormView.m b/WordPress/Classes/ReaderCommentFormView.m index 3828db463cbe..996bf488e940 100644 --- a/WordPress/Classes/ReaderCommentFormView.m +++ b/WordPress/Classes/ReaderCommentFormView.m @@ -11,6 +11,7 @@ #import "WPToast.h" #import "IOS7CorrectedTextView.h" #import "ContextManager.h" +#import "WPAccount.h" @implementation ReaderCommentFormView @@ -54,7 +55,7 @@ - (void)handleSendButtonTapped:(id)sender { } NSDictionary *params = @{@"content":str}; - [[WordPressComApi sharedApi] postPath:path parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { + [[[WPAccount defaultWordPressComAccount] restApi] postPath:path parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { NSDictionary *params = @{@"number":@100}; diff --git a/WordPress/Classes/ReaderPost.m b/WordPress/Classes/ReaderPost.m index 3d54a14e044d..e658f862f6a8 100644 --- a/WordPress/Classes/ReaderPost.m +++ b/WordPress/Classes/ReaderPost.m @@ -506,7 +506,7 @@ - (void)toggleLikedWithSuccess:(void (^)())success failure:(void (^)(NSError *er path = [NSString stringWithFormat:@"sites/%@/posts/%@/likes/mine/delete", self.siteID, self.postID]; } - [[WordPressComApi sharedApi] postPath:path parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { + [[[WPAccount defaultWordPressComAccount] restApi] postPath:path parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { [self save]; if(success) { @@ -538,7 +538,7 @@ - (void)toggleFollowingWithSuccess:(void (^)())success failure:(void (^)(NSError path = [NSString stringWithFormat:@"sites/%@/follows/mine/delete", self.siteID]; } - [[WordPressComApi sharedApi] postPath:path parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { + [[[WPAccount defaultWordPressComAccount] restApi] postPath:path parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { [self save]; if(success) { @@ -563,7 +563,7 @@ - (void)reblogPostToSite:(id)site note:(NSString *)note success:(void (^)())succ } NSString *path = [NSString stringWithFormat:@"sites/%@/posts/%@/reblogs/new", self.siteID, self.postID]; - [[WordPressComApi sharedApi] postPath:path parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { + [[[WPAccount defaultWordPressComAccount] restApi] postPath:path parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { NSDictionary *dict = (NSDictionary *)responseObject; self.isReblogged = [dict numberForKey:@"is_reblogged"]; @@ -740,7 +740,7 @@ + (void)getReaderTopicsWithSuccess:(WordPressComApiRestSuccessResponseBlock)succ NSString *path = @"reader/topics"; - [[WordPressComApi sharedApi] getPath:path parameters:nil success:success failure:failure]; + [[[WPAccount defaultWordPressComAccount] restApi] getPath:path parameters:nil success:success failure:failure]; } @@ -752,7 +752,7 @@ + (void)getCommentsForPost:(NSUInteger)postID NSString *path = [NSString stringWithFormat:@"sites/%@/posts/%i/replies", siteID, postID]; - [[WordPressComApi sharedApi] getPath:path parameters:params success:success failure:failure]; + [[[WPAccount defaultWordPressComAccount] restApi] getPath:path parameters:params success:success failure:failure]; } @@ -762,7 +762,7 @@ + (void)getPostsFromEndpoint:(NSString *)path success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { WPFLogMethod(); - [[WordPressComApi sharedApi] getPath:path + [[[WPAccount defaultWordPressComAccount] restApi] getPath:path parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { diff --git a/WordPress/Classes/ReaderPostsViewController.m b/WordPress/Classes/ReaderPostsViewController.m index 67dca2f08246..402347b4c76e 100644 --- a/WordPress/Classes/ReaderPostsViewController.m +++ b/WordPress/Classes/ReaderPostsViewController.m @@ -878,7 +878,7 @@ - (void)fetchBlogsAndPrimaryBlog { [[NSUserDefaults standardUserDefaults] setObject:usersBlogs forKey:@"wpcom_users_blogs"]; - [[WordPressComApi sharedApi] getPath:@"me" + [[[WPAccount defaultWordPressComAccount] restApi] getPath:@"me" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { if ([usersBlogs count] < 1) diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index 1dd2c6938508..527411f12441 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -334,7 +334,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N [self configureCell:cell atIndexPath:indexPath]; BOOL isSignInCell = NO; - if (![[WordPressComApi sharedApi] hasCredentials]) { + if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) { isSignInCell = indexPath.section == SettingsSectionWpcom && indexPath.row == 0; } diff --git a/WordPress/Classes/WPMobileStats.m b/WordPress/Classes/WPMobileStats.m index c68327e3bd68..235b4a0f236d 100644 --- a/WordPress/Classes/WPMobileStats.m +++ b/WordPress/Classes/WPMobileStats.m @@ -253,12 +253,12 @@ + (void)initializeStats NSDictionary *properties = @{ @"platform": @"iOS", @"session_count": @(sessionCount), - @"connected_to_dotcom": @([[WordPressComApi sharedApi] hasCredentials]), + @"connected_to_dotcom": @([[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]), @"number_of_blogs" : @([Blog countWithContext:[[ContextManager sharedInstance] mainContext]]) }; [[Mixpanel sharedInstance] registerSuperProperties:properties]; NSString *username = [[WPAccount defaultWordPressComAccount] username]; - if ([[WordPressComApi sharedApi] hasCredentials] && [username length] > 0) { + if ([[[WPAccount defaultWordPressComAccount] restApi] hasCredentials] && [username length] > 0) { [[Mixpanel sharedInstance] identify:username]; [[Mixpanel sharedInstance].people increment:@"Application Opened" by:@(1)]; [[Mixpanel sharedInstance].people set:@{ @"$username": username, @"$first_name" : username }]; @@ -364,7 +364,7 @@ + (void)flagProperty:(NSString *)property forEvent:(NSString *)event - (BOOL)connectedToWordPressDotCom { - return [[WordPressComApi sharedApi] hasCredentials]; + return [[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]; } - (void)trackEventForSelfHostedAndWPCom:(NSString *)event diff --git a/WordPress/Classes/WPcomLoginViewController.m b/WordPress/Classes/WPcomLoginViewController.m index 07c219ffebb0..b4de979b742a 100644 --- a/WordPress/Classes/WPcomLoginViewController.m +++ b/WordPress/Classes/WPcomLoginViewController.m @@ -55,7 +55,7 @@ - (void)viewDidLoad { [WPStyleGuide configureColorsForView:self.view andTableView:self.tableView]; - self.wpComApi = [WordPressComApi sharedApi]; + self.wpComApi = [[WPAccount defaultWordPressComAccount] restApi]; self.footerText = @" "; self.buttonText = NSLocalizedString(@"Sign In", @""); self.navigationItem.title = NSLocalizedString(@"Sign In", @""); diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index 73454cd3698b..4e3e815722fb 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -231,7 +231,7 @@ - (void)applicationDidBecomeActive:(UIApplication *)application { // Clear notifications badge and update server [UIApplication sharedApplication].applicationIconBadgeNumber = 0; - [[WordPressComApi sharedApi] syncPushNotificationInfo]; + [[[WPAccount defaultWordPressComAccount] restApi] syncPushNotificationInfo]; } - (BOOL)application:(UIApplication *)application shouldSaveApplicationState:(NSCoder *)coder @@ -865,7 +865,7 @@ - (void)setupReachability { - (void)checkWPcomAuthentication { // Temporarily set the is authenticated flag based upon if we have a WP.com OAuth2 token // TODO :: Move this BOOL to a method on the WordPressComApi along with checkWPcomAuthentication - BOOL tempIsAuthenticated = [[WordPressComApi sharedApi] authToken].length > 0; + BOOL tempIsAuthenticated = [[[WPAccount defaultWordPressComAccount] restApi] authToken].length > 0; self.isWPcomAuthenticated = tempIsAuthenticated; NSString *authURL = @"https://wordpress.com/xmlrpc.php"; @@ -873,7 +873,7 @@ - (void)checkWPcomAuthentication { WPAccount *account = [WPAccount defaultWordPressComAccount]; if (account) { WPXMLRPCClient *client = [WPXMLRPCClient clientWithXMLRPCEndpoint:[NSURL URLWithString:authURL]]; - [client setAuthorizationHeaderWithToken:[[WordPressComApi sharedApi] authToken]]; + [client setAuthorizationHeaderWithToken:[[[WPAccount defaultWordPressComAccount] restApi] authToken]]; [client callMethod:@"wp.getUsersBlogs" parameters:[NSArray arrayWithObjects:account.username, account.password, nil] success:^(AFHTTPRequestOperation *operation, id responseObject) { @@ -883,7 +883,7 @@ - (void)checkWPcomAuthentication { if ([error.domain isEqualToString:@"WPXMLRPCFaultError"] || ([error.domain isEqualToString:@"XMLRPC"] && error.code == 403)) { self.isWPcomAuthenticated = NO; - [[WordPressComApi sharedApi] invalidateOAuth2Token]; + [[[WPAccount defaultWordPressComAccount] restApi] invalidateOAuth2Token]; } DDLogError(@"Error authenticating %@ with WordPress.com: %@", account.username, [error description]); diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 39d8433b0c69..7b1f7aaeed2e 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -1299,7 +1299,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 = ""; }; 46F8D7F9183C293200E10A38 /* ReaderPostView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderPostView.h; sourceTree = ""; }; 46F8D7FA183C293200E10A38 /* ReaderPostView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ReaderPostView.m; sourceTree = ""; }; 5D0077A5182AE9DF00F865DB /* ReaderMediaQueue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ReaderMediaQueue.h; sourceTree = ""; }; diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 3bf3dd5cf876..cc875924946a 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -39,7 +39,6 @@ extern NSString *const WordPressComApiPushAppId; @property (nonatomic,readonly,strong) NSString *password; @property (nonatomic, readonly, strong) NSString *authToken; -+ (WordPressComApi *)sharedApi; // DEPRECATED_MSG_ATTRIBUTE("Use [[WPAccount defaultWordPressComAccount] restApi] instead"); /** Returns an API without an associated user diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 50bd495312dc..6709c0864c38 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -94,11 +94,6 @@ - (void)clearWpcomCookies; @implementation WordPressComApi -+ (WordPressComApi *)sharedApi { - DDLogWarn(@"Called obsolete [WordPressComApi sharedApi]"); - return [[WPAccount defaultWordPressComAccount] restApi]; -} - + (WordPressComApi *)anonymousApi { static WordPressComApi *_anonymousApi = nil; static dispatch_once_t oncePredicate; @@ -416,7 +411,7 @@ - (void)saveNotificationSettings:(void (^)())success NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; if( nil == token ) return; //no apns token available - if(![[WordPressComApi sharedApi] hasCredentials]) + if(![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) return; NSDictionary *notificationPreferences = [[NSUserDefaults standardUserDefaults] objectForKey:@"notification_preferences"]; @@ -483,7 +478,7 @@ - (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; if( nil == token ) return; //no apns token available - if(![[WordPressComApi sharedApi] hasCredentials]) + if(![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) return; NSArray *parameters = @[[self usernameForXmlrpc], @@ -512,7 +507,7 @@ - (void)syncPushNotificationInfo { NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; if( nil == token ) return; //no apns token available - if(![[WordPressComApi sharedApi] hasCredentials]) + if(![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) return; NSString *authURL = kNotificationAuthURL; From 71204971610c30317d8b971976e4d230840b49ad Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Mon, 9 Dec 2013 14:25:31 -0500 Subject: [PATCH 05/23] Remove method that was set for removal in future If this in fact needed, it can be reverted. It was not called. --- WordPress/WordPressApi/WordPressComApi.h | 10 ---------- WordPress/WordPressApi/WordPressComApi.m | 16 ---------------- 2 files changed, 26 deletions(-) diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index cc875924946a..6e1ebe1500a1 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -63,16 +63,6 @@ extern NSString *const WordPressComApiPushAppId; - (void)validateWPComBlogWithUrl:(NSString *)blogUrl andBlogTitle:(NSString *)blogTitle andLanguageId:(NSNumber *)languageId success:(void (^)(id))success failure:(void (^)(NSError *))failure; - (void)createWPComBlogWithUrl:(NSString *)blogUrl andBlogTitle:(NSString *)blogTitle andLanguageId:(NSNumber *)languageId andBlogVisibility:(WordPressComApiBlogVisibility)visibility success:(void (^)(id))success failure:(void (^)(NSError *))failure; -///--------------------------- -/// @name Transitional methods -///--------------------------- - -/** - Reloads `self.username` and `self.password` from the defaults dictionary and keychain - - Since WordPressComApi uses tokens now, this shouldn't be necessary and will be removed in the future - */ -- (void)updateCredentailsFromStore; ///-------------------- /// @name Notifications diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 6709c0864c38..fb5860b1b8f8 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -377,22 +377,6 @@ - (void)createWPComBlogWithUrl:(NSString *)blogUrl andBlogTitle:(NSString *)blog [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) { From 3e61881d4a640ac54ed168acb41543ea0190a2e8 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Mon, 9 Dec 2013 14:34:27 -0500 Subject: [PATCH 06/23] Collapse WPComApi and WPAccount notifications For account change #22 --- WordPress/Classes/BlogListViewController.m | 5 +---- WordPress/Classes/ReaderPostsViewController.m | 8 +++++--- WordPress/Classes/StatsWebViewController.m | 17 ++++------------- WordPress/WordPressApi/WordPressComApi.h | 3 --- WordPress/WordPressApi/WordPressComApi.m | 5 +---- 5 files changed, 11 insertions(+), 27 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index 8a8b711436d9..ef9d3011bcb1 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -78,10 +78,7 @@ - (void)viewDidLoad { 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) { + [[NSNotificationCenter defaultCenter] addObserverForName:WPAccountDefaultWordPressComAccountChangedNotification object:nil queue:nil usingBlock:^(NSNotification *note) { [self.tableView reloadSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade]; }]; diff --git a/WordPress/Classes/ReaderPostsViewController.m b/WordPress/Classes/ReaderPostsViewController.m index 402347b4c76e..13944327db46 100644 --- a/WordPress/Classes/ReaderPostsViewController.m +++ b/WordPress/Classes/ReaderPostsViewController.m @@ -140,11 +140,13 @@ - (void)viewDidLoad { } // Sync content as soon as login or creation occurs - [[NSNotificationCenter defaultCenter] addObserverForName:WordPressComApiDidLoginNotification + [[NSNotificationCenter defaultCenter] addObserverForName:WPAccountDefaultWordPressComAccountChangedNotification object:nil queue:nil - usingBlock:^(NSNotification *notification){ - [self syncItems]; + usingBlock:^(NSNotification *notification) { + if ([WPAccount defaultWordPressComAccount]) { + [self syncItems]; + } }]; } diff --git a/WordPress/Classes/StatsWebViewController.m b/WordPress/Classes/StatsWebViewController.m index 29001db1b399..6628cd26fb74 100644 --- a/WordPress/Classes/StatsWebViewController.m +++ b/WordPress/Classes/StatsWebViewController.m @@ -7,7 +7,7 @@ #import "StatsWebViewController.h" #import "Blog+Jetpack.h" #import "WordPressAppDelegate.h" -#import "WordPressComApi.h" +#import "WPAccount.h" #import "AFHTTPClient.h" #import "AFHTTPRequestOperation.h" #import "WPWebViewController.h" @@ -29,15 +29,6 @@ @interface StatsWebViewController () { @property (nonatomic, strong) AFHTTPRequestOperation *authRequest; @property (assign) BOOL authed; -+ (NSString *)lastAuthedName; -+ (void)setLastAuthedName:(NSString *)str; -+ (void)handleLogoutNotification:(NSNotification *)notification; - -- (void)clearCookies; -- (void)showAuthFailed; -- (void)showBlogSettings; -- (void)handleRefreshedWithOutValidRequest:(NSNotification *)notification; - @end @implementation StatsWebViewController @@ -71,11 +62,11 @@ + (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)ide } + (void)load { - [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleLogoutNotification:) name:WordPressComApiDidLogoutNotification object:nil]; + [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleAccountChangeNotification:) name:WPAccountDefaultWordPressComAccountChangedNotification object:nil]; } -+ (void)handleLogoutNotification:(NSNotification *)notification { - [self setLastAuthedName:nil]; ++ (void)handleAccountChangeNotification:(NSNotification *)notification { + [self setLastAuthedName:[WPAccount defaultWordPressComAccount].username]; } + (NSString *)lastAuthedName { diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 6e1ebe1500a1..b57f21018afb 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -9,9 +9,6 @@ #import #import -#define WordPressComApiDidLoginNotification @"WordPressComApiDidLogin" -#define WordPressComApiDidLogoutNotification @"WordPressComApiDidLogout" - typedef void (^WordPressComApiRestSuccessResponseBlock)(AFHTTPRequestOperation *operation, id responseObject); typedef void (^WordPressComApiRestSuccessFailureBlock)(AFHTTPRequestOperation *operation, NSError *error); diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index fb5860b1b8f8..04838162d8a4 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -166,7 +166,7 @@ - (void)signInWithUsername:(NSString *)username password:(NSString *)password su [[NSUserDefaults standardUserDefaults] synchronize]; [WordPressAppDelegate sharedWordPressApplicationDelegate].isWPcomAuthenticated = YES; // [NotificationsManager registerForPushNotifications]; - [[NSNotificationCenter defaultCenter] postNotificationName:WordPressComApiDidLoginNotification object:self.username]; +// [[NSNotificationCenter defaultCenter] postNotificationName:WordPressComApiDidLoginNotification object:self.username]; if (success) success(); } }; @@ -227,9 +227,6 @@ - (void)signOut { [self clearAuthorizationHeader]; [self clearWpcomCookies]; - - // Notify the world - [[NSNotificationCenter defaultCenter] postNotificationName:WordPressComApiDidLogoutNotification object:nil]; } - (BOOL)hasCredentials { From d41eb25150d646234771acc924c4cab8b20a6478 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Mon, 9 Dec 2013 14:37:30 -0500 Subject: [PATCH 07/23] Use WPOAuthClient for sign in Note @koke, that for JetpackSettingsVC, the effect of creating a new account may not be the correct approach taken. signInWithUsername:password:blocks use to store the authtoken internally within WordPressComApi. Now, the only way to save a token is by creating a new account. We could make `refreshTokenWithSuccess:failure` useful again for these kinds of purposes. --- .../Classes/JetpackSettingsViewController.m | 8 +++- WordPress/Classes/WPcomLoginViewController.m | 41 ++++++++++--------- WordPress/WordPressApi/WordPressComApi.h | 3 +- 3 files changed, 29 insertions(+), 23 deletions(-) diff --git a/WordPress/Classes/JetpackSettingsViewController.m b/WordPress/Classes/JetpackSettingsViewController.m index def914fba06f..aaedbb757705 100644 --- a/WordPress/Classes/JetpackSettingsViewController.m +++ b/WordPress/Classes/JetpackSettingsViewController.m @@ -16,6 +16,7 @@ #import "WPWalkthroughTextField.h" #import "WPNUXSecondaryButton.h" #import "UILabel+SuggestSize.h" +#import "WordPressComOAuthClient.h" @interface JetpackSettingsViewController () @end @@ -311,7 +312,12 @@ - (void)saveAction:(id)sender { password:_passwordField.text success:^{ if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) { - [[[WPAccount defaultWordPressComAccount] restApi] signInWithUsername:_usernameField.text password:_passwordField.text success:nil failure:nil]; + [[WordPressComOAuthClient client] authenticateWithUsername:_usernameField.text password:_passwordField.text success:^(NSString *authToken) { + WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:_usernameField.text password:_passwordField.text authToken:authToken]; + [WPAccount setDefaultWordPressComAccount:account]; + } failure:^(NSError *error) { + DDLogWarn(@"Unabled to obtain OAuth token for account credentials provided for Jetpack blog. %@", error); + }]; } [self setAuthenticating:NO]; if (self.completionBlock) { diff --git a/WordPress/Classes/WPcomLoginViewController.m b/WordPress/Classes/WPcomLoginViewController.m index 76f350ec6baa..8af5cd169b29 100644 --- a/WordPress/Classes/WPcomLoginViewController.m +++ b/WordPress/Classes/WPcomLoginViewController.m @@ -12,7 +12,7 @@ #import "UITableViewTextFieldCell.h" #import "WPTableViewActivityCell.h" #import "WPAccount.h" -#import "WordPressComApi.h" +#import "WordPressComOAuthClient.h" #import "ReachabilityUtils.h" #import "WPTableViewSectionFooterView.h" @@ -336,25 +336,26 @@ - (void)signIn:(id)sender { } else { isSigningIn = YES; self.footerText = @" "; - [[WordPressComApi anonymousApi] signInWithUsername:username - password:password - success:^{ - 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) { - [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]; - }]; + + WordPressComOAuthClient *client = [WordPressComOAuthClient client]; + [client authenticateWithUsername:username + password:password success:^(NSString *authToken) { + WPAccount *account = [WPAccount createOrUpdateWordPressComAccountWithUsername:username password:password authToken:authToken]; + [WPAccount setDefaultWordPressComAccount:account]; + [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]; } diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index b57f21018afb..2263dcf407c7 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -48,11 +48,10 @@ extern NSString *const WordPressComApiPushAppId; /// @name Account management ///------------------------- -- (void)signInWithUsername:(NSString *)username password:(NSString *)password success:(void (^)())success failure:(void (^)(NSError *error))failure; - (void)refreshTokenWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; -- (void)signInWithToken:(NSString *)token DEPRECATED_ATTRIBUTE; - (void)signOut; - (BOOL)hasCredentials; + // Wipe the OAuth2 token - (void)invalidateOAuth2Token; - (void)validateWPComAccountWithEmail:(NSString *)email andUsername:(NSString *)username andPassword:(NSString *)password success:(void (^)(id responseObject))success failure:(void (^)(NSError *error))failure; From 199a7729a449034e6194c0839f38e985a5533793 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Mon, 9 Dec 2013 17:00:39 -0500 Subject: [PATCH 08/23] Make WPAccount handle keychain and sign out tasks - WordPressComOAuthClient should likely handle the keychain for auth token - Remove kWPcomXMLRPCUrl as self.xmlrpc for a dot com blog is the same - Collapse various const NSString keys that had the same value --- WordPress/Classes/Constants.h | 1 - WordPress/Classes/WPAccount.m | 44 ++++-- WordPress/WordPressApi/WordPressComApi.h | 11 +- WordPress/WordPressApi/WordPressComApi.m | 133 ++---------------- .../WordPressApi/WordPressComOAuthClient.h | 1 + .../WordPressApi/WordPressComOAuthClient.m | 3 +- 6 files changed, 55 insertions(+), 138 deletions(-) diff --git a/WordPress/Classes/Constants.h b/WordPress/Classes/Constants.h index 941e6016f1e4..debcf52a2073 100644 --- a/WordPress/Classes/Constants.h +++ b/WordPress/Classes/Constants.h @@ -43,7 +43,6 @@ #define kStatsEndpointURL @"https://stats.wordpress.com/api/1.0/" #define kJetPackURL @"http://jetpack.me" -#define kWPcomXMLRPCUrl @"https://wordpress.com/xmlrpc.php" #define kDisabledTextColor [UIColor grayColor] diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index 5de42e571b4d..3bae8b168dbf 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -13,12 +13,15 @@ #import "WordPressComApi.h" #import "SFHFKeychainUtils.h" #import "ContextManager.h" - +#import +#import "NotificationsManager.h" +#import "WordPressComOAuthClient.h" static NSString * const DefaultDotcomAccountDefaultsKey = @"AccountDefaultDotcom"; -static NSString * const DotcomXmlrpcKey = @"https://wordpress.com/xmlrpc.php"; -static NSString * const OauthTokenServiceName = @"public-api.wordpress.com"; +static NSString * const WordPressDotcomXMLRPCKey = @"https://wordpress.com/xmlrpc.php"; + static WPAccount *__defaultDotcomAccount = nil; + NSString * const WPAccountDefaultWordPressComAccountChangedNotification = @"WPAccountDefaultWordPressComAccountChangedNotification"; @@ -70,6 +73,8 @@ + (WPAccount *)defaultWordPressComAccount { + (void)setDefaultWordPressComAccount:(WPAccount *)account { NSAssert(account.isWpcom, @"account should be a wordpress.com account"); + NSAssert(account.authToken.length > 0, @"Account should have an authToken for WP.com"); + // Make sure the account is on the main context __defaultDotcomAccount = (WPAccount *)[[[ContextManager sharedInstance] mainContext] existingObjectWithID:account.objectID error:nil]; // When the account object hasn't been saved yet, its objectID is temporary @@ -81,6 +86,10 @@ + (void)setDefaultWordPressComAccount:(WPAccount *)account { [[NSUserDefaults standardUserDefaults] setURL:accountURL forKey:DefaultDotcomAccountDefaultsKey]; [[NSUserDefaults standardUserDefaults] synchronize]; [[NSNotificationCenter defaultCenter] postNotificationName:WPAccountDefaultWordPressComAccountChangedNotification object:account]; + + [SFHFKeychainUtils storeUsername:account.username andPassword:account.authToken forServiceName:WordPressComOAuthKeychainServiceName updateExisting:YES error:nil]; + + [NotificationsManager registerForPushNotifications]; } + (void)removeDefaultWordPressComAccount { @@ -98,14 +107,29 @@ - (void)prepareForDeletion { // Invoked automatically by the Core Data framework when the receiver is about to be deleted. if (__defaultDotcomAccount == self) { [[self restApi] cancelAllHTTPOperationsWithMethod:nil path:nil]; - // FIXME: this is temporary until we move all the cleanup out of WordPressComApi - [[self restApi] signOut]; - __defaultDotcomAccount = nil; + [[self restApi] reset]; + + // Clear keychain entries + NSError *error; + [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:@"WordPress.com" error:&error]; + [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:WordPressComOAuthKeychainServiceName error:&error]; + self.password = nil; + self.authToken = nil; + + [WordPressAppDelegate sharedWordPressApplicationDelegate].isWPcomAuthenticated = NO; + + [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_username_preference"]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:DefaultDotcomAccountDefaultsKey]; + [[NSUserDefaults standardUserDefaults] synchronize]; + [[NSNotificationCenter defaultCenter] postNotificationName:WPAccountDefaultWordPressComAccountChangedNotification object:nil]; + [NotificationsManager unregisterDeviceToken]; + + __defaultDotcomAccount = nil; } } + #pragma mark - Account creation + (WPAccount *)createOrUpdateWordPressComAccountWithUsername:(NSString *)username password:(NSString *)password authToken:(NSString *)authToken { @@ -113,7 +137,7 @@ + (WPAccount *)createOrUpdateWordPressComAccountWithUsername:(NSString *)usernam } + (WPAccount *)createOrUpdateWordPressComAccountWithUsername:(NSString *)username password:(NSString *)password authToken:(NSString *)authToken context:(NSManagedObjectContext *)context { - WPAccount *account = [self createOrUpdateSelfHostedAccountWithXmlrpc:DotcomXmlrpcKey username:username andPassword:password withContext:context]; + WPAccount *account = [self createOrUpdateSelfHostedAccountWithXmlrpc:WordPressDotcomXMLRPCKey username:username andPassword:password withContext:context]; account.isWpcom = YES; account.authToken = authToken; return account; @@ -225,19 +249,19 @@ - (void)setPassword:(NSString *)password { } - (NSString *)authToken { - return [SFHFKeychainUtils getPasswordForUsername:self.username andServiceName:OauthTokenServiceName error:nil]; + return [SFHFKeychainUtils getPasswordForUsername:self.username andServiceName:WordPressComOAuthKeychainServiceName error:nil]; } - (void)setAuthToken:(NSString *)authToken { if (authToken) { [SFHFKeychainUtils storeUsername:self.username andPassword:authToken - forServiceName:OauthTokenServiceName + forServiceName:WordPressComOAuthKeychainServiceName updateExisting:YES error:nil]; } else { [SFHFKeychainUtils deleteItemForUsername:self.username - andServiceName:OauthTokenServiceName + andServiceName:WordPressComOAuthKeychainServiceName error:nil]; } } diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 2263dcf407c7..93d036832fec 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -44,12 +44,19 @@ extern NSString *const WordPressComApiPushAppId; + (WordPressComApi *)anonymousApi; - (id)initWithOAuthToken:(NSString *)authToken; +/** + Reset the API instance + + @discussion Clears authorization headers, cookies, + and sets `authToken`, `username`, and `password` to nil. + */ +- (void)reset; + ///------------------------- /// @name Account management ///------------------------- -- (void)refreshTokenWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; -- (void)signOut; + - (BOOL)hasCredentials; // Wipe the OAuth2 token diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 04838162d8a4..a57efd32af14 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -8,7 +8,6 @@ #import "WordPressComApi.h" #import "WordPressComApiCredentials.h" -#import "SFHFKeychainUtils.h" #import "WordPressAppDelegate.h" #import "Constants.h" #import "Note.h" @@ -24,8 +23,6 @@ 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"; @@ -120,113 +117,15 @@ - (id)initWithOAuthToken:(NSString *)authToken { #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] 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 { +- (void)reset { 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] synchronize]; self.authToken = nil; self.username = nil; self.password = nil; - [self clearAuthorizationHeader]; - + [self clearWpcomCookies]; + [self clearAuthorizationHeader]; } - (BOOL)hasCredentials { @@ -440,6 +339,8 @@ - (void)saveNotificationSettings:(void (^)())success @"apple", WordPressComApiPushAppId ]; + /* + * Remove extra api client, remove reference to kWPcomXMLRPCUrl WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:kWPcomXMLRPCUrl]]; [api setAuthorizationHeaderWithToken:self.authToken]; //Update supported notifications dictionary @@ -453,6 +354,7 @@ - (void)saveNotificationSettings:(void (^)())success if (failure) failure(error); }]; + */ } - (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError *error))failure { @@ -469,6 +371,8 @@ - (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError WordPressComApiPushAppId ]; + /* + * Remove extra api client, remove reference to kWPcomXMLRPCUrl WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:kWPcomXMLRPCUrl]]; [api setAuthorizationHeaderWithToken:self.authToken]; [api callMethod:@"wpcom.get_mobile_push_notification_settings" @@ -482,6 +386,7 @@ - (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError if (failure) failure(error); }]; + */ } - (void)syncPushNotificationInfo { @@ -720,26 +625,6 @@ - (NSString *)passwordForXmlrpc { } /* HACK ENDS */ -#pragma mark - Oauth methods - -- (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]]; } diff --git a/WordPress/WordPressApi/WordPressComOAuthClient.h b/WordPress/WordPressApi/WordPressComOAuthClient.h index 0134fceebd69..a800ab1864fd 100644 --- a/WordPress/WordPressApi/WordPressComOAuthClient.h +++ b/WordPress/WordPressApi/WordPressComOAuthClient.h @@ -9,6 +9,7 @@ #import "AFHTTPClient.h" extern NSString * const WordPressComOAuthErrorDomain; +extern NSString * const WordPressComOAuthKeychainServiceName; typedef NS_ENUM(NSUInteger, WordPressComOAuthError) { WordPressComOAuthErrorUnknown, diff --git a/WordPress/WordPressApi/WordPressComOAuthClient.m b/WordPress/WordPressApi/WordPressComOAuthClient.m index c4130e734b5b..2fefbef39a6a 100644 --- a/WordPress/WordPressApi/WordPressComOAuthClient.m +++ b/WordPress/WordPressApi/WordPressComOAuthClient.m @@ -10,10 +10,11 @@ #import "WordPressComApiCredentials.h" NSString * const WordPressComOAuthErrorDomain = @"WordPressComOAuthError"; - +NSString * const WordPressComOAuthKeychainServiceName = @"public-api.wordpress.com"; static NSString * const WordPressComOAuthBaseUrl = @"https://public-api.wordpress.com/oauth2"; static NSString * const WordPressComOAuthRedirectUrl = @"http://wordpress.com/"; + @implementation WordPressComOAuthClient + (WordPressComOAuthClient *)client { From 0a9b1a27b5db6af4f3ac5e347c098c481c6aa5b1 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 13:58:07 -0500 Subject: [PATCH 09/23] Move notifications constants, add convenience --- WordPress/Classes/Constants.h | 2 -- WordPress/Classes/EditSiteViewController.m | 5 ++++- WordPress/Classes/NotificationsManager.h | 16 ++++++++++++++++ WordPress/Classes/NotificationsManager.m | 20 +++++++++++++------- WordPress/Classes/SettingsViewController.m | 9 +++------ WordPress/Classes/WordPressAppDelegate.m | 2 +- 6 files changed, 37 insertions(+), 17 deletions(-) diff --git a/WordPress/Classes/Constants.h b/WordPress/Classes/Constants.h index debcf52a2073..6b1470678a2c 100644 --- a/WordPress/Classes/Constants.h +++ b/WordPress/Classes/Constants.h @@ -19,7 +19,6 @@ #define kTextFieldFont @"Arial" #define kTextViewPlaceholder @"Tap here to begin writing." #define kAppStoreURL @"http://itunes.apple.com/us/app/wordpress/id335703880?mt=8" -#define kNotificationAuthURL @"https://wordpress.com/xmlrpc.php" #define kMobileReaderFakeLoaderURL @"https://en.wordpress.com/reader/mobile/v2/loader" #define kMobileReaderURL @"https://en.wordpress.com/reader/mobile/v2/?chrome=no" @@ -145,7 +144,6 @@ #define kNotificationTypeAchievement @"ac" #define kSettingsMuteSoundsKey @"settings_mute_sounds" -#define kApnsDeviceTokenPrefKey @"apnsDeviceToken" typedef NS_ENUM(NSUInteger, MediaType) { diff --git a/WordPress/Classes/EditSiteViewController.m b/WordPress/Classes/EditSiteViewController.m index 77563e30b6ae..c5c5c9f31daa 100644 --- a/WordPress/Classes/EditSiteViewController.m +++ b/WordPress/Classes/EditSiteViewController.m @@ -15,6 +15,7 @@ #import "ReachabilityUtils.h" #import "WPAccount.h" #import "WPTableViewSectionHeaderView.h" +#import "NotificationsManager.h" #import #import #import @@ -135,7 +136,9 @@ - (NSInteger)tableView:(UITableView *)tv numberOfRowsInSection:(NSInteger)sectio case 0: return 3; // URL, username, password case 1: // Settings: Geolocation, [ Push Notifications ] - if (self.blog && ( [self.blog isWPcom] || [self.blog hasJetpack] ) && [[[WPAccount defaultWordPressComAccount] restApi] hasCredentials] && [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey] != nil) + if (self.blog && ( [self.blog isWPcom] || [self.blog hasJetpack] ) && + [[[WPAccount defaultWordPressComAccount] restApi] hasCredentials] && + [NotificationsManager deviceRegisteredForPushNotifications]) return 2; else return 1; diff --git a/WordPress/Classes/NotificationsManager.h b/WordPress/Classes/NotificationsManager.h index d62267328c87..9b9f78dcf3a4 100644 --- a/WordPress/Classes/NotificationsManager.h +++ b/WordPress/Classes/NotificationsManager.h @@ -7,6 +7,10 @@ * Some rights reserved. See license.txt */ +/** + The persisted device token + */ +extern NSString *const NotificationsDeviceToken; @interface NotificationsManager : NSObject @@ -38,6 +42,18 @@ */ + (void)unregisterDeviceToken; +/** + Returns whether the device is currently registered for remote notifications + + @return YES if the device is registered for WordPress.com notifications + @return NO if not + */ ++ (BOOL)deviceRegisteredForPushNotifications; + +///---------------------------- +/// @name Notification Handling +///---------------------------- + /** Handle the notification received, and call the completion handler for background work diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index cfa158ffcb96..0dec2cfbf452 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -16,6 +16,9 @@ #import #import "ContextManager.h" +static NSString *const NotificationsPreferencesKey = @"notification_preferences"; +NSString *const NotificationsDeviceToken = @"apnsDeviceToken"; + @implementation NotificationsManager + (void)registerForPushNotifications { @@ -31,25 +34,25 @@ + (void)registerForPushNotifications { #pragma mark - Device token registration + (void)registerDeviceToken:(NSData *)deviceToken { - NSString *myToken = [[[[deviceToken description] + NSString *newToken = [[[[deviceToken description] stringByReplacingOccurrencesOfString: @"<" withString: @""] stringByReplacingOccurrencesOfString: @">" withString: @""] stringByReplacingOccurrencesOfString: @" " withString: @""]; - DDLogInfo(@"Device token received in didRegisterForRemoteNotificationsWithDeviceToken: %@", myToken); + DDLogInfo(@"Device token received in didRegisterForRemoteNotificationsWithDeviceToken: %@", newToken); // Store the token - NSString *previousToken = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; - if (![previousToken isEqualToString:myToken]) { - DDLogInfo(@"Device Token has changed! OLD Value %@, NEW value %@", previousToken, myToken); - [[NSUserDefaults standardUserDefaults] setObject:myToken forKey:kApnsDeviceTokenPrefKey]; [[[WPAccount defaultWordPressComAccount] restApi] syncPushNotificationInfo]; + NSString *previousToken = [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken]; + if (![previousToken isEqualToString:newToken]) { + DDLogInfo(@"Device Token has changed! OLD Value %@, NEW value %@", previousToken, newToken); + [[NSUserDefaults standardUserDefaults] setObject:newToken forKey:NotificationsDeviceToken]; } } + (void)registrationDidFail:(NSError *)error { DDLogError(@"Failed to register for push notifications: %@", error); - [[NSUserDefaults standardUserDefaults] removeObjectForKey:kApnsDeviceTokenPrefKey]; + [[NSUserDefaults standardUserDefaults] removeObjectForKey:NotificationsDeviceToken]; } + (void)unregisterDeviceToken { @@ -86,6 +89,9 @@ + (void)unregisterDeviceToken { } } ++ (BOOL)deviceRegisteredForPushNotifications { + return [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken] != nil; +} #pragma mark - Notification handling diff --git a/WordPress/Classes/SettingsViewController.m b/WordPress/Classes/SettingsViewController.m index 527411f12441..a0d837d8accd 100644 --- a/WordPress/Classes/SettingsViewController.m +++ b/WordPress/Classes/SettingsViewController.m @@ -40,6 +40,7 @@ #import "WPTableViewSectionHeaderView.h" #import "SupportViewController.h" #import "ContextManager.h" +#import "NotificationsManager.h" typedef enum { SettingsSectionWpcom = 0, @@ -148,10 +149,6 @@ - (void)maskImageView:(UIImageView *)imageView corner:(UIRectCorner)corner { imageView.layer.mask = maskLayer; } -- (BOOL)supportsNotifications { - return nil != [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; -} - #pragma mark - Table view data source - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { @@ -161,14 +158,14 @@ - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { // The Sign Out row in Wpcom section can change, so identify it dynamically - (NSInteger)rowForSignOut { NSInteger rowForSignOut = 1; - if ([self supportsNotifications]) { + if ([NotificationsManager deviceRegisteredForPushNotifications]) { rowForSignOut += 1; } return rowForSignOut; } - (NSInteger)rowForNotifications { - if ([self supportsNotifications]) { + if ([NotificationsManager deviceRegisteredForPushNotifications]) { return 1; } return -1; diff --git a/WordPress/Classes/WordPressAppDelegate.m b/WordPress/Classes/WordPressAppDelegate.m index ea2d8e4ea3d3..d377c4d7f29d 100644 --- a/WordPress/Classes/WordPressAppDelegate.m +++ b/WordPress/Classes/WordPressAppDelegate.m @@ -983,7 +983,7 @@ - (void)printDebugLaunchInfo { DDLogInfo(@"OS: %@ %@", [device systemName], [device systemVersion]); DDLogInfo(@"Language: %@", currentLanguage); DDLogInfo(@"UDID: %@", [device wordpressIdentifier]); - DDLogInfo(@"APN token: %@", [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]); + DDLogInfo(@"APN token: %@", [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken]); DDLogInfo(@"==========================================================================="); } From 2cd23256ffe29a1215f8653f8783b5e7cab42358 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 14:03:00 -0500 Subject: [PATCH 10/23] Decouple syncPushNotificationInfo Registers and gets settings via XML RPC API --- WordPress/Classes/NotificationsManager.m | 14 +++++++-- WordPress/WordPressApi/WordPressComApi.h | 4 ++- WordPress/WordPressApi/WordPressComApi.m | 38 ++++++++++++++++-------- 3 files changed, 40 insertions(+), 16 deletions(-) diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index 0dec2cfbf452..6aede28cacf3 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -42,11 +42,11 @@ + (void)registerDeviceToken:(NSData *)deviceToken { DDLogInfo(@"Device token received in didRegisterForRemoteNotificationsWithDeviceToken: %@", newToken); // Store the token - [[[WPAccount defaultWordPressComAccount] restApi] syncPushNotificationInfo]; NSString *previousToken = [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken]; if (![previousToken isEqualToString:newToken]) { DDLogInfo(@"Device Token has changed! OLD Value %@, NEW value %@", previousToken, newToken); [[NSUserDefaults standardUserDefaults] setObject:newToken forKey:NotificationsDeviceToken]; + [self syncPushNotificationInfo]; } } @@ -101,7 +101,7 @@ + (void)handleNotification:(NSDictionary*)userInfo forState:(UIApplicationState) switch (state) { case UIApplicationStateActive: [[[WPAccount defaultWordPressComAccount] restApi] checkForNewUnseenNotifications]; - [[[WPAccount defaultWordPressComAccount] restApi] syncPushNotificationInfo]; + [self syncPushNotificationInfo]; break; case UIApplicationStateInactive: @@ -142,4 +142,14 @@ + (void)handleNotificationForApplicationLaunch:(NSDictionary *)launchOptions { } } ++ (void)syncPushNotificationInfo { + NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken]; + [[[WPAccount defaultWordPressComAccount] restApi] syncPushNotificationInfoWithDeviceToken:token success:^(NSDictionary *settings) { + [[NSUserDefaults standardUserDefaults] setObject:settings forKey:NotificationsPreferencesKey]; + DDLogInfo(@"Synched push notification token and received settings %@", settings); + } failure:^(NSError *error) { + DDLogError(@"Failed to receive supported notification list: %@", [error localizedDescription]); + }]; +} + @end diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 93d036832fec..a839d922209f 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -77,8 +77,10 @@ extern NSString *const WordPressComApiPushAppId; - (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError *error))failure; -- (void)syncPushNotificationInfo; +- (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token + success:(void (^)(NSDictionary *settings))success + failure:(void (^)(NSError *error))failure; /* * Queries the REST Api for unread notes and determines if the user has * seen them using the response's last_seen_time timestamp. diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index a57efd32af14..9b374289bc51 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -23,6 +23,7 @@ NSString *const WordPressComApiClientEndpointURL = @"https://public-api.wordpress.com/rest/v1/"; NSString *const WordPressComApiOauthBaseUrl = @"https://public-api.wordpress.com/oauth2"; +NSString *const WordPressComXMLRPCUrl = @"http://wordpress.com/xmlrpc.php"; NSString *const WordPressComApiNotificationFields = @"id,type,unread,body,subject,timestamp"; NSString *const WordPressComApiUnseenNotesNotification = @"WordPressComUnseenNotes"; NSString *const WordPressComApiNotesUserInfoKey = @"notes"; @@ -389,14 +390,18 @@ - (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError */ } -- (void)syncPushNotificationInfo { - NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; - if( nil == token ) return; //no apns token available +- (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token + success:(void (^)(NSDictionary *settings))success + failure:(void (^)(NSError *error))failure { - if(![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) + if (nil == token) { + return; + } + + if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) return; - NSString *authURL = kNotificationAuthURL; + NSString *authURL = WordPressComXMLRPCUrl; // Send a multicall for register the token and retrieval of push notification settings NSMutableArray *operations = [NSMutableArray arrayWithCapacity:2]; @@ -421,10 +426,11 @@ - (void)syncPushNotificationInfo { tokenOptions ]; WPXMLRPCRequest *tokenRequest = [api XMLRPCRequestWithMethod:@"wpcom.mobile_push_register_token" parameters:parameters]; - WPXMLRPCRequestOperation *tokenOperation = [api XMLRPCRequestOperationWithRequest:tokenRequest success:^(AFHTTPRequestOperation *operation, id responseObject) { - WPFLog(@"Registered APN token %@" , token); + WPXMLRPCRequestOperation *tokenOperation = [api XMLRPCRequestOperationWithRequest:tokenRequest success:^(AFHTTPRequestOperation *op, id response){ } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - WPFLog(@"Couldn't register APN token: %@", [error localizedDescription]); + if (failure) { + failure(error); + } }]; [operations addObject:tokenOperation]; @@ -437,16 +443,22 @@ - (void)syncPushNotificationInfo { ]; 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!"); + if (success) { + success(responseObject); + } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - WPFLog(@"Failed to receive supported notification list: %@", [error localizedDescription]); + if (failure) { + failure(error); + } }]; [operations addObject:settingsOperation]; - AFHTTPRequestOperation *combinedOperation = [api combinedHTTPRequestOperationWithOperations:operations success:^(AFHTTPRequestOperation *operation, id responseObject) {} failure:^(AFHTTPRequestOperation *operation, NSError *error) {}]; + AFHTTPRequestOperation *combinedOperation = [api combinedHTTPRequestOperationWithOperations:operations success:nil failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (failure) { + failure(error); + } + }]; [api enqueueHTTPRequestOperation:combinedOperation]; } From e90f49311c6b5e1eee4726ff91a3235be36d5e46 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 14:09:24 -0500 Subject: [PATCH 11/23] Decouple saveNotificationSettings - Move app usage into NotificationsManager - Make WordPressComApi app-independent --- WordPress/Classes/EditSiteViewController.m | 2 +- .../NotificationSettingsViewController.m | 6 +- WordPress/Classes/NotificationsManager.h | 9 +++ WordPress/Classes/NotificationsManager.m | 62 +++++++++++++++++++ WordPress/WordPressApi/WordPressComApi.h | 3 +- WordPress/WordPressApi/WordPressComApi.m | 62 +++---------------- 6 files changed, 88 insertions(+), 56 deletions(-) diff --git a/WordPress/Classes/EditSiteViewController.m b/WordPress/Classes/EditSiteViewController.m index c5c5c9f31daa..e85aa77558fa 100644 --- a/WordPress/Classes/EditSiteViewController.m +++ b/WordPress/Classes/EditSiteViewController.m @@ -451,7 +451,7 @@ - (void)togglePushNotifications:(id)sender { [[NSUserDefaults standardUserDefaults] setValue:_notificationPreferences forKey:@"notification_preferences"]; // Send these settings optimistically since they're low-impact (not ideal but works for now) - [[[WPAccount defaultWordPressComAccount] restApi] saveNotificationSettings:nil failure:nil]; + [NotificationsManager saveNotificationSettings]; return; } } diff --git a/WordPress/Classes/NotificationSettingsViewController.m b/WordPress/Classes/NotificationSettingsViewController.m index 580e9b9b5f72..e49d674af41e 100644 --- a/WordPress/Classes/NotificationSettingsViewController.m +++ b/WordPress/Classes/NotificationSettingsViewController.m @@ -16,6 +16,7 @@ #import "DateUtils.h" #import "WPTableViewSectionHeaderView.h" #import "WPAccount.h" +#import "NotificationsManager.h" @interface NotificationSettingsViewController () @@ -252,8 +253,9 @@ - (void)dismiss { - (void)viewWillDisappear:(BOOL)animated { self.navigationController.toolbarHidden = YES; - if (hasChanges) - [[[WPAccount defaultWordPressComAccount] restApi] saveNotificationSettings:nil failure:nil]; + if (hasChanges){ + [NotificationsManager saveNotificationSettings]; + } [super viewWillDisappear:animated]; } diff --git a/WordPress/Classes/NotificationsManager.h b/WordPress/Classes/NotificationsManager.h index 9b9f78dcf3a4..007e74473ac9 100644 --- a/WordPress/Classes/NotificationsManager.h +++ b/WordPress/Classes/NotificationsManager.h @@ -71,4 +71,13 @@ extern NSString *const NotificationsDeviceToken; */ + (void)handleNotificationForApplicationLaunch:(NSDictionary *)launchOptions; +///-------------------------------------- +/// @name WordPress.com Notifications API +///-------------------------------------- + +/** + Sends the current settings to WordPress.com + */ ++ (void)saveNotificationSettings; + @end diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index 6aede28cacf3..b8edcd74e083 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -142,6 +142,68 @@ + (void)handleNotificationForApplicationLaunch:(NSDictionary *)launchOptions { } } + +#pragma mark - WordPress.com XML RPC API + ++ (NSDictionary *)notificationSettingsDictionary { + if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) { + return nil; + } + + NSDictionary *notificationPreferences = [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsPreferencesKey]; + if (!notificationPreferences) + return nil; + + 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 nil; + } + + return updatedSettings; +} + ++ (void)saveNotificationSettings { + NSDictionary *settings = [NotificationsManager notificationSettingsDictionary]; + NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken]; + [[[WPAccount defaultWordPressComAccount] restApi] saveNotificationSettings:settings deviceToken:token success:^{ + DDLogInfo(@"Notification settings successfully sent to WP.com\n Settings: %@", settings); + } failure:^(NSError *error){ + DDLogError(@"Failed to update notification settings on WP.com %@", error.localizedDescription); + }]; +} + + (void)syncPushNotificationInfo { NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken]; [[[WPAccount defaultWordPressComAccount] restApi] syncPushNotificationInfoWithDeviceToken:token success:^(NSDictionary *settings) { diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index a839d922209f..ac196ee06abe 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -71,7 +71,8 @@ extern NSString *const WordPressComApiPushAppId; /// @name Notifications ///-------------------- -- (void)saveNotificationSettings:(void (^)())success +- (void)saveNotificationSettings:(NSDictionary *)settings + deviceToken:(NSString *)token success:(void (^)())success failure:(void (^)(NSError *error))failure; - (void)fetchNotificationSettings:(void (^)())success diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 9b374289bc51..07964318535a 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -286,76 +286,34 @@ - (void)clearWpcomCookies { #pragma mark - Notifications -- (void)saveNotificationSettings:(void (^)())success +- (void)saveNotificationSettings:(NSDictionary *)settings deviceToken:(NSString *)token + success:(void (^)())success failure:(void (^)(NSError *error))failure { - NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; - if( nil == token ) return; //no apns token available - - if(![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) + if (nil == token) 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, + settings, token, @"apple", WordPressComApiPushAppId ]; - /* - * Remove extra api client, remove reference to kWPcomXMLRPCUrl - WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:kWPcomXMLRPCUrl]]; + + WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:WordPressComXMLRPCUrl]]; [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) + if (success) { success(); + } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) + if (failure) { failure(error); + } }]; - */ } - (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError *error))failure { From 4b1fd64e3c600205e5461bd574503fc6f6045432 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 14:11:33 -0500 Subject: [PATCH 12/23] Decouple fetchNotificationSettings - Move app usage into NotificationsManager - Make WordPressComApi app-independent --- WordPress/Classes/EditSiteViewController.m | 2 +- .../NotificationSettingsViewController.m | 6 ++--- WordPress/Classes/NotificationsManager.h | 5 ++++ WordPress/Classes/NotificationsManager.m | 16 +++++++++++++ WordPress/WordPressApi/WordPressComApi.h | 5 ++-- WordPress/WordPressApi/WordPressComApi.m | 23 ++++++++----------- 6 files changed, 38 insertions(+), 19 deletions(-) diff --git a/WordPress/Classes/EditSiteViewController.m b/WordPress/Classes/EditSiteViewController.m index e85aa77558fa..d5e252bd0ed4 100644 --- a/WordPress/Classes/EditSiteViewController.m +++ b/WordPress/Classes/EditSiteViewController.m @@ -71,7 +71,7 @@ - (void)viewDidLoad { _notificationPreferences = [[[NSUserDefaults standardUserDefaults] objectForKey:@"notification_preferences"] mutableCopy]; if (!_notificationPreferences) { - [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationSettings:^{ + [NotificationsManager fetchNotificationSettingsWithSuccess:^{ [self reloadNotificationSettings]; } failure:^(NSError *error) { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"Error", @"") diff --git a/WordPress/Classes/NotificationSettingsViewController.m b/WordPress/Classes/NotificationSettingsViewController.m index e49d674af41e..1f3b7328a84a 100644 --- a/WordPress/Classes/NotificationSettingsViewController.m +++ b/WordPress/Classes/NotificationSettingsViewController.m @@ -76,10 +76,10 @@ - (void)viewWillAppear:(BOOL)animated { } - (void)getNotificationSettings { - [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationSettings:^{ - [self notificationsDidFinishRefreshingWithError: nil]; + [NotificationsManager fetchNotificationSettingsWithSuccess:^{ + [self notificationsDidFinishRefreshingWithError:nil]; } failure:^(NSError *error) { - [self notificationsDidFinishRefreshingWithError: error]; + [self notificationsDidFinishRefreshingWithError:error]; }]; } diff --git a/WordPress/Classes/NotificationsManager.h b/WordPress/Classes/NotificationsManager.h index 007e74473ac9..4713e1f3c081 100644 --- a/WordPress/Classes/NotificationsManager.h +++ b/WordPress/Classes/NotificationsManager.h @@ -80,4 +80,9 @@ extern NSString *const NotificationsDeviceToken; */ + (void)saveNotificationSettings; +/** + Fetch the current WordPress.com settings + */ ++ (void)fetchNotificationSettingsWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; + @end diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index b8edcd74e083..9e57928f56d1 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -204,6 +204,22 @@ + (void)saveNotificationSettings { }]; } ++ (void)fetchNotificationSettingsWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { + NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken]; + [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationSettingsWithDeviceToken:token success:^(NSDictionary *settings) { + [[NSUserDefaults standardUserDefaults] setObject:settings forKey:NotificationsPreferencesKey]; + DDLogInfo(@"Received notification settings %@", settings); + if (success) { + success(); + } + } failure:^(NSError *error) { + DDLogError(@"Failed to fetch notification settings %@", error.localizedDescription); + if (failure) { + failure(error); + } + }]; +} + + (void)syncPushNotificationInfo { NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken]; [[[WPAccount defaultWordPressComAccount] restApi] syncPushNotificationInfoWithDeviceToken:token success:^(NSDictionary *settings) { diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index ac196ee06abe..3d0be2b449a6 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -75,8 +75,9 @@ extern NSString *const WordPressComApiPushAppId; deviceToken:(NSString *)token success:(void (^)())success failure:(void (^)(NSError *error))failure; -- (void)fetchNotificationSettings:(void (^)())success - failure:(void (^)(NSError *error))failure; +- (void)fetchNotificationSettingsWithDeviceToken:(NSString *)token + success:(void (^)(NSDictionary *settings))success + failure:(void (^)(NSError *error))failure; - (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 07964318535a..f0312b9d102f 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -316,11 +316,11 @@ - (void)saveNotificationSettings:(NSDictionary *)settings deviceToken:(NSString }]; } -- (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError *error))failure { - NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; - if( nil == token ) return; //no apns token available +- (void)fetchNotificationSettingsWithDeviceToken:(NSString *)token success:(void (^)(NSDictionary *settings))success failure:(void (^)(NSError *error))failure { + if( nil == token ) + return; - if(![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) + if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) return; NSArray *parameters = @[[self usernameForXmlrpc], @@ -330,22 +330,19 @@ - (void)fetchNotificationSettings:(void (^)())success failure:(void (^)(NSError WordPressComApiPushAppId ]; - /* - * Remove extra api client, remove reference to kWPcomXMLRPCUrl - WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:kWPcomXMLRPCUrl]]; + WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:WordPressComXMLRPCUrl]]; [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(); + if (success) { + success(responseObject); + } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) + if (failure) { failure(error); + } }]; - */ } - (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token From e29fcb97765e0a05746711908963ea3409515457 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 14:16:54 -0500 Subject: [PATCH 13/23] Decouple notifications unregistration - Move app usage into NotificationsManager - Make WordPressComApi app-independent --- WordPress/Classes/NotificationsManager.m | 37 ++++-------------------- WordPress/WordPressApi/WordPressComApi.h | 2 ++ WordPress/WordPressApi/WordPressComApi.m | 32 +++++++++++++++++++- 3 files changed, 39 insertions(+), 32 deletions(-) diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index 9e57928f56d1..e081494a1d58 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -56,37 +56,12 @@ + (void)registrationDidFail:(NSError *)error { } + (void)unregisterDeviceToken { - NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:kApnsDeviceTokenPrefKey]; - if (nil == token) { - return; - } - - if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) { - return; - } - - NSString *authURL = kNotificationAuthURL; - WPAccount *account = [WPAccount defaultWordPressComAccount]; - if (account) { - NSArray *parameters = @[account.username, - account.password, - token, - [[UIDevice currentDevice] wordpressIdentifier], - @"apple", - @NO, // Sandbox parameter - deprecated - WordPressComApiPushAppId - ]; - - WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:authURL]]; - [api setAuthorizationHeaderWithToken:account.authToken]; - [api callMethod:@"wpcom.mobile_push_unregister_token" - parameters:parameters - success:^(AFHTTPRequestOperation *operation, id responseObject) { - DDLogInfo(@"Unregistered token %@", token); - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - DDLogError(@"Couldn't unregister token: %@", [error localizedDescription]); - }]; - } + NSString *token = [[NSUserDefaults standardUserDefaults] objectForKey:NotificationsDeviceToken]; + [[[WPAccount defaultWordPressComAccount] restApi] unregisterForPushNotificationsWithDeviceToken:token success:^{ + DDLogInfo(@"Unregistered token %@", token); + } failure:^(NSError *error){ + DDLogError(@"Couldn't unregister token: %@", [error localizedDescription]); + }]; } + (BOOL)deviceRegisteredForPushNotifications { diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 3d0be2b449a6..3301c227e8fe 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -79,6 +79,8 @@ extern NSString *const WordPressComApiPushAppId; success:(void (^)(NSDictionary *settings))success failure:(void (^)(NSError *error))failure; +- (void)unregisterForPushNotificationsWithDeviceToken:(NSString *)token + success:(void (^)())success failure:(void (^)(NSError *error))failure; - (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token success:(void (^)(NSDictionary *settings))success diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index f0312b9d102f..594b3d98b357 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -345,10 +345,40 @@ - (void)fetchNotificationSettingsWithDeviceToken:(NSString *)token success:(void }]; } +- (void)unregisterForPushNotificationsWithDeviceToken:(NSString *)token + success:(void (^)())success failure:(void (^)(NSError *error))failure { + if (nil == token) { + return; + } + + NSArray *parameters = @[[self usernameForXmlrpc], + [self passwordForXmlrpc], + token, + @"apple", + @NO, // Sandbox parameter - deprecated + WordPressComApiPushAppId + ]; + + WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:WordPressComXMLRPCUrl]]; + [api setAuthorizationHeaderWithToken:self.authToken]; + [api callMethod:@"wpcom.mobile_push_unregister_token" + parameters:parameters + success:^(AFHTTPRequestOperation *operation, id responseObject) { + DDLogInfo(@"Unregistered token %@", token); + if (success) { + success(); + } + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + DDLogError(@"Couldn't unregister token: %@", [error localizedDescription]); + if (failure) { + failure(error); + } + }]; +} + - (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token success:(void (^)(NSDictionary *settings))success failure:(void (^)(NSError *error))failure { - if (nil == token) { return; } From a8d6f0114536280cdc017f9d47cdb6ae3ad31813 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 14:45:27 -0500 Subject: [PATCH 14/23] Remove notification from WordPressComApi - Notification was posted for checkForUnseenNotifications - Also turns out that this method is called, but nothing observes the notification - Removed the call from the app in NotificationsManager. --- WordPress/Classes/NotificationsManager.m | 3 +- WordPress/WordPressApi/WordPressComApi.h | 9 +++--- WordPress/WordPressApi/WordPressComApi.m | 37 ++++++++++-------------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index e081494a1d58..bf5f146198f0 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -75,10 +75,9 @@ + (void)handleNotification:(NSDictionary*)userInfo forState:(UIApplicationState) switch (state) { case UIApplicationStateActive: - [[[WPAccount defaultWordPressComAccount] restApi] checkForNewUnseenNotifications]; [self syncPushNotificationInfo]; break; - + case UIApplicationStateInactive: [WPMobileStats recordAppOpenedForEvent:StatsEventAppOpenedDueToPushNotification]; [[WordPressAppDelegate sharedWordPressApplicationDelegate] showNotificationsTab]; diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 3301c227e8fe..6dc52fe84e31 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -32,8 +32,8 @@ extern NSString *const WordPressComApiErrorMessageKey; extern NSString *const WordPressComApiPushAppId; @interface WordPressComApi : AFHTTPClient -@property (nonatomic,readonly,strong) NSString *username; -@property (nonatomic,readonly,strong) NSString *password; +@property (nonatomic, readonly, strong) NSString *username; +@property (nonatomic, readonly, strong) NSString *password; @property (nonatomic, readonly, strong) NSString *authToken; /** @@ -89,9 +89,10 @@ extern NSString *const WordPressComApiPushAppId; * Queries the REST Api for unread notes and determines if the user has * seen them using the response's last_seen_time timestamp. * - * If we have unseen notes we post a WordPressComApiUnseenNotesNotification */ -- (void)checkForNewUnseenNotifications; +- (void)fetchNewUnseenNotificationsWithParams:(NSDictionary *)params + success:(void (^)(NSArray *notes))success + failure:(void (^)(NSError *error))failure; - (void)checkNotificationsSuccess:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure; diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 594b3d98b357..6b67bd57074b 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -25,9 +25,6 @@ NSString *const WordPressComApiOauthBaseUrl = @"https://public-api.wordpress.com/oauth2"; NSString *const WordPressComXMLRPCUrl = @"http://wordpress.com/xmlrpc.php"; 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"; @@ -447,30 +444,32 @@ - (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token [api enqueueHTTPRequestOperation:combinedOperation]; } -- (void)checkForNewUnseenNotifications { - NSDictionary *params = @{ @"unread":@"true", @"number":@"20", @"num_note_items":@"20", @"fields" : WordPressComApiNotificationFields }; + +- (void)fetchNewUnseenNotificationsWithSuccess:(void (^)(NSArray *notes))success failure:(void (^)(NSError *error))failure { + 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"]; + NSNumber *lastSeenTime = [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) { + if ([timestamp compare:lastSeenTime] == NSOrderedDescending) { [unseenNotes addObject:noteData]; } }]; - NSNotificationCenter *nc = [NSNotificationCenter defaultCenter]; - [nc postNotificationName:WordPressComApiUnseenNotesNotification - object:self - userInfo:@{ - WordPressComApiNotesUserInfoKey : unseenNotes, - WordPressComApiUnseenNoteCountInfoKey : [NSNumber numberWithInteger:[unseenNotes count]] - }]; + + if (success) { + success([NSArray arrayWithArray:unseenNotes]); + } } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - + if (failure) { + failure(error); + } }]; } @@ -497,7 +496,6 @@ - (void)getNotificationsBefore:(NSNumber *)timestamp success:(WordPressComApiRes - (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"]; @@ -549,20 +547,15 @@ - (void)refreshNotifications:(NSArray *)notes fields:(NSString *)fields success: } - (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 { From 9564c57e81f33a059872a609ab2c276a110d3480 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 15:04:26 -0500 Subject: [PATCH 15/23] Decouple numerous headers from WordPressComApi - WPToast: present toast from callers instead - Constants, WPAccount, ContextManager, Note --- WordPress/Classes/FollowButton.m | 6 +++ .../NotificationsFollowDetailViewController.m | 6 +++ WordPress/WordPressApi/WordPressComApi.h | 5 +- WordPress/WordPressApi/WordPressComApi.m | 50 +++++++------------ 4 files changed, 32 insertions(+), 35 deletions(-) diff --git a/WordPress/Classes/FollowButton.m b/WordPress/Classes/FollowButton.m index ad48c7e9ee3c..dc828f330835 100644 --- a/WordPress/Classes/FollowButton.m +++ b/WordPress/Classes/FollowButton.m @@ -8,6 +8,7 @@ #import "FollowButton.h" #import "NSString+XMLExtensions.h" +#import "WPToast.h" @interface FollowButton () @property (nonatomic, strong) UIButton *button; @@ -82,6 +83,11 @@ - (void)toggleFollowState:(id)sender { [self.user followBlog:[self.siteID intValue] isFollowing:isFollowing success:^(AFHTTPRequestOperation *operation, id followResponse){ BOOL following = [[followResponse objectForKey:@"is_following"] intValue] == 1; self.followState = following ? FollowButtonStateFollowing : FollowButtonStateNotFollowing; + + 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]]; + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // flip the button back since it failed self.followState = isFollowing ? FollowButtonStateNotFollowing : FollowButtonStateFollowing; diff --git a/WordPress/Classes/NotificationsFollowDetailViewController.m b/WordPress/Classes/NotificationsFollowDetailViewController.m index 1204dba22e37..a6ddcd077745 100644 --- a/WordPress/Classes/NotificationsFollowDetailViewController.m +++ b/WordPress/Classes/NotificationsFollowDetailViewController.m @@ -16,6 +16,7 @@ #import "WPWebViewController.h" #import #import "WPAccount.h" +#import "WPToast.h" @interface NotificationsFollowDetailViewController () @@ -260,6 +261,11 @@ - (void)followBlog:(id)sender { } else { [cell setFollowing:isFollowing]; } + + NSString *message = isFollowing ? NSLocalizedString(@"Unfollowed", @"User unfollowed a blog") : NSLocalizedString(@"Followed", @"User followed a blog"); + NSString *imageName = [NSString stringWithFormat:@"action_icon_%@", (isFollowing) ? @"unfollowed" : @"followed"]; + [WPToast showToastWithMessage:message andImage:[UIImage imageNamed:imageName]]; + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { [cell setFollowing: isFollowing]; DDLogVerbose(@"[Rest API] ! %@", [error localizedDescription]); diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 6dc52fe84e31..3d41f08005ec 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -90,8 +90,7 @@ extern NSString *const WordPressComApiPushAppId; * seen them using the response's last_seen_time timestamp. * */ -- (void)fetchNewUnseenNotificationsWithParams:(NSDictionary *)params - success:(void (^)(NSArray *notes))success +- (void)fetchNewUnseenNotificationsWithSuccess:(void (^)(NSArray *notes))success failure:(void (^)(NSError *error))failure; - (void)checkNotificationsSuccess:(WordPressComApiRestSuccessResponseBlock)success @@ -122,7 +121,7 @@ extern NSString *const WordPressComApiPushAppId; success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure; -- (void)followBlog:(NSUInteger)blogID isFollowing:(bool)following +- (void)followBlog:(NSUInteger)blogID isFollowing:(BOOL)following success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure; diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 6b67bd57074b..d99381d379ea 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -8,18 +8,12 @@ #import "WordPressComApi.h" #import "WordPressComApiCredentials.h" -#import "WordPressAppDelegate.h" -#import "Constants.h" -#import "Note.h" #import "NSString+Helpers.h" -#import "WPToast.h" #import #import #import "UIDevice+WordPressIdentifier.h" -#import "WPAccount.h" -#import "ContextManager.h" #import - +#import "WordPressAppDelegate.h" NSString *const WordPressComApiClientEndpointURL = @"https://public-api.wordpress.com/rest/v1/"; NSString *const WordPressComApiOauthBaseUrl = @"https://public-api.wordpress.com/oauth2"; @@ -317,7 +311,7 @@ - (void)fetchNotificationSettingsWithDeviceToken:(NSString *)token success:(void if( nil == token ) return; - if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) + if (![self hasCredentials]) return; NSArray *parameters = @[[self usernameForXmlrpc], @@ -380,7 +374,7 @@ - (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token return; } - if (![[[WPAccount defaultWordPressComAccount] restApi] hasCredentials]) + if (![self hasCredentials]) return; NSString *authURL = WordPressComXMLRPCUrl; @@ -444,7 +438,6 @@ - (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token [api enqueueHTTPRequestOperation:combinedOperation]; } - - (void)fetchNewUnseenNotificationsWithSuccess:(void (^)(NSArray *notes))success failure:(void (^)(NSError *error))failure { NSDictionary *params = @{@"unread": @"true", @"number": @"20", @@ -503,7 +496,7 @@ - (void)getNotificationsWithParameters:(NSDictionary *)parameters success:(WordP // 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"]]; +// [Note syncNotesWithResponse:[responseObject objectForKey:@"notes"]]; if (success != nil ) success( operation, responseObject ); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { @@ -511,6 +504,7 @@ - (void)getNotificationsWithParameters:(NSDictionary *)parameters success:(WordP }]; } +// make notes a list of IDs instead of objects - (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) { @@ -518,7 +512,7 @@ - (void)refreshNotifications:(NSArray *)notes fields:(NSString *)fields success: } NSMutableArray *noteIDs = [[NSMutableArray alloc] initWithCapacity:[notes count]]; [notes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { - [noteIDs addObject:[(Note *)obj noteID]]; +// [noteIDs addObject:[(Note *)obj noteID]]; }]; if (fields == nil) { fields = WordPressComApiNotificationFields; @@ -527,21 +521,22 @@ - (void)refreshNotifications:(NSArray *)notes fields:(NSString *)fields success: @"fields" : fields, @"ids" : noteIDs }; - NSManagedObjectContext *context = [(Note *)[notes objectAtIndex:0] managedObjectContext]; + // Move out into notifications manager or Note? +// 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]]; - } +// 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(![context save:&error]){ +// NSLog(@"Unable to update note: %@", error); +// } if (success != nil) success(operation, response); } failure:failure ]; } @@ -558,16 +553,11 @@ - (void)updateNoteLastSeenTime:(NSNumber *)timestamp success:(WordPressComApiRes [self postPath:@"notifications/seen" parameters:@{ @"time" : timestamp } success:success failure:failure]; } -- (void)followBlog:(NSUInteger)blogID isFollowing:(bool)following success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)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) + 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){ @@ -577,9 +567,7 @@ - (void)followBlog:(NSUInteger)blogID isFollowing:(bool)following success:(WordP } - (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 @@ -587,9 +575,7 @@ - (void)moderateComment:(NSUInteger)blogID forCommentID:(NSUInteger)commentID wi } - (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 From 5072ed0f958cfa0a66dc481164fe2183cb5c7d8d Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 16:00:49 -0500 Subject: [PATCH 16/23] Decouple Note from WordPressComApi - Calls to WordPressComApi discovered that relied on the Notes being synced --- WordPress/Classes/LoginViewController.m | 2 +- WordPress/Classes/Note.h | 2 +- WordPress/Classes/Note.m | 8 +-- ...NotificationsCommentDetailViewController.m | 8 ++- WordPress/Classes/NotificationsManager.m | 2 +- .../Classes/NotificationsViewController.m | 7 +- WordPress/WordPressApi/WordPressComApi.h | 27 ++++--- WordPress/WordPressApi/WordPressComApi.m | 70 ++++++++----------- 8 files changed, 63 insertions(+), 63 deletions(-) diff --git a/WordPress/Classes/LoginViewController.m b/WordPress/Classes/LoginViewController.m index d850c484777f..a59e176f524f 100644 --- a/WordPress/Classes/LoginViewController.m +++ b/WordPress/Classes/LoginViewController.m @@ -773,7 +773,7 @@ - (void)createWordPressComAccountForUsername:(NSString *)username password:(NSSt [self setAuthenticating:NO withStatusMessage:nil]; [self displayRemoteError:error]; }]; - [account.restApi getNotificationsSince:nil success:nil failure:nil]; + [Note fetchNewNotificationsWithSuccess:nil failure:nil]; } - (void)createSelfHostedAccountAndBlogWithUsername:(NSString *)username password:(NSString *)password xmlrpc:(NSString *)xmlrpc options:(NSDictionary *)options diff --git a/WordPress/Classes/Note.h b/WordPress/Classes/Note.h index b403033b4447..6cf6b0b5ad64 100644 --- a/WordPress/Classes/Note.h +++ b/WordPress/Classes/Note.h @@ -44,6 +44,6 @@ @param context The context which contains the notes to delete. */ + (void)pruneOldNotesBefore:(NSNumber *)timestamp withContext:(NSManagedObjectContext *)context; -+ (void)getNewNotificationswithContext:(NSManagedObjectContext *)context success:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure; ++ (void)fetchNewNotificationsWithSuccess:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure; @end diff --git a/WordPress/Classes/Note.m b/WordPress/Classes/Note.m index 0268d5840049..8ebe455f9183 100644 --- a/WordPress/Classes/Note.m +++ b/WordPress/Classes/Note.m @@ -128,11 +128,11 @@ + (void)pruneOldNotesBefore:(NSNumber *)timestamp withContext:(NSManagedObjectCo [context save:&error]; } -+ (void)getNewNotificationswithContext:(NSManagedObjectContext *)context success:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure { - NSNumber *timestamp = [self lastNoteTimestampWithContext:context]; ++ (void)fetchNewNotificationsWithSuccess:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure { + NSNumber *timestamp = [self lastNoteTimestampWithContext:[ContextManager sharedInstance].backgroundContext]; - [[[WPAccount defaultWordPressComAccount] restApi] getNotificationsSince:timestamp success:^(AFHTTPRequestOperation *operation, id responseObject) { - NSArray *notes = [responseObject arrayForKey:@"notes"]; + [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationsSince:timestamp success:^(NSArray *notes) { + [Note syncNotesWithResponse:notes]; if (success) { success([notes count] > 0); } diff --git a/WordPress/Classes/NotificationsCommentDetailViewController.m b/WordPress/Classes/NotificationsCommentDetailViewController.m index c01b80132e45..9d2aa87ba38b 100644 --- a/WordPress/Classes/NotificationsCommentDetailViewController.m +++ b/WordPress/Classes/NotificationsCommentDetailViewController.m @@ -374,8 +374,12 @@ - (IBAction)moderateComment:(id)sender { [self.user postPath:path parameters:[commentAction valueForKeyPath:@"params.rest_body"] success:^(AFHTTPRequestOperation *operation, id responseObject) { NSDictionary *response = (NSDictionary *)responseObject; if (response) { - NSArray *noteArray = [NSArray arrayWithObject:_note]; - [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:noteArray fields:nil success:^(AFHTTPRequestOperation *operation, id refreshResponseObject) { + [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:@[_note.noteID] fields:nil success:^(NSArray *notes) { + if ([notes count] == 1 && ![_note isDeleted] && _note.managedObjectContext) { + [_note updateAttributes:notes[0]]; + } + + [[ContextManager sharedInstance] saveContext:_note.managedObjectContext]; [spinner stopAnimating]; [self displayNote]; } failure:^(AFHTTPRequestOperation *operation, NSError *error) { diff --git a/WordPress/Classes/NotificationsManager.m b/WordPress/Classes/NotificationsManager.m index bf5f146198f0..1b798a2d8439 100644 --- a/WordPress/Classes/NotificationsManager.m +++ b/WordPress/Classes/NotificationsManager.m @@ -88,7 +88,7 @@ + (void)handleNotification:(NSDictionary*)userInfo forState:(UIApplicationState) [[WordPressAppDelegate sharedWordPressApplicationDelegate] showNotificationsTab]; if (completionHandler) { - [Note getNewNotificationswithContext:[[ContextManager sharedInstance] mainContext] success:^(BOOL hasNewNotes) { + [Note fetchNewNotificationsWithSuccess:^(BOOL hasNewNotes) { DDLogInfo(@"notification fetch completion handler completed with new notes: %@", hasNewNotes ? @"YES" : @"NO"); if (hasNewNotes) { completionHandler(UIBackgroundFetchResultNewData); diff --git a/WordPress/Classes/NotificationsViewController.m b/WordPress/Classes/NotificationsViewController.m index 268c579e63e0..f4d8d518d359 100644 --- a/WordPress/Classes/NotificationsViewController.m +++ b/WordPress/Classes/NotificationsViewController.m @@ -291,7 +291,8 @@ - (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *erro } else { timestamp = nil; } - [self.user getNotificationsSince:timestamp success:^(AFHTTPRequestOperation *operation, id responseObject) { + [self.user fetchNotificationsSince:timestamp success:^(NSArray *notes) { + [Note syncNotesWithResponse:notes]; [self updateSyncDate]; if (success) { success(); @@ -328,9 +329,9 @@ - (void)loadMoreWithSuccess:(void (^)())success failure:(void (^)(NSError *))fai _retrievingNotifications = YES; - [self.user getNotificationsBefore:lastNote.timestamp success:^(AFHTTPRequestOperation *operation, id responseObject) { + [self.user fetchNotificationsBefore:lastNote.timestamp success:^(NSArray *notes) { _retrievingNotifications = NO; - + [Note syncNotesWithResponse:notes]; if (success) { success(); } diff --git a/WordPress/WordPressApi/WordPressComApi.h b/WordPress/WordPressApi/WordPressComApi.h index 3d41f08005ec..5cd3c915bdc7 100644 --- a/WordPress/WordPressApi/WordPressComApi.h +++ b/WordPress/WordPressApi/WordPressComApi.h @@ -93,24 +93,24 @@ extern NSString *const WordPressComApiPushAppId; - (void)fetchNewUnseenNotificationsWithSuccess:(void (^)(NSArray *notes))success failure:(void (^)(NSError *error))failure; -- (void)checkNotificationsSuccess:(WordPressComApiRestSuccessResponseBlock)success +- (void)fetchRecentNotificationsWithSuccess:(void (^)(NSArray *notes))success failure:(WordPressComApiRestSuccessFailureBlock)failure; -- (void)getNotificationsBefore:(NSNumber *)timestamp - success:(WordPressComApiRestSuccessResponseBlock)success +- (void)fetchNotificationsBefore:(NSNumber *)timestamp + success:(void (^)(NSArray *notes))success failure:(WordPressComApiRestSuccessFailureBlock)failure; -- (void)getNotificationsSince:(NSNumber *)timestamp - success:(WordPressComApiRestSuccessResponseBlock)success +- (void)fetchNotificationsSince:(NSNumber *)timestamp + success:(void (^)(NSArray *notes))success failure:(WordPressComApiRestSuccessFailureBlock)failure; -- (void)getNotificationsWithParameters:(NSDictionary *)parameters - success:(WordPressComApiRestSuccessResponseBlock)success +- (void)fetchNotificationsWithParameters:(NSDictionary *)parameters + success:(void (^)(NSArray *notes))success failure:(WordPressComApiRestSuccessFailureBlock)failure; -- (void)refreshNotifications:(NSArray *)notes +- (void)refreshNotifications:(NSArray *)noteIDs fields:(NSString *)fields - success:(WordPressComApiRestSuccessResponseBlock)success + success:(void (^)(NSArray *notes))success failure:(WordPressComApiRestSuccessFailureBlock)failure; - (void)markNoteAsRead:(NSString *)noteID @@ -121,10 +121,19 @@ extern NSString *const WordPressComApiPushAppId; success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure; +///------------- +/// @name Reader +///------------- + - (void)followBlog:(NSUInteger)blogID isFollowing:(BOOL)following success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure; + +///--------------- +/// @name Comments +///--------------- + - (void)moderateComment:(NSUInteger)blogID forCommentID:(NSUInteger)commentID withStatus:(NSString *)commentStatus success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure; diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index d99381d379ea..09041b5ad715 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -466,79 +466,65 @@ - (void)fetchNewUnseenNotificationsWithSuccess:(void (^)(NSArray *notes))success }]; } -- (void)checkNotificationsSuccess:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { - [self getNotificationsBefore:nil success:success failure:failure]; +- (void)checkNotificationsSuccess:(void (^)(NSArray *notes))success failure:(WordPressComApiRestSuccessFailureBlock)failure { + [self fetchNotificationsBefore:nil success:success failure:failure]; } -- (void)getNotificationsSince:(NSNumber *)timestamp success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { +- (void)fetchNotificationsSince:(NSNumber *)timestamp + success:(void (^)(NSArray *notes))success + failure:(WordPressComApiRestSuccessFailureBlock)failure { NSDictionary *parameters; if (timestamp != nil) { - parameters = @{ @"since" : timestamp }; + parameters = @{@"since": timestamp}; } - [self getNotificationsWithParameters:parameters success:success failure:failure]; - + [self fetchNotificationsWithParameters:parameters success:success failure:failure]; } -- (void)getNotificationsBefore:(NSNumber *)timestamp success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { +- (void)fetchNotificationsBefore:(NSNumber *)timestamp + success:(void (^)(NSArray *notes))success + failure:(WordPressComApiRestSuccessFailureBlock)failure { NSDictionary *parameters; if (timestamp != nil) { - parameters = @{ @"before" : timestamp }; + parameters = @{@"before": timestamp}; } - [self getNotificationsWithParameters:parameters success:success failure:failure]; + [self fetchNotificationsWithParameters:parameters success:success failure:failure]; } -- (void)getNotificationsWithParameters:(NSDictionary *)parameters success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { +- (void)fetchNotificationsWithParameters:(NSDictionary *)parameters success:(void (^)(NSArray *notes))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 ); - + if (success) { + success(responseObject[@"notes"]); + } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) failure(operation, error); + if (failure) { + failure(operation, error); + } }]; } -// make notes a list of IDs instead of objects -- (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) { +- (void)refreshNotifications:(NSArray *)noteIDs fields:(NSString *)fields success:(void (^)(NSArray *notes))success failure:(WordPressComApiRestSuccessFailureBlock)failure { + if ([noteIDs 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 + @"fields": fields, + @"ids": noteIDs }; - // Move out into notifications manager or Note? -// 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 (success) { + success(response[@"notes"]); } -// if(![context save:&error]){ -// NSLog(@"Unable to update note: %@", error); -// } - if (success != nil) success(operation, response); - } failure:failure ]; + } failure:failure]; } - (void)markNoteAsRead:(NSString *)noteID success:(WordPressComApiRestSuccessResponseBlock)success failure:(WordPressComApiRestSuccessFailureBlock)failure { From d870a6e183058d630b013741bfa7ce55e6e20d3a Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 16:22:58 -0500 Subject: [PATCH 17/23] Update Note with renames and API category MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Split out the API usage into a category for organization - Rename confusing ‘sync’ method to `mergeNewNotes:` like other models --- WordPress/Classes/Note.h | 10 ++-- WordPress/Classes/Note.m | 54 ++++++++++--------- ...NotificationsCommentDetailViewController.m | 2 + .../Classes/NotificationsViewController.m | 4 +- 4 files changed, 40 insertions(+), 30 deletions(-) diff --git a/WordPress/Classes/Note.h b/WordPress/Classes/Note.h index 6cf6b0b5ad64..b86cf0bef594 100644 --- a/WordPress/Classes/Note.h +++ b/WordPress/Classes/Note.h @@ -31,10 +31,8 @@ - (void)syncAttributes:(NSDictionary *)data; - (void)updateAttributes:(NSDictionary *)data; -- (NSDictionary *)getNoteData; -+ (void)syncNotesWithResponse:(NSArray *)notesData; -+ (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context; ++ (void)mergeNewNotes:(NSArray *)notesData; /** Remove old notes from Core Data storage @@ -44,6 +42,12 @@ @param context The context which contains the notes to delete. */ + (void)pruneOldNotesBefore:(NSNumber *)timestamp withContext:(NSManagedObjectContext *)context; + +@end + +@interface Note (WordPressComApi) + + (void)fetchNewNotificationsWithSuccess:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure; ++ (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context; @end diff --git a/WordPress/Classes/Note.m b/WordPress/Classes/Note.m index 8ebe455f9183..519ee786cdcb 100644 --- a/WordPress/Classes/Note.m +++ b/WordPress/Classes/Note.m @@ -50,7 +50,7 @@ @implementation Note @synthesize commentText = _commentText, noteData = _noteData; -+ (void)syncNotesWithResponse:(NSArray *)notesData { ++ (void)mergeNewNotes:(NSArray *)notesData { NSManagedObjectContext *context = [[ContextManager sharedInstance] backgroundContext]; [context performBlock:^{ NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Note"]; @@ -81,15 +81,6 @@ + (void)syncNotesWithResponse:(NSArray *)notesData { }]; } -+ (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context { - NSFetchRequest *request = [[ContextManager sharedInstance].managedObjectModel fetchRequestTemplateForName:@"UnreadNotes"]; - NSError *error = nil; - NSArray *notes = [context executeFetchRequest:request error:&error]; - if ([notes count] > 0) { - [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:notes fields:@"id,unread" success:nil failure:nil]; - } -} - + (void)pruneOldNotesBefore:(NSNumber *)timestamp withContext:(NSManagedObjectContext *)context { NSError *error; @@ -128,21 +119,6 @@ + (void)pruneOldNotesBefore:(NSNumber *)timestamp withContext:(NSManagedObjectCo [context save:&error]; } -+ (void)fetchNewNotificationsWithSuccess:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure { - NSNumber *timestamp = [self lastNoteTimestampWithContext:[ContextManager sharedInstance].backgroundContext]; - - [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationsSince:timestamp success:^(NSArray *notes) { - [Note syncNotesWithResponse:notes]; - if (success) { - success([notes count] > 0); - } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) { - failure(error); - } - }]; -} - + (NSNumber *)lastNoteTimestampWithContext:(NSManagedObjectContext *)context { NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Note"]; request.resultType = NSDictionaryResultType; @@ -265,3 +241,31 @@ - (void)parseComment { } @end + +@implementation Note (WordPressComApi) + ++ (void)fetchNewNotificationsWithSuccess:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure { + NSNumber *timestamp = [self lastNoteTimestampWithContext:[ContextManager sharedInstance].backgroundContext]; + + [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationsSince:timestamp success:^(NSArray *notes) { + [Note mergeNewNotes:notes]; + if (success) { + success([notes count] > 0); + } + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (failure) { + failure(error); + } + }]; +} + ++ (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context { + NSFetchRequest *request = [[ContextManager sharedInstance].managedObjectModel fetchRequestTemplateForName:@"UnreadNotes"]; + NSError *error = nil; + NSArray *notes = [context executeFetchRequest:request error:&error]; + if ([notes count] > 0) { + [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:notes fields:@"id,unread" success:nil failure:nil]; + } +} + +@end \ No newline at end of file diff --git a/WordPress/Classes/NotificationsCommentDetailViewController.m b/WordPress/Classes/NotificationsCommentDetailViewController.m index 9d2aa87ba38b..31a9ddefd670 100644 --- a/WordPress/Classes/NotificationsCommentDetailViewController.m +++ b/WordPress/Classes/NotificationsCommentDetailViewController.m @@ -23,6 +23,8 @@ #import "IOS7CorrectedTextView.h" #import "WPAccount.h" +#import "ContextManager.h" + #define APPROVE_BUTTON_TAG 1 #define UNAPPROVE_BUTTON_TAG 2 #define TRASH_BUTTON_TAG 3 diff --git a/WordPress/Classes/NotificationsViewController.m b/WordPress/Classes/NotificationsViewController.m index f4d8d518d359..409a93e0cc64 100644 --- a/WordPress/Classes/NotificationsViewController.m +++ b/WordPress/Classes/NotificationsViewController.m @@ -292,7 +292,7 @@ - (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *erro timestamp = nil; } [self.user fetchNotificationsSince:timestamp success:^(NSArray *notes) { - [Note syncNotesWithResponse:notes]; + [Note mergeNewNotes:notes]; [self updateSyncDate]; if (success) { success(); @@ -331,7 +331,7 @@ - (void)loadMoreWithSuccess:(void (^)())success failure:(void (^)(NSError *))fai [self.user fetchNotificationsBefore:lastNote.timestamp success:^(NSArray *notes) { _retrievingNotifications = NO; - [Note syncNotesWithResponse:notes]; + [Note mergeNewNotes:notes]; if (success) { success(); } From 24567ee9d4a9ae0a0ba05b5dd5fadc5962b46b6a Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 16:26:30 -0500 Subject: [PATCH 18/23] Method name change - checkNotifications -> fetchRecentNotifications; fetches the last 20 --- WordPress/WordPressApi/WordPressComApi.m | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 09041b5ad715..d5423492b1cf 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -466,8 +466,8 @@ - (void)fetchNewUnseenNotificationsWithSuccess:(void (^)(NSArray *notes))success }]; } -- (void)checkNotificationsSuccess:(void (^)(NSArray *notes))success failure:(WordPressComApiRestSuccessFailureBlock)failure { - [self fetchNotificationsBefore:nil success:success failure:failure]; +- (void)fetchRecentNotificationsWithSuccess:(void (^)(NSArray *))success failure:(WordPressComApiRestSuccessFailureBlock)failure { + [self fetchNotificationsWithParameters:nil success:success failure:failure]; } - (void)fetchNotificationsSince:(NSNumber *)timestamp From 8b98e72a372868e5d205eb4a791c070fa683e7e2 Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 17:26:11 -0500 Subject: [PATCH 19/23] Add refresh single note to Note - Remove redundant getter, use property getter instead --- WordPress/Classes/Note.h | 1 + WordPress/Classes/Note.m | 20 +++++++++++++++---- ...NotificationsCommentDetailViewController.m | 12 +++-------- .../NotificationsFollowDetailViewController.m | 14 ++++++------- .../Classes/NotificationsViewController.m | 2 +- 5 files changed, 28 insertions(+), 21 deletions(-) diff --git a/WordPress/Classes/Note.h b/WordPress/Classes/Note.h index b86cf0bef594..f6ba7f579ac7 100644 --- a/WordPress/Classes/Note.h +++ b/WordPress/Classes/Note.h @@ -49,5 +49,6 @@ + (void)fetchNewNotificationsWithSuccess:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure; + (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context; +- (void)refreshNoteDataWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; @end diff --git a/WordPress/Classes/Note.m b/WordPress/Classes/Note.m index 519ee786cdcb..85b2a4ed8307 100644 --- a/WordPress/Classes/Note.m +++ b/WordPress/Classes/Note.m @@ -134,10 +134,6 @@ + (NSNumber *)lastNoteTimestampWithContext:(NSManagedObjectContext *)context { return timestamp; } -- (NSDictionary *)getNoteData { - return self.noteData; -} - - (void)syncAttributes:(NSDictionary *)noteData { self.payload = [NSJSONSerialization dataWithJSONObject:noteData options:0 error:nil]; self.noteData = [NSJSONSerialization JSONObjectWithData:self.payload options:0 error:nil]; @@ -268,4 +264,20 @@ + (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context { } } +- (void)refreshNoteDataWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { + [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:@[self.noteID] fields:nil success:^(NSArray *updatedNotes){ + if ([updatedNotes count] > 0 && ![self isDeleted] && self.managedObjectContext) { + [self updateAttributes:updatedNotes[0]]; + } + [[ContextManager sharedInstance] saveContext:self.managedObjectContext]; + if (success) { + success(); + } + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (failure) { + failure(error); + } + }]; +} + @end \ No newline at end of file diff --git a/WordPress/Classes/NotificationsCommentDetailViewController.m b/WordPress/Classes/NotificationsCommentDetailViewController.m index 31a9ddefd670..ee071f1b6ccf 100644 --- a/WordPress/Classes/NotificationsCommentDetailViewController.m +++ b/WordPress/Classes/NotificationsCommentDetailViewController.m @@ -23,8 +23,6 @@ #import "IOS7CorrectedTextView.h" #import "WPAccount.h" -#import "ContextManager.h" - #define APPROVE_BUTTON_TAG 1 #define UNAPPROVE_BUTTON_TAG 2 #define TRASH_BUTTON_TAG 3 @@ -373,18 +371,14 @@ - (IBAction)moderateComment:(id)sender { [spinner startAnimating]; NSString *path = [NSString stringWithFormat:@"/rest/v1%@", [commentAction valueForKeyPath:@"params.rest_path"]]; + [self.user postPath:path parameters:[commentAction valueForKeyPath:@"params.rest_body"] success:^(AFHTTPRequestOperation *operation, id responseObject) { NSDictionary *response = (NSDictionary *)responseObject; if (response) { - [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:@[_note.noteID] fields:nil success:^(NSArray *notes) { - if ([notes count] == 1 && ![_note isDeleted] && _note.managedObjectContext) { - [_note updateAttributes:notes[0]]; - } - - [[ContextManager sharedInstance] saveContext:_note.managedObjectContext]; + [_note refreshNoteDataWithSuccess:^{ [spinner stopAnimating]; [self displayNote]; - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + } failure:^(NSError *error) { [spinner stopAnimating]; [self displayNote]; }]; diff --git a/WordPress/Classes/NotificationsFollowDetailViewController.m b/WordPress/Classes/NotificationsFollowDetailViewController.m index a6ddcd077745..089e19e65446 100644 --- a/WordPress/Classes/NotificationsFollowDetailViewController.m +++ b/WordPress/Classes/NotificationsFollowDetailViewController.m @@ -51,7 +51,7 @@ - (void)viewDidLoad [super viewDidLoad]; if (_note) { - _noteData = [[[_note getNoteData] objectForKey:@"body"] objectForKey:@"items"]; + _noteData = [[[_note noteData] objectForKey:@"body"] objectForKey:@"items"]; } [_postTitleView.layer setMasksToBounds:NO]; @@ -60,7 +60,7 @@ - (void)viewDidLoad [_postTitleView.layer setShadowRadius:2.0f]; [_postTitleView.layer setShadowOpacity:0.3f]; - NSString *headerText = [[[_note getNoteData] objectForKey:@"body"] objectForKey:@"header_text"]; + NSString *headerText = [[[_note noteData] objectForKey:@"body"] objectForKey:@"header_text"]; if (headerText) { UILabel *headerLabel = [[UILabel alloc] initWithFrame:CGRectMake(0.0f, 0.0f, self.view.frame.size.width, 40.0f)]; [headerLabel setBackgroundColor:[WPStyleGuide itsEverywhereGrey]]; @@ -71,7 +71,7 @@ - (void)viewDidLoad [self.tableView setTableHeaderView:headerLabel]; [self.view bringSubviewToFront:_postTitleView]; - NSString *headerLink = [[[_note getNoteData] objectForKey:@"body"] objectForKey:@"header_link"]; + NSString *headerLink = [[[_note noteData] objectForKey:@"body"] objectForKey:@"header_link"]; if (headerLink && [headerLink isKindOfClass:[NSString class]]) { NSURL *postURL = [NSURL URLWithString:headerLink]; if (postURL) { @@ -91,7 +91,7 @@ - (void)viewDidLoad } - NSString *footerText = [[[_note getNoteData] objectForKey:@"body"] objectForKey:@"footer_text"]; + NSString *footerText = [[[_note noteData] objectForKey:@"body"] objectForKey:@"footer_text"]; if (footerText && ![footerText isEqualToString:@""]) { _hasFooter = YES; } @@ -214,7 +214,7 @@ - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(N cell.textLabel.textColor = [WPStyleGuide newKidOnTheBlockBlue]; cell.textLabel.font = [WPStyleGuide regularTextFont]; } - NSString *footerText = [[[_note getNoteData] objectForKey:@"body"] objectForKey:@"footer_text"]; + NSString *footerText = [[[_note noteData] objectForKey:@"body"] objectForKey:@"footer_text"]; cell.textLabel.text = footerText; return cell; } @@ -274,7 +274,7 @@ - (void)followBlog:(id)sender { } - (IBAction)viewPostTitle:(id)sender { - [self loadWebViewWithURL:[[[_note getNoteData] objectForKey:@"body"] objectForKey:@"header_link"]]; + [self loadWebViewWithURL:[[[_note noteData] objectForKey:@"body"] objectForKey:@"header_link"]]; } - (void)loadWebViewWithURL: (NSString*)url { @@ -328,7 +328,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath [self.tableView deselectRowAtIndexPath:indexPath animated:NO]; } } else { - [self loadWebViewWithURL:[[[_note getNoteData] objectForKey:@"body"] objectForKey:@"footer_link"]]; + [self loadWebViewWithURL:[[[_note noteData] objectForKey:@"body"] objectForKey:@"footer_link"]]; } } diff --git a/WordPress/Classes/NotificationsViewController.m b/WordPress/Classes/NotificationsViewController.m index 409a93e0cc64..6d1e2e107dbf 100644 --- a/WordPress/Classes/NotificationsViewController.m +++ b/WordPress/Classes/NotificationsViewController.m @@ -237,7 +237,7 @@ - (BOOL)noteHasDetailView:(Note *)note { if ([note isComment]) return YES; - NSDictionary *noteBody = [[note getNoteData] objectForKey:@"body"]; + NSDictionary *noteBody = [[note noteData] objectForKey:@"body"]; if (noteBody) { NSString *noteTemplate = [noteBody objectForKey:@"template"]; if ([noteTemplate isEqualToString:@"single-line-list"] || [noteTemplate isEqualToString:@"multi-line-list"]) From aba24a9d393770371de63d410e9903096b68963a Mon Sep 17 00:00:00 2001 From: Rebecca Putinski Date: Tue, 10 Dec 2013 17:35:38 -0500 Subject: [PATCH 20/23] Use Note to keep API calls organized MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - While not ideal, it gives more meaning to the API calls - Most Notes related calls sync the notes after the response comes back, so keep this in Note - Remove redundant ‘user’ reference in controller that points to WordPressComApi --- WordPress/Classes/Note.h | 3 ++ WordPress/Classes/Note.m | 38 +++++++++++++++++++ .../Classes/NotificationsViewController.m | 36 ++++++------------ 3 files changed, 52 insertions(+), 25 deletions(-) diff --git a/WordPress/Classes/Note.h b/WordPress/Classes/Note.h index f6ba7f579ac7..6693e1e13907 100644 --- a/WordPress/Classes/Note.h +++ b/WordPress/Classes/Note.h @@ -49,6 +49,9 @@ + (void)fetchNewNotificationsWithSuccess:(void (^)(BOOL hasNewNotes))success failure:(void (^)(NSError *error))failure; + (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context; ++ (void)fetchNotificationsSince:(NSNumber *)timestamp success:(void (^)())success failure:(void (^)(NSError *error))failure; ++ (void)fetchNotificationsBefore:(NSNumber *)timestamp success:(void (^)())success failure:(void (^)(NSError *error))failure; - (void)refreshNoteDataWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; +- (void)markAsReadWithSuccess:(void (^)())success failure:(void (^)(NSError *error))failure; @end diff --git a/WordPress/Classes/Note.m b/WordPress/Classes/Note.m index 85b2a4ed8307..5ab3190d58d9 100644 --- a/WordPress/Classes/Note.m +++ b/WordPress/Classes/Note.m @@ -264,6 +264,32 @@ + (void)refreshUnreadNotesWithContext:(NSManagedObjectContext *)context { } } ++ (void)fetchNotificationsBefore:(NSNumber *)timestamp success:(void (^)())success failure:(void (^)(NSError *))failure { + [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationsBefore:timestamp success:^(NSArray *notes) { + [self mergeNewNotes:notes]; + if (success) { + success(); + } + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (failure) { + failure(error); + } + }]; +} + ++ (void)fetchNotificationsSince:(NSNumber *)timestamp success:(void (^)())success failure:(void (^)(NSError *))failure { + [[[WPAccount defaultWordPressComAccount] restApi] fetchNotificationsSince:timestamp success:^(NSArray *notes) { + [self mergeNewNotes:notes]; + if (success) { + success(); + } + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (failure) { + failure(error); + } + }]; +} + - (void)refreshNoteDataWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:@[self.noteID] fields:nil success:^(NSArray *updatedNotes){ if ([updatedNotes count] > 0 && ![self isDeleted] && self.managedObjectContext) { @@ -280,4 +306,16 @@ - (void)refreshNoteDataWithSuccess:(void (^)())success failure:(void (^)(NSError }]; } +- (void)markAsReadWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { + [[[WPAccount defaultWordPressComAccount] restApi] markNoteAsRead:self.noteID success:^(AFHTTPRequestOperation *operation, id responseObject) { + if (success) { + success(); + } + } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + if (failure) { + failure(error); + } + }]; +} + @end \ No newline at end of file diff --git a/WordPress/Classes/NotificationsViewController.m b/WordPress/Classes/NotificationsViewController.m index 6d1e2e107dbf..455222f41239 100644 --- a/WordPress/Classes/NotificationsViewController.m +++ b/WordPress/Classes/NotificationsViewController.m @@ -27,7 +27,6 @@ @interface NotificationsViewController () { } @property (nonatomic, strong) id authListener; -@property (nonatomic, strong) WordPressComApi *user; @property (nonatomic, assign) BOOL isPushingViewController; @end @@ -39,7 +38,6 @@ - (id)init { self = [super init]; if (self) { self.title = NSLocalizedString(@"Notifications", @"Notifications View Controller title"); - self.user = [[WPAccount defaultWordPressComAccount] restApi]; } return self; } @@ -85,12 +83,8 @@ - (void)didTapNoResultsView:(WPNoResultsView *)noResultsView [self.navigationController pushViewController:webViewController animated:YES]; } -- (BOOL)showJetpackConnectMessage -{ - // self.user == nil. No user implies that the user is using the - // app with a self-hosted blog not connected to jetpack - return self.user == nil; - +- (BOOL)showJetpackConnectMessage { + return [WPAccount defaultWordPressComAccount] != nil; } - (void)dealloc { @@ -149,7 +143,7 @@ - (void)updateSyncDate { NSArray *notes = self.resultsController.fetchedObjects; if ([notes count] > 0) { Note *note = [notes objectAtIndex:0]; - [self.user updateNoteLastSeenTime:note.timestamp success:nil failure:nil]; + [[[WPAccount defaultWordPressComAccount] restApi] updateNoteLastSeenTime:note.timestamp success:nil failure:nil]; } NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; @@ -207,7 +201,7 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath if ([note isComment]) { NotificationsCommentDetailViewController *detailViewController = [[NotificationsCommentDetailViewController alloc] initWithNibName:@"NotificationsCommentDetailViewController" bundle:nil]; detailViewController.note = note; - detailViewController.user = self.user; + detailViewController.user = [[WPAccount defaultWordPressComAccount] restApi]; [self.navigationController pushViewController:detailViewController animated:YES]; } else { NotificationsFollowDetailViewController *detailViewController = [[NotificationsFollowDetailViewController alloc] initWithNibName:@"NotificationsFollowDetailViewController" bundle:nil]; @@ -225,15 +219,13 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath [self.tableView selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]; } - [self.user markNoteAsRead:note.noteID success:^(AFHTTPRequestOperation *operation, id responseObject) { - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + [note markAsReadWithSuccess:nil failure:^(NSError *error){ note.unread = [NSNumber numberWithInt:1]; }]; } } - (BOOL)noteHasDetailView:(Note *)note { - if ([note isComment]) return YES; @@ -274,7 +266,7 @@ - (void)configureCell:(NewNotificationsTableViewCell *)cell atIndexPath:(NSIndex } - (BOOL)userCanRefresh { - return self.user != nil; + return [WPAccount defaultWordPressComAccount] != nil; } - (void)syncItemsViaUserInteractionWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { @@ -291,17 +283,13 @@ - (void)syncItemsWithSuccess:(void (^)())success failure:(void (^)(NSError *erro } else { timestamp = nil; } - [self.user fetchNotificationsSince:timestamp success:^(NSArray *notes) { - [Note mergeNewNotes:notes]; + + [Note fetchNotificationsSince:timestamp success:^{ [self updateSyncDate]; if (success) { success(); } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { - if (failure) { - failure(error); - } - }]; + } failure:failure]; } - (BOOL)hasMoreContent { @@ -329,15 +317,13 @@ - (void)loadMoreWithSuccess:(void (^)())success failure:(void (^)(NSError *))fai _retrievingNotifications = YES; - [self.user fetchNotificationsBefore:lastNote.timestamp success:^(NSArray *notes) { + [Note fetchNotificationsBefore:lastNote.timestamp success:^{ _retrievingNotifications = NO; - [Note mergeNewNotes:notes]; if (success) { success(); } - } failure:^(AFHTTPRequestOperation *operation, NSError *error) { + } failure:^(NSError *error) { _retrievingNotifications = NO; - if (failure) { failure(error); } From 6a671d98d1b01dea1c1a5b850b62965bfec02795 Mon Sep 17 00:00:00 2001 From: Rebecca Date: Thu, 12 Dec 2013 18:31:48 -0500 Subject: [PATCH 21/23] Unregister for push before account is deleted Move the default account URL as recipients of the notification fired attempt to use the default account while deletion is happening, even if it's through the same context. Fixes a visual issue where the sign out did not cause the visual status of settings to be correct. --- WordPress/Classes/WPAccount.m | 52 +++++++++++++++++------------------ 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/WordPress/Classes/WPAccount.m b/WordPress/Classes/WPAccount.m index 751a0f6b5347..569f173cc6df 100644 --- a/WordPress/Classes/WPAccount.m +++ b/WordPress/Classes/WPAccount.m @@ -97,42 +97,42 @@ + (void)removeDefaultWordPressComAccount { } + (void)removeDefaultWordPressComAccountWithContext:(NSManagedObjectContext *)context { - WPAccount *defaultAccount = __defaultDotcomAccount; - if (!defaultAccount) { + if (!__defaultDotcomAccount) { return; } + + [NotificationsManager unregisterDeviceToken]; + + [[NSUserDefaults standardUserDefaults] removeObjectForKey:DefaultDotcomAccountDefaultsKey]; + NSManagedObjectID *accountObjectID = __defaultDotcomAccount.objectID; + __defaultDotcomAccount = nil; + [context performBlock:^{ - WPAccount *account = (WPAccount *)[context objectWithID:defaultAccount.objectID]; + WPAccount *account = (WPAccount *)[context objectWithID:accountObjectID]; [context deleteObject:account]; [[ContextManager sharedInstance] saveContext:context]; }]; - __defaultDotcomAccount = nil; } - (void)prepareForDeletion { - // Invoked automatically by the Core Data framework when the receiver is about to be deleted. - if (__defaultDotcomAccount == self) { - [[self restApi] cancelAllHTTPOperationsWithMethod:nil path:nil]; - [[self restApi] reset]; - - // Clear keychain entries - NSError *error; - [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:@"WordPress.com" error:&error]; - [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:WordPressComOAuthKeychainServiceName error:&error]; - self.password = nil; - self.authToken = nil; - - [WordPressAppDelegate sharedWordPressApplicationDelegate].isWPcomAuthenticated = NO; - - [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_username_preference"]; - [[NSUserDefaults standardUserDefaults] removeObjectForKey:DefaultDotcomAccountDefaultsKey]; - [[NSUserDefaults standardUserDefaults] synchronize]; - + [[self restApi] cancelAllHTTPOperationsWithMethod:nil path:nil]; + [[self restApi] reset]; + + // Clear keychain entries + NSError *error; + [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:@"WordPress.com" error:&error]; + [SFHFKeychainUtils deleteItemForUsername:self.username andServiceName:WordPressComOAuthKeychainServiceName error:&error]; + self.password = nil; + self.authToken = nil; + + [WordPressAppDelegate sharedWordPressApplicationDelegate].isWPcomAuthenticated = NO; + + [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"wpcom_username_preference"]; + [[NSUserDefaults standardUserDefaults] synchronize]; + + dispatch_async(dispatch_get_main_queue(), ^{ [[NSNotificationCenter defaultCenter] postNotificationName:WPAccountDefaultWordPressComAccountChangedNotification object:nil]; - [NotificationsManager unregisterDeviceToken]; - - __defaultDotcomAccount = nil; - } + }); } From 56b5e40b930004a5091c43d0af53ee2149ca45d9 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Fri, 3 Jan 2014 12:49:23 +0100 Subject: [PATCH 22/23] Don't listen for account changes on blogs list Results controller should take care of noticing when account changes --- WordPress/Classes/BlogListViewController.m | 4 ---- 1 file changed, 4 deletions(-) diff --git a/WordPress/Classes/BlogListViewController.m b/WordPress/Classes/BlogListViewController.m index ddb268bcd547..4f0de20162e8 100644 --- a/WordPress/Classes/BlogListViewController.m +++ b/WordPress/Classes/BlogListViewController.m @@ -82,10 +82,6 @@ - (void)viewDidLoad { target:self action:@selector(showSettings:)]; self.navigationItem.rightBarButtonItem = self.settingsButton; - - [[NSNotificationCenter defaultCenter] addObserverForName:WPAccountDefaultWordPressComAccountChangedNotification 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) { From 24563867a2dcc9c5412ef74cf46cac90e8bf3748 Mon Sep 17 00:00:00 2001 From: Jorge Bernal Date: Mon, 6 Jan 2014 19:23:15 +0100 Subject: [PATCH 23/23] Fix build errors after merging develop --- WordPress/Classes/Blog+Jetpack.m | 3 ++- WordPress/Classes/BlogToAccount.m | 1 + WordPress/Classes/BlogToJetpackAccount.m | 1 + WordPress/Classes/Note.h | 2 -- WordPress/Classes/Note.m | 2 +- WordPress/Classes/NotificationsViewController.m | 2 -- WordPress/Classes/ReaderCommentPublisher.m | 3 ++- WordPress/Classes/WPAccount.h | 1 - WordPress/WordPressApi/WordPressComApi.m | 7 ++----- 9 files changed, 9 insertions(+), 13 deletions(-) diff --git a/WordPress/Classes/Blog+Jetpack.m b/WordPress/Classes/Blog+Jetpack.m index 636008932c1b..899f413ff879 100644 --- a/WordPress/Classes/Blog+Jetpack.m +++ b/WordPress/Classes/Blog+Jetpack.m @@ -10,6 +10,7 @@ #import "Blog+Jetpack.h" #import "WPAccount.h" +#import "Note.h" #import "WordPressAppDelegate.h" #import "ContextManager.h" #import "WordPressComOAuthClient.h" @@ -147,7 +148,7 @@ - (void)saveJetpackUsername:(NSString *)username andPassword:(NSString *)passwor // Sadly we don't care if this succeeds or not [account syncBlogsWithSuccess:nil failure:nil]; - [account.restApi getNotificationsSince:nil success:nil failure:nil]; + [Note fetchNewNotificationsWithSuccess:nil failure:nil]; } } failure:^(NSError *error) { DDLogError(@"Error while obtaining OAuth2 token after enabling JetPack: %@", error); diff --git a/WordPress/Classes/BlogToAccount.m b/WordPress/Classes/BlogToAccount.m index 4717f42ea2fd..aec8e08bc010 100644 --- a/WordPress/Classes/BlogToAccount.m +++ b/WordPress/Classes/BlogToAccount.m @@ -12,6 +12,7 @@ #import "WPAccount.h" static NSString * const DefaultDotcomAccountDefaultsKey = @"AccountDefaultDotcom"; +static NSString * const WPComXMLRPCUrl = @"https://wordpress.com/xmlrpc.php"; @implementation BlogToAccount { NSString *_defaultWpcomUsername; diff --git a/WordPress/Classes/BlogToJetpackAccount.m b/WordPress/Classes/BlogToJetpackAccount.m index 695b6a9fdb03..515bd26fd8bf 100644 --- a/WordPress/Classes/BlogToJetpackAccount.m +++ b/WordPress/Classes/BlogToJetpackAccount.m @@ -11,6 +11,7 @@ #import "WPAccount.h" static NSString * const BlogJetpackKeychainPrefix = @"jetpackblog-"; +static NSString * const WPComXMLRPCUrl = @"https://wordpress.com/xmlrpc.php"; @implementation BlogToJetpackAccount diff --git a/WordPress/Classes/Note.h b/WordPress/Classes/Note.h index e7cb24bf70c9..9e0f3b5f3cbf 100644 --- a/WordPress/Classes/Note.h +++ b/WordPress/Classes/Note.h @@ -30,8 +30,6 @@ - (BOOL)isUnread; - (void)syncAttributes:(NSDictionary *)data; -- (void)updateAttributes:(NSDictionary *)data; -- (NSDictionary *)getNoteData; + (void)mergeNewNotes:(NSArray *)notesData; diff --git a/WordPress/Classes/Note.m b/WordPress/Classes/Note.m index 86dc34cf1942..5a3a86c399bb 100644 --- a/WordPress/Classes/Note.m +++ b/WordPress/Classes/Note.m @@ -279,7 +279,7 @@ + (void)fetchNotificationsSince:(NSNumber *)timestamp success:(void (^)())succes - (void)refreshNoteDataWithSuccess:(void (^)())success failure:(void (^)(NSError *))failure { [[[WPAccount defaultWordPressComAccount] restApi] refreshNotifications:@[self.noteID] fields:nil success:^(NSArray *updatedNotes){ if ([updatedNotes count] > 0 && ![self isDeleted] && self.managedObjectContext) { - [self updateAttributes:updatedNotes[0]]; + [self syncAttributes:updatedNotes[0]]; } [[ContextManager sharedInstance] saveContext:self.managedObjectContext]; if (success) { diff --git a/WordPress/Classes/NotificationsViewController.m b/WordPress/Classes/NotificationsViewController.m index fe61ae900618..ce8c0975907a 100644 --- a/WordPress/Classes/NotificationsViewController.m +++ b/WordPress/Classes/NotificationsViewController.m @@ -201,8 +201,6 @@ - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath _isPushingViewController = YES; if ([note isComment]) { NotificationsCommentDetailViewController *detailViewController = [[NotificationsCommentDetailViewController alloc] initWithNote:note]; - detailViewController.note = note; - detailViewController.user = [[WPAccount defaultWordPressComAccount] restApi]; [self.navigationController pushViewController:detailViewController animated:YES]; } else { NotificationsFollowDetailViewController *detailViewController = [[NotificationsFollowDetailViewController alloc] initWithNote:note]; diff --git a/WordPress/Classes/ReaderCommentPublisher.m b/WordPress/Classes/ReaderCommentPublisher.m index 25c885009946..42776a545495 100644 --- a/WordPress/Classes/ReaderCommentPublisher.m +++ b/WordPress/Classes/ReaderCommentPublisher.m @@ -9,6 +9,7 @@ #import "ReaderPost.h" #import "ReaderComment.h" #import "WPToast.h" +#import "WPAccount.h" @interface ReaderCommentPublisher () @@ -119,7 +120,7 @@ - (void)publishComment:(NSString *)commentText { self.composeView.enabled = NO; NSDictionary *params = @{@"content":str}; - [[WordPressComApi sharedApi] postPath:[self pathForContext] parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { + [[[WPAccount defaultWordPressComAccount] restApi] postPath:[self pathForContext] parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { [self.composeView clearText]; self.composeView.enabled = YES; diff --git a/WordPress/Classes/WPAccount.h b/WordPress/Classes/WPAccount.h index b6a6d6c87fd1..e26d8b76f4ce 100644 --- a/WordPress/Classes/WPAccount.h +++ b/WordPress/Classes/WPAccount.h @@ -16,7 +16,6 @@ @class Blog; extern NSString *const WPAccountDefaultWordPressComAccountChangedNotification; -extern NSString *const WPComXMLRPCUrl; @interface WPAccount : NSManagedObject diff --git a/WordPress/WordPressApi/WordPressComApi.m b/WordPress/WordPressApi/WordPressComApi.m index 093f7f556118..4e635577f9fe 100644 --- a/WordPress/WordPressApi/WordPressComApi.m +++ b/WordPress/WordPressApi/WordPressComApi.m @@ -18,7 +18,6 @@ static NSString *const WordPressComApiClientEndpointURL = @"https://public-api.wordpress.com/rest/v1/"; static NSString *const WordPressComApiOauthBaseUrl = @"https://public-api.wordpress.com/oauth2"; -NSString *const WordPressComXMLRPCUrl = @"http://wordpress.com/xmlrpc.php"; NSString *const WordPressComApiNotificationFields = @"id,type,unread,body,subject,timestamp"; static NSString *const WordPressComApiLoginUrl = @"https://wordpress.com/wp-login.php"; static NSString *const WordPressComXMLRPCUrl = @"https://wordpress.com/xmlrpc.php"; @@ -378,12 +377,10 @@ - (void)syncPushNotificationInfoWithDeviceToken:(NSString *)token if (![self hasCredentials]) return; - - NSString *authURL = WordPressComXMLRPCUrl; - + // 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:WPComXMLRPCUrl]]; + WPXMLRPCClient *api = [[WPXMLRPCClient alloc] initWithXMLRPCEndpoint:[NSURL URLWithString:WordPressComXMLRPCUrl]]; [api setAuthorizationHeaderWithToken:self.authToken];