Skip to content

Commit

Permalink
Merge pull request wordpress-mobile#21073 from wordpress-mobile/task/…
Browse files Browse the repository at this point in the history
…20783-cell-view-model-impl
  • Loading branch information
dvdchr authored Jul 13, 2023
2 parents cd712e3 + 2aa0907 commit 300547d
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 21 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ struct PrepublishingAutoSharingView: View {
HStack {
textStack
Spacer()
if model.connections.count > 0 {
if model.services.count > 0 {
socialIconsView
}
}
Expand Down Expand Up @@ -41,8 +41,8 @@ struct PrepublishingAutoSharingView: View {

private var socialIconsView: some View {
HStack(spacing: -2.0) {
ForEach(model.connections, id: \.self) { connection in
iconImage(connection.serviceName.localIconImage, opaque: connection.enabled)
ForEach(model.services, id: \.self) { service in
iconImage(service.serviceName.localIconImage, opaque: service.usesOpaqueIcon)
}
}
}
Expand Down Expand Up @@ -84,22 +84,42 @@ private extension PrepublishingAutoSharingView {
/// The value-type data model that drives the `PrepublishingAutoSharingView`.
struct PrepublishingAutoSharingViewModel {

struct Connection: Hashable {
// MARK: Helper Models

/// A value-type representation of `PublicizeService` that's simplified for the needs of the auto-sharing view.
struct Service: Hashable {
let serviceName: PublicizeService.ServiceName
let connections: [Connection]

/// Whether the icon for this service should be opaque or transparent.
/// If at least one account is enabled, an opaque version should be shown.
var usesOpaqueIcon: Bool {
connections.reduce(false) { $0 || $1.enabled }
}

var enabledConnections: [Connection] {
connections.filter { $0.enabled }
}
}

struct Connection: Hashable {
let account: String
let enabled: Bool
}

// TODO: Default values are for temporary testing purposes. Will be removed later.
let connections: [Connection] = [.init(serviceName: .facebook, account: "foo", enabled: true),
.init(serviceName: .twitter, account: "bar", enabled: false),
.init(serviceName: .tumblr, account: "baz", enabled: true)]
// MARK: Properties

// TODO: Default values are for temporary testing purposes. Will be removed later.
let sharingLimit: PublicizeInfo.SharingLimit? = .init(remaining: 1, limit: 30)
let services: [Service]
let sharingLimit: PublicizeInfo.SharingLimit?

// MARK: Computed Properties

var enabledConnectionsCount: Int {
connections.filter({ $0.enabled }).count
services.reduce(0) { $0 + $1.enabledConnections.count }
}

var totalConnectionsCount: Int {
services.reduce(0) { $0 + $1.connections.count }
}

var showsWarning: Bool {
Expand All @@ -110,14 +130,14 @@ struct PrepublishingAutoSharingViewModel {
}

var labelText: String {
switch (enabledConnectionsCount, connections.count) {
switch (enabledConnectionsCount, totalConnectionsCount) {
case (let enabled, _) where enabled == 0:
// not sharing to any social media
return Strings.notSharingText

case (let enabled, let total) where enabled == total && total == 1:
// sharing to the one and only connection
guard let account = connections.first?.account else {
guard let account = services.first?.connections.first?.account else {
return String()
}
return String(format: Strings.singleConnectionTextFormat, account)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,20 @@
extension PrepublishingViewController {

/// Determines whether the account and the post's blog is eligible to see auto-sharing options.
var isEligibleForAutoSharing: Bool {
let postObjectID = post.objectID
let blogSupportsPublicize = coreDataStack.performQuery { context in
func isEligibleForAutoSharing(isJetpack: Bool = AppConfiguration.isJetpack,
isFeatureEnabled: Bool = FeatureFlag.jetpackSocial.enabled) -> Bool {
let blogSupportsPublicize = coreDataStack.performQuery { [postObjectID = post.objectID] context in
let post = (try? context.existingObject(with: postObjectID)) as? Post
return post?.blog.supportsPublicize() ?? false
}

return blogSupportsPublicize && FeatureFlag.jetpackSocial.enabled
return blogSupportsPublicize && isJetpack && isFeatureEnabled
}

func configureSocialCell(_ cell: UITableViewCell) {
// TODO:
// - Show the NoConnectionView if user has 0 connections.
// - Properly create and configure the view models.
let autoSharingView = UIView.embedSwiftUIView(PrepublishingAutoSharingView(model: .init()))
let autoSharingView = UIView.embedSwiftUIView(PrepublishingAutoSharingView(model: makeAutoSharingViewModel()))
cell.contentView.addSubview(autoSharingView)

// Pin constraints to the cell's layoutMarginsGuide so that the content is properly aligned.
Expand All @@ -25,6 +24,50 @@ extension PrepublishingViewController {
autoSharingView.bottomAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.bottomAnchor),
autoSharingView.trailingAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.trailingAnchor)
])
cell.accessoryType = .disclosureIndicator
cell.accessoryType = .disclosureIndicator // TODO: only for autoSharingView.
}
}

// MARK: - Helper Methods

private extension PrepublishingViewController {

func makeAutoSharingViewModel() -> PrepublishingAutoSharingViewModel {
return coreDataStack.performQuery { [postObjectID = post.objectID] context in
guard let post = (try? context.existingObject(with: postObjectID)) as? Post,
let connections = post.blog.sortedConnections as? [PublicizeConnection],
let supportedServices = try? PublicizeService.allSupportedServices(in: context) else {
return .init(services: [], sharingLimit: nil)
}

// first, build a dictionary to categorize the connections.
var connectionsMap = [PublicizeService.ServiceName: [PublicizeConnection]]()
connections.forEach { connection in
let serviceName = PublicizeService.ServiceName(rawValue: connection.service) ?? .unknown
var serviceConnections = connectionsMap[serviceName] ?? []
serviceConnections.append(connection)
connectionsMap[serviceName] = serviceConnections
}

// then, transform [PublicizeService] to [PrepublishingAutoSharingViewModel.Service].
let modelServices = supportedServices.compactMap { service -> PrepublishingAutoSharingViewModel.Service? in
// skip services without connections.
guard let serviceConnections = connectionsMap[service.name],
!serviceConnections.isEmpty else {
return nil
}

return PrepublishingAutoSharingViewModel.Service(
serviceName: service.name,
connections: serviceConnections.map {
.init(account: $0.externalDisplay,
enabled: !post.publicizeConnectionDisabledForKeyringID($0.keyringConnectionID))
}
)
}

return .init(services: modelServices, sharingLimit: post.blog.sharingLimit)
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ class PrepublishingViewController: UITableViewController {
switch identifier {
case .autoSharing:
// skip the social cell if the post's blog is not eligible for auto-sharing.
guard isEligibleForAutoSharing else {
guard isEligibleForAutoSharing() else {
return nil
}
break
Expand Down

0 comments on commit 300547d

Please sign in to comment.