Skip to content

Commit

Permalink
Merge pull request #20244 from wordpress-mobile/refactor-people-servi…
Browse files Browse the repository at this point in the history
…ce-update-user

Refactor updating user role to save local user asynchronously
  • Loading branch information
crazytonyli authored Mar 9, 2023
2 parents 00e5aa5 + 61e81f2 commit 795e06a
Show file tree
Hide file tree
Showing 3 changed files with 39 additions and 33 deletions.
2 changes: 1 addition & 1 deletion RELEASE-NOTES.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
22.0
-----
* [*] [internal] Refactored updating user role in the "People" screen on the "My Sites" tab. [#20244]
* [*] [internal] Refactor managing social connections and social buttons in the "Sharing" screen. [#20265]


21.9
-----
* [*] [internal] Refactored fetching posts in the Reader tab, including post related operations (i.e. like/unlike, save for later, etc.) [#20197]
Expand Down
56 changes: 32 additions & 24 deletions WordPress/Classes/Services/PeopleService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ import Foundation
import CocoaLumberjack
import WordPressKit

enum PeopleServiceError: Error {
case userNotFoundLocally(User)
}

/// Service providing access to the People Management WordPress.com API.
///
struct PeopleService {
Expand Down Expand Up @@ -128,48 +132,52 @@ struct PeopleService {
///
/// - Returns: A new Person instance, with the new Role already assigned.
///
func updateUser(_ user: User, role: String, failure: ((Error, User) -> Void)?) -> User {
var pristineRole: String?
var updated: User?
coreDataStack.performAndSave { context in
func updateUser(_ user: User, role: String, receiveUpdate: @escaping (User) -> Void, failure: ((Error, User) -> Void)?) {
coreDataStack.performAndSave({ context throws -> (String, User) in
guard let managedPerson = managedPersonFromPerson(user, in: context) else {
return
throw PeopleServiceError.userNotFoundLocally(user)
}

// OP Reversal
pristineRole = managedPerson.role
let pristineRole = managedPerson.role

// Pre-emptively update the role
managedPerson.role = role

updated = User(managedPerson: managedPerson)
}

// Early exit if failed to update the user
guard let updated else {
return user
}
return (pristineRole, User(managedPerson: managedPerson))
}, completion: { result in
switch result {
case let .failure(error):
failure?(error, user)
case let .success((pristineRole, updated)):
receiveUpdate(updated)
self.updateRemoteUser(user, role: role, roleToRevertUponFailure: pristineRole, failure: failure)
}
}, on: .main)
}

// Hit the Backend
private func updateRemoteUser(_ user: User, role: String, roleToRevertUponFailure pristineRole: String, failure: ((Error, User) -> Void)?) {
remote.updateUserRole(siteID, userID: user.ID, newRole: role, success: nil, failure: { error in

DDLogError("### Error while updating person \(user.ID) in blog \(self.siteID): \(error)")

var reloadedPerson: User!
self.coreDataStack.performAndSave { context in
self.coreDataStack.performAndSave({ context in
guard let managedPerson = self.managedPersonFromPerson(user, in: context) else {
DDLogError("### Person with ID \(user.ID) deleted before update")
return
throw PeopleServiceError.userNotFoundLocally(user)
}

managedPerson.role = pristineRole!
managedPerson.role = pristineRole

reloadedPerson = User(managedPerson: managedPerson)
}
failure?(error, reloadedPerson)
return User(managedPerson: managedPerson)
}, completion: { result in
switch result {
case let .failure(error):
failure?(error, user)
case let .success(reloadedPerson):
failure?(error, reloadedPerson)
}
}, on: .main)
})

return updated
}

/// Deletes a given User.
Expand Down
14 changes: 6 additions & 8 deletions WordPress/Classes/ViewRelated/People/PersonViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -373,15 +373,13 @@ private extension PersonViewController {
return
}

let updated = service.updateUser(user, role: newRole) { (error, reloadedPerson) in
self.person = reloadedPerson
self.retryUpdatingRole(newRole)
service.updateUser(user, role: newRole) { updated in
self.person = updated
WPAnalytics.track(.personUpdated)
} failure: { [weak self] _, reloadedPerson in
self?.person = reloadedPerson
self?.retryUpdatingRole(newRole)
}

// Optimistically refresh the UI
self.person = updated

WPAnalytics.track(.personUpdated)
}

func retryUpdatingRole(_ newRole: String) {
Expand Down

0 comments on commit 795e06a

Please sign in to comment.