From db4ddaab74b0f4de34d67211eabc6fa04196cca2 Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Wed, 12 Jul 2023 16:51:38 +0700 Subject: [PATCH 1/3] Allow NoConnectionView to use custom background color --- .../Social/JetpackSocialNoConnectionView.swift | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Jetpack/Social/JetpackSocialNoConnectionView.swift b/WordPress/Classes/ViewRelated/Jetpack/Social/JetpackSocialNoConnectionView.swift index 325342326186..be5cdeabd243 100644 --- a/WordPress/Classes/ViewRelated/Jetpack/Social/JetpackSocialNoConnectionView.swift +++ b/WordPress/Classes/ViewRelated/Jetpack/Social/JetpackSocialNoConnectionView.swift @@ -34,16 +34,16 @@ struct JetpackSocialNoConnectionView: View { } } .padding(viewModel.padding) - .background(Color(UIColor.listForeground)) + .background(Color(viewModel.preferredBackgroundColor)) } func iconImage(_ image: UIImage) -> some View { Image(uiImage: image) .resizable() .frame(width: 32.0, height: 32.0) - .background(Color(UIColor.listForeground)) + .background(Color(viewModel.preferredBackgroundColor)) .clipShape(Circle()) - .overlay(Circle().stroke(Color(UIColor.listForeground), lineWidth: 2.0)) + .overlay(Circle().stroke(Color(viewModel.preferredBackgroundColor), lineWidth: 2.0)) } } @@ -53,7 +53,7 @@ extension JetpackSocialNoConnectionView { static func createHostController(with viewModel: JetpackSocialNoConnectionViewModel = JetpackSocialNoConnectionViewModel()) -> UIHostingController { let hostController = UIHostingController(rootView: JetpackSocialNoConnectionView(viewModel: viewModel)) hostController.view.translatesAutoresizingMaskIntoConstraints = false - hostController.view.backgroundColor = .listForeground + hostController.view.backgroundColor = viewModel.preferredBackgroundColor return hostController } } @@ -63,6 +63,7 @@ extension JetpackSocialNoConnectionView { class JetpackSocialNoConnectionViewModel: ObservableObject { let padding: EdgeInsets let hideNotNow: Bool + let preferredBackgroundColor: UIColor let onConnectTap: (() -> Void)? let onNotNowTap: (() -> Void)? @MainActor @Published var icons: [UIImage] = [UIImage()] @@ -70,10 +71,12 @@ class JetpackSocialNoConnectionViewModel: ObservableObject { init(services: [PublicizeService] = [], padding: EdgeInsets = Constants.defaultPadding, hideNotNow: Bool = false, + preferredBackgroundColor: UIColor? = nil, onConnectTap: (() -> Void)? = nil, onNotNowTap: (() -> Void)? = nil) { self.padding = padding self.hideNotNow = hideNotNow + self.preferredBackgroundColor = preferredBackgroundColor ?? Constants.defaultBackgroundColor self.onConnectTap = onConnectTap self.onNotNowTap = onNotNowTap updateIcons(services) @@ -118,6 +121,7 @@ class JetpackSocialNoConnectionViewModel: ObservableObject { private struct Constants { static let defaultPadding = EdgeInsets(top: 16.0, leading: 16.0, bottom: 24.0, trailing: 16.0) + static let defaultBackgroundColor = UIColor.listForeground static let bodyText = NSLocalizedString("social.noconnection.body", value: "Increase your traffic by auto-sharing your posts with your friends on social media.", comment: "Body text for the Jetpack Social no connection view") From bd6c67181087c6ebe55e1b4bb4c387a94a636b24 Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Wed, 12 Jul 2023 17:01:18 +0700 Subject: [PATCH 2/3] Show NoConnectionView for eligible sites with 0 connections --- .../Post/PrepublishingAutoSharingView.swift | 50 ++++++------ ...blishingViewController+JetpackSocial.swift | 80 ++++++++++++++++--- 2 files changed, 92 insertions(+), 38 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/PrepublishingAutoSharingView.swift b/WordPress/Classes/ViewRelated/Post/PrepublishingAutoSharingView.swift index 93f1150a7de9..f43c959b9d4d 100644 --- a/WordPress/Classes/ViewRelated/Post/PrepublishingAutoSharingView.swift +++ b/WordPress/Classes/ViewRelated/Post/PrepublishingAutoSharingView.swift @@ -84,31 +84,6 @@ private extension PrepublishingAutoSharingView { /// The value-type data model that drives the `PrepublishingAutoSharingView`. struct PrepublishingAutoSharingViewModel { - // 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) { partialResult, connection in - return partialResult || connection.enabled - } - } - - var enabledConnections: [Connection] { - connections.filter { $0.enabled } - } - } - - struct Connection: Hashable { - let account: String - let enabled: Bool - } - // MARK: Properties let services: [Service] @@ -160,6 +135,31 @@ struct PrepublishingAutoSharingViewModel { return String() } } + + // 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) { partialResult, connection in + return partialResult || connection.enabled + } + } + + var enabledConnections: [Connection] { + connections.filter { $0.enabled } + } + } + + struct Connection: Hashable { + let account: String + let enabled: Bool + } } private extension PrepublishingAutoSharingViewModel { diff --git a/WordPress/Classes/ViewRelated/Post/PrepublishingViewController+JetpackSocial.swift b/WordPress/Classes/ViewRelated/Post/PrepublishingViewController+JetpackSocial.swift index a8c13b5fe175..df57694a9618 100644 --- a/WordPress/Classes/ViewRelated/Post/PrepublishingViewController+JetpackSocial.swift +++ b/WordPress/Classes/ViewRelated/Post/PrepublishingViewController+JetpackSocial.swift @@ -1,3 +1,5 @@ +/// Encapsulates logic related to Jetpack Social in the pre-publishing sheet. +/// extension PrepublishingViewController { /// Determines whether the account and the post's blog is eligible to see auto-sharing options. @@ -12,19 +14,11 @@ extension PrepublishingViewController { } func configureSocialCell(_ cell: UITableViewCell) { - // TODO: - // - Show the NoConnectionView if user has 0 connections. - 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. - NSLayoutConstraint.activate([ - autoSharingView.leadingAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.leadingAnchor), - autoSharingView.topAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.topAnchor), - autoSharingView.bottomAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.bottomAnchor), - autoSharingView.trailingAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.trailingAnchor) - ]) - cell.accessoryType = .disclosureIndicator // TODO: only for autoSharingView. + if hasExistingConnections { + configureAutoSharingView(for: cell) + } else { + configureNoConnectionView(for: cell) + } } } @@ -32,6 +26,34 @@ extension PrepublishingViewController { private extension PrepublishingViewController { + var hasExistingConnections: Bool { + coreDataStack.performQuery { [postObjectID = post.objectID] context in + guard let post = (try? context.existingObject(with: postObjectID)) as? Post, + let connections = post.blog.connections as? Set else { + return false + } + return !connections.isEmpty + } + } + + // MARK: Auto Sharing View + + func configureAutoSharingView(for cell: UITableViewCell) { + let viewModel = makeAutoSharingViewModel() + let viewToEmbed = UIView.embedSwiftUIView(PrepublishingAutoSharingView(model: viewModel)) + cell.contentView.addSubview(viewToEmbed) + + // Pin constraints to the cell's layoutMarginsGuide so that the content is properly aligned. + NSLayoutConstraint.activate([ + viewToEmbed.leadingAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.leadingAnchor), + viewToEmbed.topAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.topAnchor), + viewToEmbed.bottomAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.bottomAnchor), + viewToEmbed.trailingAnchor.constraint(equalTo: cell.contentView.layoutMarginsGuide.trailingAnchor) + ]) + + cell.accessoryType = .disclosureIndicator + } + func makeAutoSharingViewModel() -> PrepublishingAutoSharingViewModel { return coreDataStack.performQuery { [postObjectID = post.objectID] context in guard let post = (try? context.existingObject(with: postObjectID)) as? Post, @@ -70,4 +92,36 @@ private extension PrepublishingViewController { } } + // MARK: - No Connection View + + func configureNoConnectionView(for cell: UITableViewCell) { + let viewModel = makeNoConnectionViewModel() + guard let viewToEmbed = JetpackSocialNoConnectionView.createHostController(with: viewModel).view else { + return + } + + cell.contentView.addSubview(viewToEmbed) + cell.contentView.pinSubviewToSafeArea(viewToEmbed) + } + + func makeNoConnectionView() -> UIView { + let viewModel = makeNoConnectionViewModel() + let controller = JetpackSocialNoConnectionView.createHostController(with: viewModel) + return controller.view + } + + func makeNoConnectionViewModel() -> JetpackSocialNoConnectionViewModel { + return coreDataStack.performQuery { [weak self] context in + guard let services = try? PublicizeService.allSupportedServices(in: context) else { + return .init() + } + + // TODO: Tap actions + return .init(services: services, preferredBackgroundColor: self?.tableView.backgroundColor) + } + } + + enum Constants { + static let socialCellBackgroundColor = UIColor(light: .listForeground, dark: .listBackground) + } } From b0850b0486a3a303ab7c7db2b2b75fe9f5f62d12 Mon Sep 17 00:00:00 2001 From: David Christiandy <1299411+dvdchr@users.noreply.github.com> Date: Wed, 12 Jul 2023 21:03:14 +0700 Subject: [PATCH 3/3] Try to use the post's object context first --- .../PrepublishingViewController+JetpackSocial.swift | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/WordPress/Classes/ViewRelated/Post/PrepublishingViewController+JetpackSocial.swift b/WordPress/Classes/ViewRelated/Post/PrepublishingViewController+JetpackSocial.swift index df57694a9618..2ad3040ecdb1 100644 --- a/WordPress/Classes/ViewRelated/Post/PrepublishingViewController+JetpackSocial.swift +++ b/WordPress/Classes/ViewRelated/Post/PrepublishingViewController+JetpackSocial.swift @@ -111,14 +111,13 @@ private extension PrepublishingViewController { } func makeNoConnectionViewModel() -> JetpackSocialNoConnectionViewModel { - return coreDataStack.performQuery { [weak self] context in - guard let services = try? PublicizeService.allSupportedServices(in: context) else { - return .init() - } - - // TODO: Tap actions - return .init(services: services, preferredBackgroundColor: self?.tableView.backgroundColor) + let context = post.managedObjectContext ?? coreDataStack.mainContext + guard let services = try? PublicizeService.allSupportedServices(in: context) else { + return .init() } + + // TODO: Tap actions + return .init(services: services, preferredBackgroundColor: tableView.backgroundColor) } enum Constants {