Skip to content

Commit

Permalink
Subscribers List Details: Update People List UI (#23115)
Browse files Browse the repository at this point in the history
  • Loading branch information
staskus committed May 6, 2024
2 parents fd795d8 + f301d05 commit bea9bc1
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 237 deletions.
15 changes: 0 additions & 15 deletions WordPress/Classes/Models/Role.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,18 +21,3 @@ extension Role {
return context.firstObject(ofType: Role.self, matching: predicate)
}
}

extension Role {
@objc var color: UIColor {
switch slug {
case .some("super-admin"):
return WPStyleGuide.People.superAdminColor
case .some("administrator"):
return WPStyleGuide.People.adminColor
case .some("editor"):
return WPStyleGuide.People.editorColor
default:
return WPStyleGuide.People.otherRoleColor
}
}
}
25 changes: 0 additions & 25 deletions WordPress/Classes/Services/PeopleService.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,31 +76,6 @@ struct PeopleService {
})
}

/// Loads a page of Email Followers associated to the current blog, starting at the specified offset.
///
/// - Parameters:
/// - offset: Number of records to skip.
/// - count: Number of records to retrieve. By default set to 20.
/// - success: Closure to be executed on success with the number of followers retrieved and a bool indicating if more are available.
/// - failure: Closure to be executed on failure.
///
func loadEmailFollowersPage(_ offset: Int = 0,
count: Int = 20,
success: @escaping ((_ retrieved: Int, _ shouldLoadMore: Bool) -> Void),
failure: ((Error) -> Void)? = nil) {
let page = (offset / count) + 1
remote.getEmailFollowers(siteID, page: page, max: count, success: { followers, hasMore in
self.coreDataStack.performAndSave({ context in
self.mergePeople(followers, in: context)
}, completion: {
success(followers.count, hasMore)
}, on: .main)
}, failure: { error in
DDLogError(String(describing: error))
failure?(error)
})
}

/// Loads a page of Viewers associated to the current blog, starting at the specified offset.
///
/// - Parameters:
Expand Down
160 changes: 82 additions & 78 deletions WordPress/Classes/ViewRelated/People/People.storyboard

Large diffs are not rendered by default.

16 changes: 12 additions & 4 deletions WordPress/Classes/ViewRelated/People/PeopleCell.swift
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import UIKit
import WordPressShared
import WordPressUI
import Gravatar
import DesignSystem

class PeopleCell: WPTableViewCell {
@IBOutlet private weak var avatarImageView: CircularImageView!
Expand All @@ -14,8 +15,17 @@ class PeopleCell: WPTableViewCell {
override func awakeFromNib() {
super.awakeFromNib()

WPStyleGuide.configureLabel(displayNameLabel, textStyle: .callout)
WPStyleGuide.configureLabel(usernameLabel, textStyle: .caption2)
displayNameLabel.textColor = .DS.Foreground.primary
displayNameLabel.font = .DS.font(.bodyMedium(.regular))

usernameLabel.textColor = .DS.Foreground.secondary
usernameLabel.font = .DS.font(.bodyMedium(.regular))
}

override func prepareForReuse() {
super.prepareForReuse()

avatarImageView.image = UIImage(named: "gravatar")
}

func bindViewModel(_ viewModel: PeopleCellViewModel) {
Expand All @@ -24,14 +34,12 @@ class PeopleCell: WPTableViewCell {
displayNameLabel.textColor = viewModel.usernameColor
usernameLabel.text = viewModel.usernameText
usernameLabel.isHidden = viewModel.usernameHidden
roleBadge.borderColor = viewModel.roleBorderColor
roleBadge.backgroundColor = viewModel.roleBackgroundColor
roleBadge.textColor = viewModel.roleTextColor
roleBadge.text = viewModel.roleText
roleBadge.isHidden = viewModel.roleHidden
superAdminRoleBadge.text = viewModel.superAdminText
superAdminRoleBadge.isHidden = viewModel.superAdminHidden
superAdminRoleBadge.borderColor = viewModel.superAdminBorderColor
superAdminRoleBadge.backgroundColor = viewModel.superAdminBackgroundColor
badgeStackView.isHidden = viewModel.roleHidden && viewModel.superAdminHidden
}
Expand Down
25 changes: 14 additions & 11 deletions WordPress/Classes/ViewRelated/People/PeopleCellViewModel.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import Foundation
import WordPressShared
import DesignSystem

struct PeopleCellViewModel {
let displayName: String
Expand Down Expand Up @@ -28,16 +29,22 @@ struct PeopleCellViewModel {
return .text
}

var roleBorderColor: UIColor {
return role?.color ?? WPStyleGuide.People.otherRoleColor
}

var roleBackgroundColor: UIColor {
return role?.color ?? WPStyleGuide.People.otherRoleColor
switch role?.slug {
case .some("super-admin"), .some("administrator"):
return .DS.Foreground.primary
default:
return .DS.Background.secondary
}
}

var roleTextColor: UIColor {
return WPStyleGuide.People.RoleBadge.textColor
switch role?.slug {
case .some("super-admin"), .some("administrator"):
return .DS.Background.primary
default:
return .DS.Foreground.primary
}
}

var roleText: String {
Expand All @@ -52,12 +59,8 @@ struct PeopleCellViewModel {
return NSLocalizedString("Super Admin", comment: "User role badge")
}

var superAdminBorderColor: UIColor {
return superAdminBackgroundColor
}

var superAdminBackgroundColor: UIColor {
return WPStyleGuide.People.superAdminColor
return .DS.Foreground.primary
}

var superAdminHidden: Bool {
Expand Down
11 changes: 5 additions & 6 deletions WordPress/Classes/ViewRelated/People/PeopleRoleBadgeLabel.swift
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import UIKit
import WordPressShared.WPStyleGuide
import DesignSystem

class PeopleRoleBadgeLabel: BadgeLabel {
override init(frame: CGRect) {
Expand All @@ -13,11 +13,10 @@ class PeopleRoleBadgeLabel: BadgeLabel {
}

private func setupView() {
adjustsFontForContentSizeCategory = true
adjustsFontSizeToFitWidth = true
horizontalPadding = WPStyleGuide.People.RoleBadge.padding
font = WPStyleGuide.People.RoleBadge.font
layer.borderWidth = WPStyleGuide.People.RoleBadge.borderWidth
layer.cornerRadius = WPStyleGuide.People.RoleBadge.cornerRadius
horizontalPadding = CGFloat.DS.Padding.single
verticalPadding = .DS.Padding.half
font = .DS.font(.footnote)
layer.cornerRadius = .DS.Radius.small
}
}
60 changes: 38 additions & 22 deletions WordPress/Classes/ViewRelated/People/PeopleViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ class PeopleViewController: UITableViewController {
// Followers must be sorted out by creationDate!
//
switch filter {
case .followers, .email:
case .followers:
return [NSSortDescriptor(key: "creationDate", ascending: true, selector: #selector(NSDate.compare(_:)))]
default:
return [NSSortDescriptor(key: "displayName", ascending: true, selector: #selector(NSString.localizedCaseInsensitiveCompare(_:)))]
Expand Down Expand Up @@ -150,7 +150,7 @@ class PeopleViewController: UITableViewController {
// MARK: UITableViewDelegate

override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return hasHorizontallyCompactView() ? CGFloat.leastNormalMagnitude : 0
return .DS.Padding.single
}

override func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
Expand All @@ -163,6 +163,37 @@ class PeopleViewController: UITableViewController {
loadMorePeopleIfNeeded()
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)

guard let blog = blog, let blogId = blog.dotComID?.intValue else { return }

switch filter {
case .users, .viewers:
guard let viewController = PersonViewController.controllerWithBlog(
blog,
context: viewContext,
person: personAtIndexPath(indexPath),
screenMode: filter.screenMode
) else {
return
}
navigationController?.pushViewController(viewController, animated: true)
case .followers:
let url = URL(string: "https://wordpress.com/subscribers/\(blogId)/\(personAtIndexPath(indexPath).ID)")
let configuration = WebViewControllerConfiguration(url: url)
configuration.authenticateWithDefaultAccount()
configuration.secureInteraction = true
configuration.onClose = { [weak self] in
self?.resetManagedPeople()
self?.refreshPeople()
}
let viewController = WebKitViewController(configuration: configuration)
let navWrapper = LightNavigationController(rootViewController: viewController)
navigationController?.present(navWrapper, animated: true)
}
}

// MARK: UIViewController

override func viewDidLoad() {
Expand All @@ -189,16 +220,6 @@ class PeopleViewController: UITableViewController {
tableView.reloadData()
}

@IBSegueAction func createPersonViewController(_ coder: NSCoder) -> PersonViewController? {
guard let selectedIndexPath = tableView.indexPathForSelectedRow, let blog = blog else { return nil }

return PersonViewController(coder: coder,
blog: blog,
context: viewContext,
person: personAtIndexPath(selectedIndexPath),
screenMode: filter.screenMode)
}

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if let navController = segue.destination as? UINavigationController,
let inviteViewController = navController.topViewController as? InvitePersonViewController {
Expand Down Expand Up @@ -251,11 +272,10 @@ extension PeopleViewController {

case users = "users"
case followers = "followers"
case email = "email"
case viewers = "viewers"

static var defaultFilters: [Filter] {
return [.users, .followers, .email]
return [.users, .followers]
}

var title: String {
Expand All @@ -266,8 +286,6 @@ extension PeopleViewController {
return NSLocalizedString("users.list.title.subscribers", value: "Subscribers", comment: "Site Subscribers")
case .viewers:
return NSLocalizedString("Viewers", comment: "Blog Viewers")
case .email:
return NSLocalizedString("users.list.title.emailSubscribers", value: "Email Subscribers", comment: "Site Email Subscribers")
}
}

Expand All @@ -279,8 +297,6 @@ extension PeopleViewController {
return .follower
case .viewers:
return .viewer
case .email:
return .emailFollower
}
}

Expand All @@ -292,8 +308,6 @@ extension PeopleViewController {
return .Follower
case .viewers:
return .Viewer
case .email:
return .Email
}
}
}
Expand Down Expand Up @@ -336,6 +350,8 @@ private extension PeopleViewController {
// MARK: Sync Helpers

func refreshPeople() {
self.isInitialLoad = true
self.refreshNoResultsView()
loadPeoplePage() { [weak self] (retrieved, shouldLoadMore) in
self?.isInitialLoad = false
self?.refreshNoResultsView()
Expand Down Expand Up @@ -382,8 +398,6 @@ private extension PeopleViewController {
loadUsersPage(offset, success: success)
case .viewers:
service.loadViewersPage(offset, success: success)
case .email:
service.loadEmailFollowersPage(offset, success: success)
}
}

Expand Down Expand Up @@ -531,6 +545,8 @@ private extension PeopleViewController {

WPStyleGuide.configureColors(view: view, tableView: tableView)
WPStyleGuide.configureAutomaticHeightRows(for: tableView)
tableView.separatorStyle = .none
tableView.backgroundColor = .DS.Background.primary

setupFilterBar()
setupTableView()
Expand Down
36 changes: 7 additions & 29 deletions WordPress/Classes/ViewRelated/People/PersonViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@ final class PersonViewController: UITableViewController {
case User = "user"
case Follower = "follower"
case Viewer = "viewer"
case Email = "email"

var title: String {
switch self {
Expand All @@ -33,8 +32,6 @@ final class PersonViewController: UITableViewController {
return NSLocalizedString("user.details.title.subscriber", value: "Site's Subscriber", comment: "Site's Subscriber Profile. Displayed when the name is empty!")
case .Viewer:
return NSLocalizedString("user.details.title.viewer", value: "Site's Viewer", comment: "Site's Viewers Profile. Displayed when the name is empty!")
case .Email:
return NSLocalizedString("user.details.title.emailSubscriber", value: "Site's Email Subscriber", comment: "Site's Email Subscriber Profile. Displayed when the name is empty!")
}
}
}
Expand Down Expand Up @@ -73,6 +70,13 @@ final class PersonViewController: UITableViewController {
super.init(coder: coder)
}

class func controllerWithBlog(_ blog: Blog, context: NSManagedObjectContext, person: Person, screenMode: ScreenMode) -> PersonViewController? {
let storyboard = UIStoryboard(name: "People", bundle: nil)
return storyboard.instantiateViewController(identifier: "PersonViewController") { coder in
PersonViewController(coder: coder, blog: blog, context: context, person: person, screenMode: screenMode)
}
}

required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
Expand Down Expand Up @@ -230,8 +234,6 @@ private extension PersonViewController {
case .Viewer:
strongSelf.deleteViewer()
return
case .Email:
strongSelf.deleteEmailFollower()
}
}

Expand All @@ -251,9 +253,6 @@ private extension PersonViewController {
case .Viewer:
messageFirstLine = NSLocalizedString("If you remove this viewer, he or she will not be able to visit this site.",
comment: "First line of remove viewer warning in confirmation dialog.")
case .Email:
messageFirstLine = NSLocalizedString("Removing followers makes them stop receiving updates from your site. If they choose to, they can still visit your site, and follow it again.",
comment: "First line of remove email follower warning in confirmation dialog.")
}

let messageSecondLineText = NSLocalizedString("Would you still like to remove this person?",
Expand Down Expand Up @@ -298,23 +297,6 @@ private extension PersonViewController {
_ = navigationController?.popViewController(animated: true)
}

func deleteEmailFollower() {
guard let emailFollower = emailFollower, isEmailFollower else {
DDLogError("Error: Only email followers can be deleted here")
assertionFailure()
return
}

service?.deleteEmailFollower(emailFollower, failure: { [weak self] error in
guard let strongSelf = self, let error = error as NSError? else {
return
}

strongSelf.handleRemoveViewerOrFollowerError(error)
})
_ = navigationController?.popViewController(animated: true)
}

func deleteViewer() {
guard let viewer = viewer, isViewer else {
DDLogError("Error: Only Viewers can be deleted here")
Expand Down Expand Up @@ -542,8 +524,6 @@ private extension PersonViewController {
return isFollower == true
case .Viewer:
return isViewer == true
case .Email:
return isEmailFollower
}
}

Expand Down Expand Up @@ -587,8 +567,6 @@ private extension PersonViewController {
return .viewer
case .User:
return try? Role.lookup(withBlogID: blog.objectID, slug: person.role, in: context)?.toUnmanaged()
case .Email:
return .follower
}
}
}
Expand Down
Loading

0 comments on commit bea9bc1

Please sign in to comment.