From f9863b78aa32b622be2e378dd3d477e1a7af199d Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 2 Nov 2022 12:01:51 +0900 Subject: [PATCH 01/24] Add getPluginDetails action to ZendeskManager --- .../Tools/Zendesk/ZendeskManager.swift | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 7a229032327..7b8ccaa86c9 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -358,6 +358,23 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { if let sourceTagOrigin = supportSourceTag, sourceTagOrigin.isEmpty == false { decoratedTags.append(sourceTagOrigin) } + // WIP + let action = SitePluginAction.getPluginDetails(siteID: site.siteID, pluginName: "WooCommerce Stripe Gateway") { result in + switch result { + case .success(let plugin): + if plugin.status == .inactive { + decoratedTags.append(Constants.woo_mobile_stripe_installed_and_not_activated) + } else if plugin.status == .active { + decoratedTags.append(Constants.woo_mobile_stripe_installed_and_activated) + } else { + decoratedTags.append(Constants.woo_mobile_stripe_not_installed) + } + case .failure(let error): + DDLogError("Unable to fetch plugin details: \(error)") + break + } + } + ServiceLocator.stores.dispatch(action) return decoratedTags } @@ -1012,6 +1029,16 @@ private extension ZendeskManager { static let paymentsSubcategory = "payment" static let paymentsProduct = "woocommerce_payments" static let paymentsProductArea = "product_area_woo_payment_gateway" + // WIP + static let stripePluginName = "WooCommerce Stripe Gateway" + static let wcPayPluginName = "WooCommerce Payments" + static let woo_mobile_stripe_not_installed = "woo_mobile_stripe_not_installed" + static let woo_mobile_stripe_installed_and_not_activated = "woo_mobile_stripe_installed_and_not_activated" + static let woo_mobile_stripe_installed_and_activated = "woo_mobile_stripe_installed_and_activated" + static let woo_mobile_wcpay_not_installed = "woo_mobile_wcpay_not_installed" + static let woo_mobile_wcpay_installed_and_not_activated = "woo_mobile_wcpay_installed_and_not_activated" + static let woo_mobile_wcpay_installed_and_activated = "woo_mobile_wcpay_installed_and_activated" + static let woo_mobile_site_plugins_fetching_error = "woo_mobile_site_plugins_fetching_error" } // Zendesk expects these as NSNumber. However, they are defined as UInt64 to satisfy 32-bit devices (ex: iPhone 5). From a38b3058e8bdc6b0d6c8f9efdea54421843b1a62 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 2 Nov 2022 16:25:13 +0900 Subject: [PATCH 02/24] Add plugin list and completion handler callback --- .../Tools/Zendesk/ZendeskManager.swift | 57 +++++++++++++------ 1 file changed, 40 insertions(+), 17 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 7b8ccaa86c9..c3717e88c48 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -340,6 +340,42 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } + /// Add tags for IPP plugins + /// + func decorateWithIPPTags(onCompletion: @escaping ([String]) -> ()) { + // Get Site ID + guard let siteID = ServiceLocator.stores.sessionManager.defaultSite?.siteID else { + return + } + // Using WooCommerce for testing: + var ippTags: [String] = [] + let pluginList = [ + "woocommerce/woocommerce", + "woocommerce-gateway-stripe/woocommerce-gateway-stripe", + "woocommerce-payments/woocommerce-payments" + ] + // Dispatch action: + for pluginName in pluginList { + let action = SitePluginAction.getPluginDetails(siteID: siteID, pluginName: pluginName) { result in + switch result { + case .success(let plugin): + if plugin.status == .inactive { + ippTags.append(Constants.woo_mobile_stripe_installed_and_not_activated) + } else if plugin.status == .active { + ippTags.append(Constants.woo_mobile_stripe_installed_and_activated) + } else { + ippTags.append(Constants.woo_mobile_stripe_not_installed) + } + case .failure(let error): + DDLogError("Unable to fetch plugin \(pluginName). Error: \(error)") + break + } + onCompletion(ippTags) + } + ServiceLocator.stores.dispatch(action) + } + } + func decorateTags(tags: [String], supportSourceTag: String?) -> [String] { guard let site = ServiceLocator.stores.sessionManager.defaultSite else { return tags @@ -358,24 +394,11 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { if let sourceTagOrigin = supportSourceTag, sourceTagOrigin.isEmpty == false { decoratedTags.append(sourceTagOrigin) } - // WIP - let action = SitePluginAction.getPluginDetails(siteID: site.siteID, pluginName: "WooCommerce Stripe Gateway") { result in - switch result { - case .success(let plugin): - if plugin.status == .inactive { - decoratedTags.append(Constants.woo_mobile_stripe_installed_and_not_activated) - } else if plugin.status == .active { - decoratedTags.append(Constants.woo_mobile_stripe_installed_and_activated) - } else { - decoratedTags.append(Constants.woo_mobile_stripe_not_installed) - } - case .failure(let error): - DDLogError("Unable to fetch plugin details: \(error)") - break - } - } - ServiceLocator.stores.dispatch(action) + decorateWithIPPTags(onCompletion: { ippTags in + print("decorateWithIPPTags callback completed: \(ippTags)") + }) + // TODO: Inject decorateWithIPPTags here. return decoratedTags } } From f44fca00dc37647329bcfb8b4b3e4c75c21e7e77 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 2 Nov 2022 18:26:17 +0900 Subject: [PATCH 03/24] Try to get plugins by observing changes in Storage --- .../Tools/Zendesk/ZendeskManager.swift | 75 ++++++++++++++++--- 1 file changed, 64 insertions(+), 11 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index c3717e88c48..2a6c23e9308 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -8,6 +8,7 @@ import WordPressShared import CoreTelephony import SafariServices import Yosemite +import Storage extension NSNotification.Name { @@ -138,6 +139,28 @@ struct ZendeskProvider { /// #if !targetEnvironment(macCatalyst) final class ZendeskManager: NSObject, ZendeskManagerProtocol { + // WIP. Like PluginListViewModel + private let storageManager: StorageManagerType = ServiceLocator.storageManager + private lazy var resultsController: ResultsController = { + let siteID = ServiceLocator.stores.sessionManager.defaultSite?.siteID + let predicate = NSPredicate(format: "siteID = %ld", String(siteID ?? 0)) + let statusDescriptor = NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true) + let resultsController = ResultsController( + storageManager: storageManager, sortedBy: [statusDescriptor]) + do { + try resultsController.performFetch() + } catch { + DDLogError("⛔️ Error fetching plugin list!") + } + return resultsController + }() + + func observePlugins(onDataChanged: @escaping () -> Void) { + resultsController.onDidResetContent = onDataChanged + let foundIt = resultsController.fetchedObjects.first(where: { $0.plugin == "woocommerce/woocommerce" } ) + print("Found it: \(foundIt?.name ?? "Not Found")") + } + func showNewRequestIfPossible(from controller: UIViewController) { showNewRequestIfPossible(from: controller, with: nil) } @@ -340,6 +363,39 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } + func experimentObservingChangesOnStorage() { + observePlugins(onDataChanged: { }) + } + + private func checkFor(plugin: Yosemite.SitePlugin) -> String { + var tag = "" + let pluginList = [ + "woocommerce-gateway-stripe/woocommerce-gateway-stripe", + "woocommerce-payments/woocommerce-payments" + ] + // Stripe + if plugin.plugin == pluginList[0] { + if plugin.status == .inactive { + tag = Constants.woo_mobile_stripe_installed_and_not_activated + } else if plugin.status == .active { + tag = Constants.woo_mobile_stripe_installed_and_activated + } else { + tag = Constants.woo_mobile_stripe_not_installed + } + } + // WCPay + if plugin.plugin == pluginList[1] { + if plugin.status == .inactive { + tag = Constants.woo_mobile_wcpay_installed_and_not_activated + } else if plugin.status == .active { + tag = Constants.woo_mobile_wcpay_installed_and_activated + } else { + tag = Constants.woo_mobile_wcpay_not_installed + } + } + return tag + } + /// Add tags for IPP plugins /// func decorateWithIPPTags(onCompletion: @escaping ([String]) -> ()) { @@ -347,10 +403,8 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { guard let siteID = ServiceLocator.stores.sessionManager.defaultSite?.siteID else { return } - // Using WooCommerce for testing: - var ippTags: [String] = [] + var ippTags = [String]() let pluginList = [ - "woocommerce/woocommerce", "woocommerce-gateway-stripe/woocommerce-gateway-stripe", "woocommerce-payments/woocommerce-payments" ] @@ -359,13 +413,8 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { let action = SitePluginAction.getPluginDetails(siteID: siteID, pluginName: pluginName) { result in switch result { case .success(let plugin): - if plugin.status == .inactive { - ippTags.append(Constants.woo_mobile_stripe_installed_and_not_activated) - } else if plugin.status == .active { - ippTags.append(Constants.woo_mobile_stripe_installed_and_activated) - } else { - ippTags.append(Constants.woo_mobile_stripe_not_installed) - } + let checkedPlugin = self.checkFor(plugin: plugin) + ippTags.append(checkedPlugin) case .failure(let error): DDLogError("Unable to fetch plugin \(pluginName). Error: \(error)") break @@ -394,10 +443,14 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { if let sourceTagOrigin = supportSourceTag, sourceTagOrigin.isEmpty == false { decoratedTags.append(sourceTagOrigin) } - + + // Testing via Actions: decorateWithIPPTags(onCompletion: { ippTags in print("decorateWithIPPTags callback completed: \(ippTags)") }) + // Testing via Storage: + experimentObservingChangesOnStorage() + // TODO: Inject decorateWithIPPTags here. return decoratedTags } From 783e34a356c9e900c2f7aa09ad1079a799f546fb Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 2 Nov 2022 21:25:39 +0900 Subject: [PATCH 04/24] Append ipp tags if needed to decorated tags --- .../Tools/Zendesk/ZendeskManager.swift | 94 +++++-------------- 1 file changed, 23 insertions(+), 71 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 2a6c23e9308..8708e192a09 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -139,12 +139,14 @@ struct ZendeskProvider { /// #if !targetEnvironment(macCatalyst) final class ZendeskManager: NSObject, ZendeskManagerProtocol { - // WIP. Like PluginListViewModel + private let storageManager: StorageManagerType = ServiceLocator.storageManager + private lazy var resultsController: ResultsController = { let siteID = ServiceLocator.stores.sessionManager.defaultSite?.siteID let predicate = NSPredicate(format: "siteID = %ld", String(siteID ?? 0)) let statusDescriptor = NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true) + let resultsController = ResultsController( storageManager: storageManager, sortedBy: [statusDescriptor]) do { @@ -156,9 +158,16 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { }() func observePlugins(onDataChanged: @escaping () -> Void) { + let stripePluginSlug = "woocommerce-gateway-stripe/woocommerce-gateway-stripe" + let wcPayPluginSlug = "woocommerce-payments/woocommerce-payments" + resultsController.onDidResetContent = onDataChanged - let foundIt = resultsController.fetchedObjects.first(where: { $0.plugin == "woocommerce/woocommerce" } ) - print("Found it: \(foundIt?.name ?? "Not Found")") + if let _ = resultsController.fetchedObjects.first(where: { $0.plugin == stripePluginSlug } ) { + ippTags.append(stripePluginSlug) + } + if let _ = resultsController.fetchedObjects.first(where: { $0.plugin == wcPayPluginSlug } ) { + ippTags.append(wcPayPluginSlug) + } } func showNewRequestIfPossible(from controller: UIViewController) { @@ -195,6 +204,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { private var userEmail: String? private var haveUserIdentity = false private var alertNameField: UITextField? + private var ippTags: [String] = [""] private weak var presentInController: UIViewController? @@ -363,66 +373,12 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } - func experimentObservingChangesOnStorage() { - observePlugins(onDataChanged: { }) - } - - private func checkFor(plugin: Yosemite.SitePlugin) -> String { - var tag = "" - let pluginList = [ - "woocommerce-gateway-stripe/woocommerce-gateway-stripe", - "woocommerce-payments/woocommerce-payments" - ] - // Stripe - if plugin.plugin == pluginList[0] { - if plugin.status == .inactive { - tag = Constants.woo_mobile_stripe_installed_and_not_activated - } else if plugin.status == .active { - tag = Constants.woo_mobile_stripe_installed_and_activated - } else { - tag = Constants.woo_mobile_stripe_not_installed - } - } - // WCPay - if plugin.plugin == pluginList[1] { - if plugin.status == .inactive { - tag = Constants.woo_mobile_wcpay_installed_and_not_activated - } else if plugin.status == .active { - tag = Constants.woo_mobile_wcpay_installed_and_activated - } else { - tag = Constants.woo_mobile_wcpay_not_installed - } - } - return tag - } - - /// Add tags for IPP plugins - /// - func decorateWithIPPTags(onCompletion: @escaping ([String]) -> ()) { - // Get Site ID - guard let siteID = ServiceLocator.stores.sessionManager.defaultSite?.siteID else { - return - } - var ippTags = [String]() - let pluginList = [ - "woocommerce-gateway-stripe/woocommerce-gateway-stripe", - "woocommerce-payments/woocommerce-payments" - ] - // Dispatch action: - for pluginName in pluginList { - let action = SitePluginAction.getPluginDetails(siteID: siteID, pluginName: pluginName) { result in - switch result { - case .success(let plugin): - let checkedPlugin = self.checkFor(plugin: plugin) - ippTags.append(checkedPlugin) - case .failure(let error): - DDLogError("Unable to fetch plugin \(pluginName). Error: \(error)") - break - } - onCompletion(ippTags) - } - ServiceLocator.stores.dispatch(action) - } + func appendIPPstatusTagsIfNeeded(decoratedTags: [String]) -> [String] { + var tags = decoratedTags + observePlugins(onDataChanged: { + tags.append(contentsOf: self.ippTags) + }) + return tags } func decorateTags(tags: [String], supportSourceTag: String?) -> [String] { @@ -443,15 +399,11 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { if let sourceTagOrigin = supportSourceTag, sourceTagOrigin.isEmpty == false { decoratedTags.append(sourceTagOrigin) } + + // Adds specific plugin status tags for Stripe and WCPay: + decoratedTags = appendIPPstatusTagsIfNeeded(decoratedTags: decoratedTags) - // Testing via Actions: - decorateWithIPPTags(onCompletion: { ippTags in - print("decorateWithIPPTags callback completed: \(ippTags)") - }) - // Testing via Storage: - experimentObservingChangesOnStorage() - - // TODO: Inject decorateWithIPPTags here. + print("Tags: \(decoratedTags)") return decoratedTags } } From 914d74b879a71b308a1a655c80817b247de6c496 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 2 Nov 2022 21:32:34 +0900 Subject: [PATCH 05/24] Add logic for plugin status --- .../Tools/Zendesk/ZendeskManager.swift | 24 ++++++++++++++----- 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 8708e192a09..659ba6b2fd4 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -162,11 +162,24 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { let wcPayPluginSlug = "woocommerce-payments/woocommerce-payments" resultsController.onDidResetContent = onDataChanged - if let _ = resultsController.fetchedObjects.first(where: { $0.plugin == stripePluginSlug } ) { - ippTags.append(stripePluginSlug) + + if let stripe = resultsController.fetchedObjects.first(where: { $0.plugin == stripePluginSlug } ) { + if stripe.status == .inactive { + ippTags.append(Constants.woo_mobile_stripe_installed_and_not_activated) + } else if stripe.status == .active { + ippTags.append(Constants.woo_mobile_stripe_installed_and_activated) + } else { + ippTags.append(Constants.woo_mobile_stripe_not_installed) + } } - if let _ = resultsController.fetchedObjects.first(where: { $0.plugin == wcPayPluginSlug } ) { - ippTags.append(wcPayPluginSlug) + if let wcPay = resultsController.fetchedObjects.first(where: { $0.plugin == wcPayPluginSlug } ) { + if wcPay.status == .inactive { + ippTags.append(Constants.woo_mobile_wcpay_installed_and_not_activated) + } else if wcPay.status == .active { + ippTags.append(Constants.woo_mobile_wcpay_installed_and_activated) + } else { + ippTags.append(Constants.woo_mobile_wcpay_not_installed) + } } } @@ -400,10 +413,9 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { decoratedTags.append(sourceTagOrigin) } - // Adds specific plugin status tags for Stripe and WCPay: decoratedTags = appendIPPstatusTagsIfNeeded(decoratedTags: decoratedTags) - print("Tags: \(decoratedTags)") + print("All tags: \(decoratedTags)") return decoratedTags } } From 1c97557b2102b61145b376e6524f8de91611c367 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 3 Nov 2022 14:17:40 +0900 Subject: [PATCH 06/24] Experiment with async call for tag retrieval --- .../Tools/Zendesk/ZendeskManager.swift | 46 +++++++++++-------- 1 file changed, 28 insertions(+), 18 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 659ba6b2fd4..f429448df2b 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -217,7 +217,8 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { private var userEmail: String? private var haveUserIdentity = false private var alertNameField: UITextField? - private var ippTags: [String] = [""] + private var supportRequestTags = [String]() + private var ippTags = [String]() private weak var presentInController: UIViewController? @@ -372,7 +373,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { func getTags(supportSourceTag: String?) -> [String] { let tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] - return decorateTags(tags: tags, supportSourceTag: supportSourceTag) + return decorateTags(supportSourceTag: supportSourceTag) } func getWCPayTags(supportSourceTag: String?) -> [String] { @@ -383,7 +384,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { Constants.paymentsSubcategory, Constants.paymentsProductArea] - return decorateTags(tags: tags, supportSourceTag: supportSourceTag) + return decorateTags(supportSourceTag: supportSourceTag) } func appendIPPstatusTagsIfNeeded(decoratedTags: [String]) -> [String] { @@ -394,29 +395,25 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return tags } - func decorateTags(tags: [String], supportSourceTag: String?) -> [String] { + func decorateTags(supportSourceTag: String?) -> [String] { guard let site = ServiceLocator.stores.sessionManager.defaultSite else { - return tags + return supportRequestTags } - var decoratedTags = tags - if site.isWordPressStore == true { - decoratedTags.append(Constants.wpComTag) + supportRequestTags.append(Constants.wpComTag) } if site.plan.isEmpty == false { - decoratedTags.append(site.plan) + supportRequestTags.append(site.plan) } if let sourceTagOrigin = supportSourceTag, sourceTagOrigin.isEmpty == false { - decoratedTags.append(sourceTagOrigin) + supportRequestTags.append(sourceTagOrigin) } - decoratedTags = appendIPPstatusTagsIfNeeded(decoratedTags: decoratedTags) - - print("All tags: \(decoratedTags)") - return decoratedTags + print("All tags: \(supportRequestTags)") + return supportRequestTags } } @@ -646,7 +643,20 @@ private extension ZendeskManager { return createRequest(supportSourceTag: supportSourceTag, formID: TicketFieldIDs.form, ticketFields: ticketFields, - tags: getTags(supportSourceTag: supportSourceTag)) + tags: asyncGetTags(completion: { _ in })) + } + + func asyncGetTags(supportSourceTag: String? = nil, completion: @escaping ([String]) -> ()) { + // 1 - getTags code: + supportRequestTags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] + // 2 - decorateTags code: + supportRequestTags = decorateTags(supportSourceTag: supportSourceTag) + // 3 - add IPP ones if needed: + observePlugins(onDataChanged: { [weak self] in + guard let self = self else { return } + self.supportRequestTags.append(contentsOf: self.ippTags) + completion(self.supportRequestTags) + }) } func createWCPayRequest(supportSourceTag: String?) -> RequestUiConfiguration { @@ -667,10 +677,10 @@ private extension ZendeskManager { return createRequest(supportSourceTag: supportSourceTag, formID: TicketFieldIDs.paymentsForm, ticketFields: ticketFields, - tags: getWCPayTags(supportSourceTag: supportSourceTag)) + tags: asyncGetTags(completion: { _ in })) } - func createRequest(supportSourceTag: String?, formID: Int64, ticketFields: [CustomField], tags: [String]) -> RequestUiConfiguration { + func createRequest(supportSourceTag: String?, formID: Int64, ticketFields: [CustomField], tags: ()) -> RequestUiConfiguration { let requestConfig = RequestUiConfiguration() // Set Zendesk ticket form to use @@ -679,7 +689,7 @@ private extension ZendeskManager { requestConfig.customFields = ticketFields // Set tags - requestConfig.tags = tags + requestConfig.tags = self.supportRequestTags // Set the ticket subject requestConfig.subject = Constants.ticketSubject From 7a3b9ce490533227f66569de8dc2fa85c846db2a Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 3 Nov 2022 18:28:41 +0900 Subject: [PATCH 07/24] Return all tags on creating ZD request --- .../Tools/Zendesk/ZendeskManager.swift | 46 +++++++++---------- 1 file changed, 21 insertions(+), 25 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index f429448df2b..311a8f3a731 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -219,6 +219,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { private var alertNameField: UITextField? private var supportRequestTags = [String]() private var ippTags = [String]() + private var getSitePlugins: () private weak var presentInController: UIViewController? @@ -238,6 +239,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { fileprivate override init() { super.init() observeZendeskNotifications() + getSitePlugins = observePlugins(onDataChanged: {}) } @@ -373,7 +375,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { func getTags(supportSourceTag: String?) -> [String] { let tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] - return decorateTags(supportSourceTag: supportSourceTag) + return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } func getWCPayTags(supportSourceTag: String?) -> [String] { @@ -384,7 +386,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { Constants.paymentsSubcategory, Constants.paymentsProductArea] - return decorateTags(supportSourceTag: supportSourceTag) + return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } func appendIPPstatusTagsIfNeeded(decoratedTags: [String]) -> [String] { @@ -395,25 +397,27 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return tags } - func decorateTags(supportSourceTag: String?) -> [String] { + func decorateTags(tags: [String], supportSourceTag: String?) -> [String] { guard let site = ServiceLocator.stores.sessionManager.defaultSite else { - return supportRequestTags + return tags } + var decoratedTags = tags + if site.isWordPressStore == true { - supportRequestTags.append(Constants.wpComTag) + decoratedTags.append(Constants.wpComTag) } if site.plan.isEmpty == false { - supportRequestTags.append(site.plan) + decoratedTags.append(site.plan) } if let sourceTagOrigin = supportSourceTag, sourceTagOrigin.isEmpty == false { - supportRequestTags.append(sourceTagOrigin) + decoratedTags.append(sourceTagOrigin) } - print("All tags: \(supportRequestTags)") - return supportRequestTags + print("All decorated tags: \(decoratedTags)") + return decoratedTags } } @@ -643,20 +647,7 @@ private extension ZendeskManager { return createRequest(supportSourceTag: supportSourceTag, formID: TicketFieldIDs.form, ticketFields: ticketFields, - tags: asyncGetTags(completion: { _ in })) - } - - func asyncGetTags(supportSourceTag: String? = nil, completion: @escaping ([String]) -> ()) { - // 1 - getTags code: - supportRequestTags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] - // 2 - decorateTags code: - supportRequestTags = decorateTags(supportSourceTag: supportSourceTag) - // 3 - add IPP ones if needed: - observePlugins(onDataChanged: { [weak self] in - guard let self = self else { return } - self.supportRequestTags.append(contentsOf: self.ippTags) - completion(self.supportRequestTags) - }) + tags: getSitePlugins ) } func createWCPayRequest(supportSourceTag: String?) -> RequestUiConfiguration { @@ -677,7 +668,7 @@ private extension ZendeskManager { return createRequest(supportSourceTag: supportSourceTag, formID: TicketFieldIDs.paymentsForm, ticketFields: ticketFields, - tags: asyncGetTags(completion: { _ in })) + tags: getSitePlugins ) } func createRequest(supportSourceTag: String?, formID: Int64, ticketFields: [CustomField], tags: ()) -> RequestUiConfiguration { @@ -689,7 +680,12 @@ private extension ZendeskManager { requestConfig.customFields = ticketFields // Set tags - requestConfig.tags = self.supportRequestTags + var defaultTags = getTags(supportSourceTag: supportSourceTag) + let ippTags = self.ippTags + var allTags = defaultTags + ippTags + print(allTags) + + requestConfig.tags = allTags // Set the ticket subject requestConfig.subject = Constants.ticketSubject From 6f9a3fdd6aa8553d85877b21b7323fefca0965a9 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Fri, 4 Nov 2022 19:11:46 +0900 Subject: [PATCH 08/24] Remove unused vars --- WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift | 5 ----- 1 file changed, 5 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 311a8f3a731..d051411690c 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -217,7 +217,6 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { private var userEmail: String? private var haveUserIdentity = false private var alertNameField: UITextField? - private var supportRequestTags = [String]() private var ippTags = [String]() private var getSitePlugins: () @@ -683,7 +682,6 @@ private extension ZendeskManager { var defaultTags = getTags(supportSourceTag: supportSourceTag) let ippTags = self.ippTags var allTags = defaultTags + ippTags - print(allTags) requestConfig.tags = allTags @@ -1075,9 +1073,6 @@ private extension ZendeskManager { static let paymentsSubcategory = "payment" static let paymentsProduct = "woocommerce_payments" static let paymentsProductArea = "product_area_woo_payment_gateway" - // WIP - static let stripePluginName = "WooCommerce Stripe Gateway" - static let wcPayPluginName = "WooCommerce Payments" static let woo_mobile_stripe_not_installed = "woo_mobile_stripe_not_installed" static let woo_mobile_stripe_installed_and_not_activated = "woo_mobile_stripe_installed_and_not_activated" static let woo_mobile_stripe_installed_and_activated = "woo_mobile_stripe_installed_and_activated" From 4b39882c9c61a7fe7dcc6484a22441f95895bd05 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Fri, 4 Nov 2022 19:19:26 +0900 Subject: [PATCH 09/24] Move plugin slugs to Constants enum --- WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index d051411690c..0613d84d19c 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -152,18 +152,16 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { do { try resultsController.performFetch() } catch { + ippTags.append(Constants.woo_mobile_site_plugins_fetching_error) DDLogError("⛔️ Error fetching plugin list!") } return resultsController }() func observePlugins(onDataChanged: @escaping () -> Void) { - let stripePluginSlug = "woocommerce-gateway-stripe/woocommerce-gateway-stripe" - let wcPayPluginSlug = "woocommerce-payments/woocommerce-payments" - resultsController.onDidResetContent = onDataChanged - if let stripe = resultsController.fetchedObjects.first(where: { $0.plugin == stripePluginSlug } ) { + if let stripe = resultsController.fetchedObjects.first(where: { $0.plugin == Constants.stripe_plugin_slug } ) { if stripe.status == .inactive { ippTags.append(Constants.woo_mobile_stripe_installed_and_not_activated) } else if stripe.status == .active { @@ -172,7 +170,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { ippTags.append(Constants.woo_mobile_stripe_not_installed) } } - if let wcPay = resultsController.fetchedObjects.first(where: { $0.plugin == wcPayPluginSlug } ) { + if let wcPay = resultsController.fetchedObjects.first(where: { $0.plugin == Constants.wcpay_plugin_slug } ) { if wcPay.status == .inactive { ippTags.append(Constants.woo_mobile_wcpay_installed_and_not_activated) } else if wcPay.status == .active { @@ -1073,6 +1071,8 @@ private extension ZendeskManager { static let paymentsSubcategory = "payment" static let paymentsProduct = "woocommerce_payments" static let paymentsProductArea = "product_area_woo_payment_gateway" + static let stripe_plugin_slug = "woocommerce-gateway-stripe/woocommerce-gateway-stripe" + static let wcpay_plugin_slug = "woocommerce-payments/woocommerce-payments" static let woo_mobile_stripe_not_installed = "woo_mobile_stripe_not_installed" static let woo_mobile_stripe_installed_and_not_activated = "woo_mobile_stripe_installed_and_not_activated" static let woo_mobile_stripe_installed_and_activated = "woo_mobile_stripe_installed_and_activated" From 75cb9672f8c032707939bb5132869f42a5d7ebed Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Fri, 4 Nov 2022 19:26:20 +0900 Subject: [PATCH 10/24] Access control changes. Make func private. --- WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 0613d84d19c..894ce0eb543 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -158,7 +158,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return resultsController }() - func observePlugins(onDataChanged: @escaping () -> Void) { + private func observePlugins(onDataChanged: @escaping () -> Void) { resultsController.onDidResetContent = onDataChanged if let stripe = resultsController.fetchedObjects.first(where: { $0.plugin == Constants.stripe_plugin_slug } ) { @@ -375,7 +375,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } - func getWCPayTags(supportSourceTag: String?) -> [String] { + private func getWCPayTags(supportSourceTag: String?) -> [String] { let tags = [Constants.platformTag, Constants.sdkTag, Constants.paymentsProduct, @@ -386,7 +386,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } - func appendIPPstatusTagsIfNeeded(decoratedTags: [String]) -> [String] { + private func appendIPPstatusTagsIfNeeded(decoratedTags: [String]) -> [String] { var tags = decoratedTags observePlugins(onDataChanged: { tags.append(contentsOf: self.ippTags) @@ -394,7 +394,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return tags } - func decorateTags(tags: [String], supportSourceTag: String?) -> [String] { + private func decorateTags(tags: [String], supportSourceTag: String?) -> [String] { guard let site = ServiceLocator.stores.sessionManager.defaultSite else { return tags } From e243aaa046e629553c5d18ee26ccf7c25505f71f Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 7 Nov 2022 11:36:54 +0900 Subject: [PATCH 11/24] Extract logic to SettingsViewModel --- .../Tools/Zendesk/ZendeskManager.swift | 88 +++---------------- .../Settings/Settings/SettingsViewModel.swift | 53 +++++++++++ 2 files changed, 65 insertions(+), 76 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 894ce0eb543..76d4d829926 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -8,8 +8,6 @@ import WordPressShared import CoreTelephony import SafariServices import Yosemite -import Storage - extension NSNotification.Name { static let ZDPNReceived = NSNotification.Name(rawValue: "ZDPNReceived") @@ -139,48 +137,6 @@ struct ZendeskProvider { /// #if !targetEnvironment(macCatalyst) final class ZendeskManager: NSObject, ZendeskManagerProtocol { - - private let storageManager: StorageManagerType = ServiceLocator.storageManager - - private lazy var resultsController: ResultsController = { - let siteID = ServiceLocator.stores.sessionManager.defaultSite?.siteID - let predicate = NSPredicate(format: "siteID = %ld", String(siteID ?? 0)) - let statusDescriptor = NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true) - - let resultsController = ResultsController( - storageManager: storageManager, sortedBy: [statusDescriptor]) - do { - try resultsController.performFetch() - } catch { - ippTags.append(Constants.woo_mobile_site_plugins_fetching_error) - DDLogError("⛔️ Error fetching plugin list!") - } - return resultsController - }() - - private func observePlugins(onDataChanged: @escaping () -> Void) { - resultsController.onDidResetContent = onDataChanged - - if let stripe = resultsController.fetchedObjects.first(where: { $0.plugin == Constants.stripe_plugin_slug } ) { - if stripe.status == .inactive { - ippTags.append(Constants.woo_mobile_stripe_installed_and_not_activated) - } else if stripe.status == .active { - ippTags.append(Constants.woo_mobile_stripe_installed_and_activated) - } else { - ippTags.append(Constants.woo_mobile_stripe_not_installed) - } - } - if let wcPay = resultsController.fetchedObjects.first(where: { $0.plugin == Constants.wcpay_plugin_slug } ) { - if wcPay.status == .inactive { - ippTags.append(Constants.woo_mobile_wcpay_installed_and_not_activated) - } else if wcPay.status == .active { - ippTags.append(Constants.woo_mobile_wcpay_installed_and_activated) - } else { - ippTags.append(Constants.woo_mobile_wcpay_not_installed) - } - } - } - func showNewRequestIfPossible(from controller: UIViewController) { showNewRequestIfPossible(from: controller, with: nil) } @@ -201,6 +157,8 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { } } + private lazy var settingsVM = SettingsViewModel() + private var unreadNotificationsCount = 0 var showSupportNotificationIndicator: Bool { @@ -215,8 +173,6 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { private var userEmail: String? private var haveUserIdentity = false private var alertNameField: UITextField? - private var ippTags = [String]() - private var getSitePlugins: () private weak var presentInController: UIViewController? @@ -236,7 +192,6 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { fileprivate override init() { super.init() observeZendeskNotifications() - getSitePlugins = observePlugins(onDataChanged: {}) } @@ -370,12 +325,15 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// The SDK tag is used in a trigger and displays tickets in Woo > Mobile Apps New. /// func getTags(supportSourceTag: String?) -> [String] { - let tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] + var tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] + if let ippTags = settingsVM.ippPluginTags { + tags.append(contentsOf: ippTags) + } return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } - private func getWCPayTags(supportSourceTag: String?) -> [String] { + func getWCPayTags(supportSourceTag: String?) -> [String] { let tags = [Constants.platformTag, Constants.sdkTag, Constants.paymentsProduct, @@ -386,15 +344,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } - private func appendIPPstatusTagsIfNeeded(decoratedTags: [String]) -> [String] { - var tags = decoratedTags - observePlugins(onDataChanged: { - tags.append(contentsOf: self.ippTags) - }) - return tags - } - - private func decorateTags(tags: [String], supportSourceTag: String?) -> [String] { + func decorateTags(tags: [String], supportSourceTag: String?) -> [String] { guard let site = ServiceLocator.stores.sessionManager.defaultSite else { return tags } @@ -413,7 +363,6 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { decoratedTags.append(sourceTagOrigin) } - print("All decorated tags: \(decoratedTags)") return decoratedTags } } @@ -644,7 +593,7 @@ private extension ZendeskManager { return createRequest(supportSourceTag: supportSourceTag, formID: TicketFieldIDs.form, ticketFields: ticketFields, - tags: getSitePlugins ) + tags: getTags(supportSourceTag: supportSourceTag)) } func createWCPayRequest(supportSourceTag: String?) -> RequestUiConfiguration { @@ -665,10 +614,10 @@ private extension ZendeskManager { return createRequest(supportSourceTag: supportSourceTag, formID: TicketFieldIDs.paymentsForm, ticketFields: ticketFields, - tags: getSitePlugins ) + tags: getWCPayTags(supportSourceTag: supportSourceTag)) } - func createRequest(supportSourceTag: String?, formID: Int64, ticketFields: [CustomField], tags: ()) -> RequestUiConfiguration { + func createRequest(supportSourceTag: String?, formID: Int64, ticketFields: [CustomField], tags: [String]) -> RequestUiConfiguration { let requestConfig = RequestUiConfiguration() // Set Zendesk ticket form to use @@ -677,11 +626,7 @@ private extension ZendeskManager { requestConfig.customFields = ticketFields // Set tags - var defaultTags = getTags(supportSourceTag: supportSourceTag) - let ippTags = self.ippTags - var allTags = defaultTags + ippTags - - requestConfig.tags = allTags + requestConfig.tags = tags // Set the ticket subject requestConfig.subject = Constants.ticketSubject @@ -1071,15 +1016,6 @@ private extension ZendeskManager { static let paymentsSubcategory = "payment" static let paymentsProduct = "woocommerce_payments" static let paymentsProductArea = "product_area_woo_payment_gateway" - static let stripe_plugin_slug = "woocommerce-gateway-stripe/woocommerce-gateway-stripe" - static let wcpay_plugin_slug = "woocommerce-payments/woocommerce-payments" - static let woo_mobile_stripe_not_installed = "woo_mobile_stripe_not_installed" - static let woo_mobile_stripe_installed_and_not_activated = "woo_mobile_stripe_installed_and_not_activated" - static let woo_mobile_stripe_installed_and_activated = "woo_mobile_stripe_installed_and_activated" - static let woo_mobile_wcpay_not_installed = "woo_mobile_wcpay_not_installed" - static let woo_mobile_wcpay_installed_and_not_activated = "woo_mobile_wcpay_installed_and_not_activated" - static let woo_mobile_wcpay_installed_and_activated = "woo_mobile_wcpay_installed_and_activated" - static let woo_mobile_site_plugins_fetching_error = "woo_mobile_site_plugins_fetching_error" } // Zendesk expects these as NSNumber. However, they are defined as UInt64 to satisfy 32-bit devices (ex: iPhone 5). diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift index cf5cac4d8cf..dae951d279a 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift @@ -94,6 +94,14 @@ final class SettingsViewModel: SettingsViewModelOutput, SettingsViewModelActions /// private let sitesResultsController: ResultsController + /// + /// + private let ippResultsController: ResultsController + + /// + /// + private(set) var ippPluginTags: [String]? + /// Payment Gateway Accounts Results Controller: Loads Payment Gateway Accounts from the Storage Layer /// e.g. WooCommerce Payments, but eventually other in-person payment accounts too /// @@ -125,6 +133,12 @@ final class SettingsViewModel: SettingsViewModelOutput, SettingsViewModelActions matching: NSPredicate(format: "isWooCommerceActive == YES"), sortedBy: [NSSortDescriptor(key: "name", ascending: true)]) + /// + /// + let ippStatusDescriptor = [NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true)] + ippResultsController = ResultsController(storageManager: storageManager, + sortedBy: ippStatusDescriptor) + /// Initialize Payment Gateway Accounts Results Controller /// if let siteID = stores.sessionManager.defaultSite?.siteID { @@ -141,6 +155,34 @@ final class SettingsViewModel: SettingsViewModelOutput, SettingsViewModelActions let action = SystemStatusAction.synchronizeSystemPlugins(siteID: siteID, onCompletion: { _ in }) stores.dispatch(action) } + + /// + /// + ippPluginTags = { + var out = [String]() + + if let stripe = ippResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.stripe_plugin_slug }) { + if stripe.status == .inactive { + out.append("stripe .inactive") + } else if stripe.status == .active { + out.append("stripe .active") + } + } else { + out.append("stripe .not installed") + } + + if let wcpay = ippResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.wcpay_plugin_slug }) { + if wcpay.status == .inactive { + out.append("wcpay .inactive") + } else if wcpay.status == .active { + out.append("wcpay .active") + } + } + else { + out.append("wcpay .not installed") + } + return out + }() } /// Sets up the view model and loads the settings. @@ -361,6 +403,17 @@ private extension SettingsViewModel { // MARK: - Localizations // private extension SettingsViewModel { + enum IPPPluginStatus { + static let stripe_plugin_slug = "woocommerce-gateway-stripe/woocommerce-gateway-stripe" + static let wcpay_plugin_slug = "woocommerce-payments/woocommerce-payments" + static let woo_mobile_stripe_not_installed = "woo_mobile_stripe_not_installed" + static let woo_mobile_stripe_installed_and_not_activated = "woo_mobile_stripe_installed_and_not_activated" + static let woo_mobile_stripe_installed_and_activated = "woo_mobile_stripe_installed_and_activated" + static let woo_mobile_wcpay_not_installed = "woo_mobile_wcpay_not_installed" + static let woo_mobile_wcpay_installed_and_not_activated = "woo_mobile_wcpay_installed_and_not_activated" + static let woo_mobile_wcpay_installed_and_activated = "woo_mobile_wcpay_installed_and_activated" + static let woo_mobile_site_plugins_fetching_error = "woo_mobile_site_plugins_fetching_error" + } enum Localization { static let pluginsTitle = NSLocalizedString( "Plugins", From b59a59d2efafc94dd861d15561cd1cac593da4b2 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Mon, 7 Nov 2022 12:02:21 +0900 Subject: [PATCH 12/24] Rename variables for clarity. Add comments. --- .../Tools/Zendesk/ZendeskManager.swift | 6 ++- .../Settings/Settings/SettingsViewModel.swift | 50 +++++++++---------- 2 files changed, 29 insertions(+), 27 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 76d4d829926..738e53f448b 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -157,7 +157,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { } } - private lazy var settingsVM = SettingsViewModel() + private lazy var settingsViewModel = SettingsViewModel() private var unreadNotificationsCount = 0 @@ -326,7 +326,9 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// func getTags(supportSourceTag: String?) -> [String] { var tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] - if let ippTags = settingsVM.ippPluginTags { + + // Get IPP plugin statuses + if let ippTags = settingsViewModel.ippPluginstatuses { tags.append(contentsOf: ippTags) } diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift index dae951d279a..cb31ba523ff 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift @@ -94,13 +94,13 @@ final class SettingsViewModel: SettingsViewModelOutput, SettingsViewModelActions /// private let sitesResultsController: ResultsController + /// Loads Plugins from the Storage Layer. /// - /// - private let ippResultsController: ResultsController + private let pluginResultsController: ResultsController + /// IPP plugin statuses /// - /// - private(set) var ippPluginTags: [String]? + private(set) var ippPluginstatuses: [String]? /// Payment Gateway Accounts Results Controller: Loads Payment Gateway Accounts from the Storage Layer /// e.g. WooCommerce Payments, but eventually other in-person payment accounts too @@ -133,11 +133,11 @@ final class SettingsViewModel: SettingsViewModelOutput, SettingsViewModelActions matching: NSPredicate(format: "isWooCommerceActive == YES"), sortedBy: [NSSortDescriptor(key: "name", ascending: true)]) + /// Initialize Plugins Results Controller /// - /// - let ippStatusDescriptor = [NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true)] - ippResultsController = ResultsController(storageManager: storageManager, - sortedBy: ippStatusDescriptor) + let pluginStatusDescriptor = [NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true)] + pluginResultsController = ResultsController(storageManager: storageManager, + sortedBy: pluginStatusDescriptor) /// Initialize Payment Gateway Accounts Results Controller /// @@ -158,30 +158,30 @@ final class SettingsViewModel: SettingsViewModelOutput, SettingsViewModelActions /// /// - ippPluginTags = { - var out = [String]() - - if let stripe = ippResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.stripe_plugin_slug }) { - if stripe.status == .inactive { - out.append("stripe .inactive") - } else if stripe.status == .active { - out.append("stripe .active") + ippPluginstatuses = { + var ippTags = [String]() + // Check Stripe plugin status + if let stripe = pluginResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.stripe_plugin_slug }) { + if stripe.status == .active { + ippTags.append(IPPPluginStatus.woo_mobile_stripe_installed_and_activated) + } else if stripe.status == .inactive { + ippTags.append(IPPPluginStatus.woo_mobile_stripe_installed_and_not_activated) } } else { - out.append("stripe .not installed") + ippTags.append(IPPPluginStatus.woo_mobile_stripe_not_installed) } - - if let wcpay = ippResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.wcpay_plugin_slug }) { - if wcpay.status == .inactive { - out.append("wcpay .inactive") - } else if wcpay.status == .active { - out.append("wcpay .active") + // Check WCPay plugin status + if let wcpay = pluginResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.wcpay_plugin_slug }) { + if wcpay.status == .active { + ippTags.append(IPPPluginStatus.woo_mobile_wcpay_installed_and_activated) + } else if wcpay.status == .inactive { + ippTags.append(IPPPluginStatus.woo_mobile_wcpay_installed_and_not_activated) } } else { - out.append("wcpay .not installed") + ippTags.append(IPPPluginStatus.woo_mobile_wcpay_not_installed) } - return out + return ippTags }() } From 96b123dce5001afe9beb398decfbf0d6647cc171 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 10:56:48 +0900 Subject: [PATCH 13/24] Move logic to ZendeskManager MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We’re moving the logic to retrieve IPP plugin statuses directly to ZenDesk, as if a merchant attempts to open a ticket without passing through the SettingsView, we wouldn’t have these available. --- .../Tools/Zendesk/ZendeskManager.swift | 67 +++++++++++++++++-- .../Settings/Settings/SettingsViewModel.swift | 42 ------------ 2 files changed, 63 insertions(+), 46 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 738e53f448b..4020fb6a0cf 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -137,6 +137,40 @@ struct ZendeskProvider { /// #if !targetEnvironment(macCatalyst) final class ZendeskManager: NSObject, ZendeskManagerProtocol { + /// Loads Plugins from the Storage Layer. + /// + private let pluginResultsController: ResultsController + + private let stores = ServiceLocator.stores + + private let storageManager = ServiceLocator.storageManager + + /// IPP plugin statuses + /// + private var ippPluginstatuses: [String]? { + var ippTags = [String]() + if let stripe = pluginResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.stripe_plugin_slug }) { + if stripe.status == .active { + ippTags.append(IPPPluginStatus.woo_mobile_stripe_installed_and_activated) + } else if stripe.status == .inactive { + ippTags.append(IPPPluginStatus.woo_mobile_stripe_installed_and_not_activated) + } + } else { + ippTags.append(IPPPluginStatus.woo_mobile_stripe_not_installed) + } + if let wcpay = pluginResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.wcpay_plugin_slug }) { + if wcpay.status == .active { + ippTags.append(IPPPluginStatus.woo_mobile_wcpay_installed_and_activated) + } else if wcpay.status == .inactive { + ippTags.append(IPPPluginStatus.woo_mobile_wcpay_installed_and_not_activated) + } + } + else { + ippTags.append(IPPPluginStatus.woo_mobile_wcpay_not_installed) + } + return ippTags + } + func showNewRequestIfPossible(from controller: UIViewController) { showNewRequestIfPossible(from: controller, with: nil) } @@ -186,10 +220,24 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { return ZDKPushProvider(zendesk: zendesk) } - /// Designated Initialier /// fileprivate override init() { + /// Initialize Plugins Results Controller + let sitePredicate: NSPredicate? + let pluginStatusDescriptor = [NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true)] + + if let siteID = stores.sessionManager.defaultSite?.siteID { + sitePredicate = NSPredicate(format: "siteID == %lld", siteID) + } else { + sitePredicate = nil + DDLogError("ZendeskManager: No siteID found when attempting to initialize Plugins Results predicate.") + } + pluginResultsController = ResultsController(storageManager: storageManager, + matching: sitePredicate, + sortedBy: pluginStatusDescriptor) + + super.init() observeZendeskNotifications() } @@ -328,9 +376,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { var tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] // Get IPP plugin statuses - if let ippTags = settingsViewModel.ippPluginstatuses { - tags.append(contentsOf: ippTags) - } + tags.append(contentsOf: ippPluginstatuses ?? []) return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } @@ -1072,6 +1118,19 @@ private extension ZendeskManager { } } +private extension ZendeskManager { + enum IPPPluginStatus { + static let stripe_plugin_slug = "woocommerce-gateway-stripe/woocommerce-gateway-stripe" + static let wcpay_plugin_slug = "woocommerce-payments/woocommerce-payments" + static let woo_mobile_stripe_not_installed = "woo_mobile_stripe_not_installed" + static let woo_mobile_stripe_installed_and_not_activated = "woo_mobile_stripe_installed_and_not_activated" + static let woo_mobile_stripe_installed_and_activated = "woo_mobile_stripe_installed_and_activated" + static let woo_mobile_wcpay_not_installed = "woo_mobile_wcpay_not_installed" + static let woo_mobile_wcpay_installed_and_not_activated = "woo_mobile_wcpay_installed_and_not_activated" + static let woo_mobile_wcpay_installed_and_activated = "woo_mobile_wcpay_installed_and_activated" + static let woo_mobile_site_plugins_fetching_error = "woo_mobile_site_plugins_fetching_error" + } +} // MARK: - UITextFieldDelegate // diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift index cb31ba523ff..ba2b16e5185 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift @@ -94,14 +94,6 @@ final class SettingsViewModel: SettingsViewModelOutput, SettingsViewModelActions /// private let sitesResultsController: ResultsController - /// Loads Plugins from the Storage Layer. - /// - private let pluginResultsController: ResultsController - - /// IPP plugin statuses - /// - private(set) var ippPluginstatuses: [String]? - /// Payment Gateway Accounts Results Controller: Loads Payment Gateway Accounts from the Storage Layer /// e.g. WooCommerce Payments, but eventually other in-person payment accounts too /// @@ -133,12 +125,6 @@ final class SettingsViewModel: SettingsViewModelOutput, SettingsViewModelActions matching: NSPredicate(format: "isWooCommerceActive == YES"), sortedBy: [NSSortDescriptor(key: "name", ascending: true)]) - /// Initialize Plugins Results Controller - /// - let pluginStatusDescriptor = [NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true)] - pluginResultsController = ResultsController(storageManager: storageManager, - sortedBy: pluginStatusDescriptor) - /// Initialize Payment Gateway Accounts Results Controller /// if let siteID = stores.sessionManager.defaultSite?.siteID { @@ -155,34 +141,6 @@ final class SettingsViewModel: SettingsViewModelOutput, SettingsViewModelActions let action = SystemStatusAction.synchronizeSystemPlugins(siteID: siteID, onCompletion: { _ in }) stores.dispatch(action) } - - /// - /// - ippPluginstatuses = { - var ippTags = [String]() - // Check Stripe plugin status - if let stripe = pluginResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.stripe_plugin_slug }) { - if stripe.status == .active { - ippTags.append(IPPPluginStatus.woo_mobile_stripe_installed_and_activated) - } else if stripe.status == .inactive { - ippTags.append(IPPPluginStatus.woo_mobile_stripe_installed_and_not_activated) - } - } else { - ippTags.append(IPPPluginStatus.woo_mobile_stripe_not_installed) - } - // Check WCPay plugin status - if let wcpay = pluginResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.wcpay_plugin_slug }) { - if wcpay.status == .active { - ippTags.append(IPPPluginStatus.woo_mobile_wcpay_installed_and_activated) - } else if wcpay.status == .inactive { - ippTags.append(IPPPluginStatus.woo_mobile_wcpay_installed_and_not_activated) - } - } - else { - ippTags.append(IPPPluginStatus.woo_mobile_wcpay_not_installed) - } - return ippTags - }() } /// Sets up the view model and loads the settings. From 9a1ae44d69d7f4bd509301cd3b40487d033a8f0a Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 10:58:19 +0900 Subject: [PATCH 14/24] Remove unnecessary variable --- WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift | 2 -- 1 file changed, 2 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 4020fb6a0cf..412a702f294 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -191,8 +191,6 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { } } - private lazy var settingsViewModel = SettingsViewModel() - private var unreadNotificationsCount = 0 var showSupportNotificationIndicator: Bool { From 849862e0e101050badcb6e53a96490ae3bc31dc8 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 14:18:10 +0900 Subject: [PATCH 15/24] Remove unused extension from SettingsViewModel --- .../Settings/Settings/SettingsViewModel.swift | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift index ba2b16e5185..cf5cac4d8cf 100644 --- a/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift +++ b/WooCommerce/Classes/ViewRelated/Dashboard/Settings/Settings/SettingsViewModel.swift @@ -361,17 +361,6 @@ private extension SettingsViewModel { // MARK: - Localizations // private extension SettingsViewModel { - enum IPPPluginStatus { - static let stripe_plugin_slug = "woocommerce-gateway-stripe/woocommerce-gateway-stripe" - static let wcpay_plugin_slug = "woocommerce-payments/woocommerce-payments" - static let woo_mobile_stripe_not_installed = "woo_mobile_stripe_not_installed" - static let woo_mobile_stripe_installed_and_not_activated = "woo_mobile_stripe_installed_and_not_activated" - static let woo_mobile_stripe_installed_and_activated = "woo_mobile_stripe_installed_and_activated" - static let woo_mobile_wcpay_not_installed = "woo_mobile_wcpay_not_installed" - static let woo_mobile_wcpay_installed_and_not_activated = "woo_mobile_wcpay_installed_and_not_activated" - static let woo_mobile_wcpay_installed_and_activated = "woo_mobile_wcpay_installed_and_activated" - static let woo_mobile_site_plugins_fetching_error = "woo_mobile_site_plugins_fetching_error" - } enum Localization { static let pluginsTitle = NSLocalizedString( "Plugins", From 10fcac66cd9bf1beea2b6ed879fdb4a7b913ab87 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 14:58:32 +0900 Subject: [PATCH 16/24] Make enum cases snakecase and split them --- .../Tools/Zendesk/ZendeskManager.swift | 41 ++++++++++--------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 412a702f294..192a8811f7b 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -148,27 +148,27 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// IPP plugin statuses /// private var ippPluginstatuses: [String]? { - var ippTags = [String]() - if let stripe = pluginResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.stripe_plugin_slug }) { + var ippTags = [PluginStatus]() + if let stripe = pluginResultsController.fetchedObjects.first(where: { $0.plugin == PluginSlug.stripe }) { if stripe.status == .active { - ippTags.append(IPPPluginStatus.woo_mobile_stripe_installed_and_activated) + ippTags.append(.stripeInstalledAndActivated) } else if stripe.status == .inactive { - ippTags.append(IPPPluginStatus.woo_mobile_stripe_installed_and_not_activated) + ippTags.append(.stripeInstalledButNotActivated) } } else { - ippTags.append(IPPPluginStatus.woo_mobile_stripe_not_installed) + ippTags.append(.stripeNotInstalled) } - if let wcpay = pluginResultsController.fetchedObjects.first(where: { $0.plugin == IPPPluginStatus.wcpay_plugin_slug }) { + if let wcpay = pluginResultsController.fetchedObjects.first(where: { $0.plugin == PluginSlug.wcpay }) { if wcpay.status == .active { - ippTags.append(IPPPluginStatus.woo_mobile_wcpay_installed_and_activated) + ippTags.append(.wcpayInstalledAndActivated) } else if wcpay.status == .inactive { - ippTags.append(IPPPluginStatus.woo_mobile_wcpay_installed_and_not_activated) + ippTags.append(.wcpayInstalledButNotActivated) } } else { - ippTags.append(IPPPluginStatus.woo_mobile_wcpay_not_installed) + ippTags.append(.wcpayNotInstalled) } - return ippTags + return ippTags.map{ $0.rawValue } } func showNewRequestIfPossible(from controller: UIViewController) { @@ -1117,16 +1117,17 @@ private extension ZendeskManager { } private extension ZendeskManager { - enum IPPPluginStatus { - static let stripe_plugin_slug = "woocommerce-gateway-stripe/woocommerce-gateway-stripe" - static let wcpay_plugin_slug = "woocommerce-payments/woocommerce-payments" - static let woo_mobile_stripe_not_installed = "woo_mobile_stripe_not_installed" - static let woo_mobile_stripe_installed_and_not_activated = "woo_mobile_stripe_installed_and_not_activated" - static let woo_mobile_stripe_installed_and_activated = "woo_mobile_stripe_installed_and_activated" - static let woo_mobile_wcpay_not_installed = "woo_mobile_wcpay_not_installed" - static let woo_mobile_wcpay_installed_and_not_activated = "woo_mobile_wcpay_installed_and_not_activated" - static let woo_mobile_wcpay_installed_and_activated = "woo_mobile_wcpay_installed_and_activated" - static let woo_mobile_site_plugins_fetching_error = "woo_mobile_site_plugins_fetching_error" + enum PluginSlug { + static let stripe = "woocommerce-gateway-stripe/woocommerce-gateway-stripe" + static let wcpay = "woocommerce-payments/woocommerce-payments" + } + enum PluginStatus: String { + case stripeNotInstalled = "woo_mobile_stripe_not_installed" + case stripeInstalledAndActivated = "woo_mobile_stripe_installed_and_activated" + case stripeInstalledButNotActivated = "woo_mobile_stripe_installed_and_not_activated" + case wcpayNotInstalled = "woo_mobile_wcpay_not_installed" + case wcpayInstalledAndActivated = "woo_mobile_wcpay_installed_and_activated" + case wcpayInstalledButNotActivated = "woo_mobile_wcpay_installed_and_not_activated" } } From c36468978777c5137a019484e90ea3e7ab561ed7 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 15:00:52 +0900 Subject: [PATCH 17/24] Make ippPluginstatuses non-optional --- WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 192a8811f7b..27ec1953bc2 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -147,7 +147,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// IPP plugin statuses /// - private var ippPluginstatuses: [String]? { + private var ippPluginstatuses: [String] { var ippTags = [PluginStatus]() if let stripe = pluginResultsController.fetchedObjects.first(where: { $0.plugin == PluginSlug.stripe }) { if stripe.status == .active { @@ -371,11 +371,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// The SDK tag is used in a trigger and displays tickets in Woo > Mobile Apps New. /// func getTags(supportSourceTag: String?) -> [String] { - var tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] - - // Get IPP plugin statuses - tags.append(contentsOf: ippPluginstatuses ?? []) - + var tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] + ippPluginstatuses return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } From 16affe860cb462d2e602e315ff5a4674411361aa Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 15:04:59 +0900 Subject: [PATCH 18/24] Fix opening brace violation --- WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 27ec1953bc2..b0392d16f3a 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -168,7 +168,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { else { ippTags.append(.wcpayNotInstalled) } - return ippTags.map{ $0.rawValue } + return ippTags.map { $0.rawValue } } func showNewRequestIfPossible(from controller: UIViewController) { From 37b95b58bed2ffbe8e054a7c66cf62b1ba0ef2a6 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 15:43:18 +0900 Subject: [PATCH 19/24] Move ResultsController outside of ZendeskManager init As ZendeskManager is initialized only once, moving the ResultsController outside of the init allows for the siteID to be recalculated when we switch stores. --- .../Tools/Zendesk/ZendeskManager.swift | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index b0392d16f3a..9f0fbc6e17f 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -137,13 +137,25 @@ struct ZendeskProvider { /// #if !targetEnvironment(macCatalyst) final class ZendeskManager: NSObject, ZendeskManagerProtocol { + private let stores = ServiceLocator.stores + private let storageManager = ServiceLocator.storageManager + /// Loads Plugins from the Storage Layer. /// - private let pluginResultsController: ResultsController + private var pluginResultsController: ResultsController { + var sitePredicate: NSPredicate? = nil + if let siteID = stores.sessionManager.defaultSite?.siteID { + sitePredicate = NSPredicate(format: "siteID == %lld", siteID) + } else { + DDLogError("ZendeskManager: No siteID found when attempting to initialize Plugins Results predicate.") + } - private let stores = ServiceLocator.stores + let pluginStatusDescriptor = [NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true)] - private let storageManager = ServiceLocator.storageManager + return ResultsController(storageManager: storageManager, + matching: sitePredicate, + sortedBy: pluginStatusDescriptor) + } /// IPP plugin statuses /// @@ -221,21 +233,6 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// Designated Initialier /// fileprivate override init() { - /// Initialize Plugins Results Controller - let sitePredicate: NSPredicate? - let pluginStatusDescriptor = [NSSortDescriptor(keyPath: \StorageSitePlugin.status, ascending: true)] - - if let siteID = stores.sessionManager.defaultSite?.siteID { - sitePredicate = NSPredicate(format: "siteID == %lld", siteID) - } else { - sitePredicate = nil - DDLogError("ZendeskManager: No siteID found when attempting to initialize Plugins Results predicate.") - } - pluginResultsController = ResultsController(storageManager: storageManager, - matching: sitePredicate, - sortedBy: pluginStatusDescriptor) - - super.init() observeZendeskNotifications() } From f82b2c9b7650c7cfaf87465bfb0cb6cd0a0fe620 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 17:40:16 +0900 Subject: [PATCH 20/24] Access ZD shared from SwitchStore --- .../Epilogue/SwitchStoreUseCase.swift | 5 ++++- .../Classes/Tools/Zendesk/ZendeskManager.swift | 17 ++++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-) diff --git a/WooCommerce/Classes/Authentication/Epilogue/SwitchStoreUseCase.swift b/WooCommerce/Classes/Authentication/Epilogue/SwitchStoreUseCase.swift index 67f25b5b12f..a6ebe85bcf5 100644 --- a/WooCommerce/Classes/Authentication/Epilogue/SwitchStoreUseCase.swift +++ b/WooCommerce/Classes/Authentication/Epilogue/SwitchStoreUseCase.swift @@ -12,6 +12,7 @@ final class SwitchStoreUseCase: SwitchStoreUseCaseProtocol { private let stores: StoresManager private let storageManager: StorageManagerType + private let ZendeskShared: ZendeskManagerProtocol = ZendeskProvider.shared private lazy var resultsController: ResultsController = { return ResultsController(storageManager: storageManager, sortedBy: []) @@ -72,7 +73,9 @@ final class SwitchStoreUseCase: SwitchStoreUseCaseProtocol { // https://github.com/woocommerce/woocommerce-ios/pull/2013#discussion_r454620804 logOutOfCurrentStore { self.finalizeStoreSelection(storeID) - + // Inform ZD that the site has changed + // https://github.com/woocommerce/woocommerce-ios/pull/8008/ + self.ZendeskShared.test_listenToSiteSwitchChanges() onCompletion(true) } } diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 9f0fbc6e17f..e027832947d 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -22,6 +22,8 @@ extension NSNotification.Name { protocol ZendeskManagerProtocol: SupportManagerAdapter { typealias onUserInformationCompletion = (_ success: Bool, _ email: String?) -> Void + func test_listenToSiteSwitchChanges() + /// Displays the Zendesk New Request view from the given controller, for users to submit new tickets. /// func showNewRequestIfPossible(from controller: UIViewController, with sourceTag: String?) @@ -44,6 +46,10 @@ protocol ZendeskManagerProtocol: SupportManagerAdapter { } struct NoZendeskManager: ZendeskManagerProtocol { + func test_listenToSiteSwitchChanges() { + // no-op + } + func showNewRequestIfPossible(from controller: UIViewController) { // no-op } @@ -157,6 +163,15 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { sortedBy: pluginStatusDescriptor) } + func test_listenToSiteSwitchChanges() { + print("Changed! SiteID: ") + do { + try pluginResultsController.performFetch() + } catch { + DDLogError(":(") + } + } + /// IPP plugin statuses /// private var ippPluginstatuses: [String] { @@ -368,7 +383,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// The SDK tag is used in a trigger and displays tickets in Woo > Mobile Apps New. /// func getTags(supportSourceTag: String?) -> [String] { - var tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] + ippPluginstatuses + let tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] + ippPluginstatuses return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } From e88a7a374ecb0363e8625e2ef99514979d829a52 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 18:28:35 +0900 Subject: [PATCH 21/24] Make pluginResultsController lazy --- .../Epilogue/SwitchStoreUseCase.swift | 6 +++--- .../Classes/Tools/Zendesk/ZendeskManager.swift | 15 +++++++++------ 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/WooCommerce/Classes/Authentication/Epilogue/SwitchStoreUseCase.swift b/WooCommerce/Classes/Authentication/Epilogue/SwitchStoreUseCase.swift index a6ebe85bcf5..405ac54aadd 100644 --- a/WooCommerce/Classes/Authentication/Epilogue/SwitchStoreUseCase.swift +++ b/WooCommerce/Classes/Authentication/Epilogue/SwitchStoreUseCase.swift @@ -12,7 +12,7 @@ final class SwitchStoreUseCase: SwitchStoreUseCaseProtocol { private let stores: StoresManager private let storageManager: StorageManagerType - private let ZendeskShared: ZendeskManagerProtocol = ZendeskProvider.shared + private let zendeskShared: ZendeskManagerProtocol = ZendeskProvider.shared private lazy var resultsController: ResultsController = { return ResultsController(storageManager: storageManager, sortedBy: []) @@ -73,9 +73,9 @@ final class SwitchStoreUseCase: SwitchStoreUseCaseProtocol { // https://github.com/woocommerce/woocommerce-ios/pull/2013#discussion_r454620804 logOutOfCurrentStore { self.finalizeStoreSelection(storeID) - // Inform ZD that the site has changed + // Inform the Zendesk shared instance that the Store has been switched // https://github.com/woocommerce/woocommerce-ios/pull/8008/ - self.ZendeskShared.test_listenToSiteSwitchChanges() + self.zendeskShared.observeStoreSwitch() onCompletion(true) } } diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index e027832947d..f0c6587f94e 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -22,7 +22,7 @@ extension NSNotification.Name { protocol ZendeskManagerProtocol: SupportManagerAdapter { typealias onUserInformationCompletion = (_ success: Bool, _ email: String?) -> Void - func test_listenToSiteSwitchChanges() + func observeStoreSwitch() /// Displays the Zendesk New Request view from the given controller, for users to submit new tickets. /// @@ -46,7 +46,7 @@ protocol ZendeskManagerProtocol: SupportManagerAdapter { } struct NoZendeskManager: ZendeskManagerProtocol { - func test_listenToSiteSwitchChanges() { + func observeStoreSwitch() { // no-op } @@ -148,7 +148,9 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// Loads Plugins from the Storage Layer. /// - private var pluginResultsController: ResultsController { + private lazy var pluginResultsController: ResultsController = updatePluginResultsController() + + private func updatePluginResultsController() -> ResultsController { var sitePredicate: NSPredicate? = nil if let siteID = stores.sessionManager.defaultSite?.siteID { sitePredicate = NSPredicate(format: "siteID == %lld", siteID) @@ -163,12 +165,12 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { sortedBy: pluginStatusDescriptor) } - func test_listenToSiteSwitchChanges() { - print("Changed! SiteID: ") + func observeStoreSwitch() { + pluginResultsController = updatePluginResultsController() do { try pluginResultsController.performFetch() } catch { - DDLogError(":(") + DDLogError("ZendeskManager: Unable to update plugin results") } } @@ -249,6 +251,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// fileprivate override init() { super.init() + try? pluginResultsController.performFetch() observeZendeskNotifications() } From dca42e539dba2978b064ca1fd2e96aab7cf1c602 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Wed, 9 Nov 2022 23:12:24 +0900 Subject: [PATCH 22/24] Add missing method to MockZendeskManager --- WooCommerce/WooCommerceTests/Testing/MockZendeskManager.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/WooCommerce/WooCommerceTests/Testing/MockZendeskManager.swift b/WooCommerce/WooCommerceTests/Testing/MockZendeskManager.swift index 102b8d0d749..e3832c51db4 100644 --- a/WooCommerce/WooCommerceTests/Testing/MockZendeskManager.swift +++ b/WooCommerce/WooCommerceTests/Testing/MockZendeskManager.swift @@ -67,6 +67,10 @@ final class MockZendeskManager: ZendeskManagerProtocol { func reset() { // no-op } + + func observeStoreSwitch() { + // no-op + } } extension MockZendeskManager: SupportManagerAdapter { From 998499687560bf9c8621894c548b5e14208d4ba0 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 10 Nov 2022 11:55:09 +0900 Subject: [PATCH 23/24] Rename method for clarity. Typo. --- .../Classes/Tools/Zendesk/ZendeskManager.swift | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index f0c6587f94e..3ab04c01d54 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -146,11 +146,13 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { private let stores = ServiceLocator.stores private let storageManager = ServiceLocator.storageManager - /// Loads Plugins from the Storage Layer. + /// Controller for fetching site plugins from Storage /// - private lazy var pluginResultsController: ResultsController = updatePluginResultsController() - - private func updatePluginResultsController() -> ResultsController { + private lazy var pluginResultsController: ResultsController = createPluginResultsController() + + /// Returns a `pluginResultsController` using the latest selected site ID for predicate + /// + private func createPluginResultsController() -> ResultsController { var sitePredicate: NSPredicate? = nil if let siteID = stores.sessionManager.defaultSite?.siteID { sitePredicate = NSPredicate(format: "siteID == %lld", siteID) @@ -166,7 +168,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { } func observeStoreSwitch() { - pluginResultsController = updatePluginResultsController() + pluginResultsController = createPluginResultsController() do { try pluginResultsController.performFetch() } catch { @@ -174,9 +176,9 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { } } - /// IPP plugin statuses + /// List of tags that reflect Stripe and WCPay plugin statuses /// - private var ippPluginstatuses: [String] { + private var ippPluginStatuses: [String] { var ippTags = [PluginStatus]() if let stripe = pluginResultsController.fetchedObjects.first(where: { $0.plugin == PluginSlug.stripe }) { if stripe.status == .active { @@ -386,7 +388,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// The SDK tag is used in a trigger and displays tickets in Woo > Mobile Apps New. /// func getTags(supportSourceTag: String?) -> [String] { - let tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] + ippPluginstatuses + let tags = [Constants.platformTag, Constants.sdkTag, Constants.jetpackTag] + ippPluginStatuses return decorateTags(tags: tags, supportSourceTag: supportSourceTag) } From d341fc524afb05ca1f481ffb881f39d50130b256 Mon Sep 17 00:00:00 2001 From: iamgabrielma Date: Thu, 10 Nov 2022 11:57:32 +0900 Subject: [PATCH 24/24] Remove trailing whitespace --- WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift index 3ab04c01d54..f4b7cac87ee 100644 --- a/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift +++ b/WooCommerce/Classes/Tools/Zendesk/ZendeskManager.swift @@ -149,7 +149,7 @@ final class ZendeskManager: NSObject, ZendeskManagerProtocol { /// Controller for fetching site plugins from Storage /// private lazy var pluginResultsController: ResultsController = createPluginResultsController() - + /// Returns a `pluginResultsController` using the latest selected site ID for predicate /// private func createPluginResultsController() -> ResultsController {