-
Notifications
You must be signed in to change notification settings - Fork 1.2k
My Profile #4510
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
My Profile #4510
Changes from all commits
4ab6fbb
f9f966e
4b02332
5c8490c
cd9d064
6619f94
1e91f98
86ae455
8b2bca6
d2c1a16
c4902ca
fd90d4a
6aa5838
63e084e
732f7b7
e25a739
0ab7917
5dff34b
7436147
275a4b0
064604c
dc54d70
f9289a3
a6c2d38
a0fbef0
11c275a
6b6e679
24644d0
56d22ec
eb3d35d
f83498b
448e102
1565343
140bcb5
1ce6954
3145ee3
cc39339
e8da51b
381fd33
5cdda3f
0e50b11
b153a99
43190d1
b77fe2b
42c39e7
68aa087
0a08dff
eb3af9f
2e02293
fbd65ff
74cb4c0
09e3005
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| import Foundation | ||
| import CoreData | ||
|
|
||
| extension ManagedAccountSettings { | ||
| @NSManaged var firstName: String | ||
| @NSManaged var lastName: String | ||
| @NSManaged var displayName: String | ||
| @NSManaged var aboutMe: String | ||
|
|
||
| @NSManaged var username: String | ||
| @NSManaged var email: String | ||
| @NSManaged var primarySiteID: Int | ||
| @NSManaged var webAddress: String | ||
| @NSManaged var language: String | ||
|
|
||
| @NSManaged var account: WPAccount | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,105 @@ | ||
| import Foundation | ||
| import CoreData | ||
|
|
||
| class ManagedAccountSettings: NSManagedObject { | ||
| static let entityName = "AccountSettings" | ||
|
|
||
| func updateWith(accountSettings: AccountSettings) { | ||
| firstName = accountSettings.firstName | ||
| lastName = accountSettings.lastName | ||
| displayName = accountSettings.displayName | ||
| aboutMe = accountSettings.aboutMe | ||
|
|
||
| username = accountSettings.username | ||
| email = accountSettings.email | ||
| primarySiteID = accountSettings.primarySiteID | ||
| webAddress = accountSettings.webAddress | ||
| language = accountSettings.language | ||
| } | ||
|
|
||
| /** | ||
| Applies a change to the account settings | ||
|
|
||
| To change a setting, you create a change and apply it to the AccountSettings object. | ||
| This method will return a new change object to apply if you want to revert the changes (for instance, if they failed to save) | ||
|
|
||
| - returns: the change object needed to revert this change | ||
| */ | ||
| func applyChange(change: AccountSettingsChange) -> AccountSettingsChange { | ||
| let reverse = reverseChange(change) | ||
|
|
||
| switch change { | ||
| case .FirstName(let value): | ||
| self.firstName = value | ||
| case .LastName(let value): | ||
| self.lastName = value | ||
| case .DisplayName(let value): | ||
| self.displayName = value | ||
| case .AboutMe(let value): | ||
| self.aboutMe = value | ||
| case .Email(let value): | ||
| self.email = value | ||
| case .PrimarySite(let value): | ||
| self.primarySiteID = value | ||
| case .WebAddress(let value): | ||
| self.webAddress = value | ||
| case .Language(let value): | ||
| self.language = value | ||
| } | ||
|
|
||
| return reverse | ||
| } | ||
|
|
||
| private func reverseChange(change: AccountSettingsChange) -> AccountSettingsChange { | ||
| switch change { | ||
| case .FirstName(_): | ||
| return .FirstName(self.firstName) | ||
| case .LastName(_): | ||
| return .LastName(self.lastName) | ||
| case .DisplayName(_): | ||
| return .DisplayName(self.displayName) | ||
| case .AboutMe(_): | ||
| return .AboutMe(self.aboutMe) | ||
| case .Email(_): | ||
| return .Email(self.email) | ||
| case .PrimarySite(_): | ||
| return .PrimarySite(self.primarySiteID) | ||
| case .WebAddress(_): | ||
| return .WebAddress(self.webAddress) | ||
| case .Language(_): | ||
| return .Language(self.language) | ||
| } | ||
| } | ||
| } | ||
|
|
||
| enum AccountSettingsChange { | ||
| case FirstName(String) | ||
| case LastName(String) | ||
| case DisplayName(String) | ||
| case AboutMe(String) | ||
| case Email(String) | ||
| case PrimarySite(Int) | ||
| case WebAddress(String) | ||
| case Language(String) | ||
|
|
||
| var stringValue: String { | ||
| switch self { | ||
| case .FirstName(let value): | ||
| return value | ||
| case .LastName(let value): | ||
| return value | ||
| case .DisplayName(let value): | ||
| return value | ||
| case .AboutMe(let value): | ||
| return value | ||
| case .Email(let value): | ||
| return value | ||
| case .PrimarySite(let value): | ||
| return String(value) | ||
| case .WebAddress(let value): | ||
| return value | ||
| case .Language(let value): | ||
| return value | ||
| } | ||
| } | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,85 @@ | ||
| import Foundation | ||
|
|
||
| class AccountSettingsRemote: ServiceRemoteREST { | ||
| func getSettings(success success: AccountSettings -> Void, failure: ErrorType -> Void) { | ||
| let endpoint = "me/settings" | ||
| let path = pathForEndpoint(endpoint, withVersion: ServiceRemoteRESTApiVersion_1_1) | ||
|
|
||
| api.GET(path, | ||
| parameters: nil, | ||
| success: { | ||
| operation, responseObject in | ||
|
|
||
| do { | ||
| let settings = try self.settingsFromResponse(responseObject) | ||
| success(settings) | ||
| } catch { | ||
| failure(error) | ||
| } | ||
| }, | ||
| failure: { operation, error in | ||
| failure(error) | ||
| }) | ||
| } | ||
|
|
||
| func updateSetting(change: AccountSettingsChange, success: () -> Void, failure: ErrorType -> Void) { | ||
| let endpoint = "me/settings" | ||
| let path = pathForEndpoint(endpoint, withVersion: ServiceRemoteRESTApiVersion_1_1) | ||
| let parameters = [fieldNameForChange(change): change.stringValue] | ||
|
|
||
| api.POST(path, | ||
| parameters: parameters, | ||
| success: { | ||
| operation, responseObject in | ||
|
|
||
| success() | ||
| }, | ||
| failure: { operation, error in | ||
| failure(error) | ||
| }) | ||
| } | ||
|
|
||
| private func settingsFromResponse(responseObject: AnyObject) throws -> AccountSettings { | ||
| guard let | ||
| response = responseObject as? [String: AnyObject], | ||
| firstName = response["first_name"] as? String, | ||
| lastName = response["last_name"] as? String, | ||
| displayName = response["display_name"] as? String, | ||
| aboutMe = response["description"] as? String, | ||
| username = response["user_login"] as? String, | ||
| email = response["user_email"] as? String, | ||
| primarySiteID = response["primary_site_ID"] as? Int, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is primary site ID required? I can create a WordPress.com account without any sites.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice catch. I think when I wrote this there was still no documentation for I'm not doing anything with this for profile, but I wanted to get the extra properties in since Account Settings is next |
||
| webAddress = response["user_URL"] as? String, | ||
| language = response["language"] as? String else { | ||
| DDLogSwift.logError("Error decoding me/settings response: \(responseObject)") | ||
| throw Error.DecodeError | ||
| } | ||
|
|
||
| return AccountSettings(firstName: firstName, lastName: lastName, displayName: displayName, aboutMe: aboutMe, username: username, email: email, primarySiteID: primarySiteID, webAddress: webAddress, language: language) | ||
| } | ||
|
|
||
| private func fieldNameForChange(change: AccountSettingsChange) -> String { | ||
| switch change { | ||
| case .FirstName(_): | ||
| return "first_name" | ||
| case .LastName(_): | ||
| return "last_name" | ||
| case .DisplayName(_): | ||
| return "display_name" | ||
| case .AboutMe(_): | ||
| return "description" | ||
| case .Email(_): | ||
| return "email" | ||
| case .PrimarySite(_): | ||
| return "primary_site_ID" | ||
| case .WebAddress(_): | ||
| return "user_URL" | ||
| case .Language(_): | ||
| return "language" | ||
| } | ||
| } | ||
|
|
||
| enum Error: ErrorType { | ||
| case DecodeError | ||
| } | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -68,7 +68,15 @@ extern NSString *const WPAccountEmailAndDefaultBlogUpdatedNotification; | |
| @param username the account's username | ||
| @return a `WPAccount` object if there's one for the specified username. Otherwise it returns nil | ||
| */ | ||
| - (WPAccount *)findAccountWithUsername:(NSString *)username; | ||
| - (nullable WPAccount *)findAccountWithUsername:(NSString *)username; | ||
|
|
||
| /** | ||
| Returns a WordPress.com account with the specified user ID, if it exists | ||
|
|
||
| @param userID the account's user ID | ||
| @return a `WPAccount` object if there's one for the specified username. Otherwise it returns nil | ||
| */ | ||
| - (nullable WPAccount *)findAccountWithUserID:(NSNumber *)userID; | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I love the new nullability qualifiers in Objective-C! |
||
|
|
||
| /** | ||
| Updates user details including username, email, userID, avatarURL, and default blog. | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
❤️
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I still find a bit weird that the properties that define an object are in an extension, and the helper methods in the class
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think its sort of a take on Protocol-Based Programming in Swift. We should, ideally, be regenerating those Core Data accessors and not manually adding the properties to the classes. Over time those generated properties will change based upon newer best practices - this forces us to keep those accessors that would normally get overwritten separate.
I like/hate it too. 😄
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I like the separation. I just think the contents of the class/extension should be swapped. My main reason is that none of the code currently in the class would work if you take away the extension, but not the other way around