Skip to content

Commit ac3c3ac

Browse files
Merge pull request #7553 from woocommerce/feat/7547-enter-store-address-help-page
Custom help center content for "Enter Store Address" screen
2 parents bdc0b42 + 4178453 commit ac3c3ac

File tree

9 files changed

+180
-17
lines changed

9 files changed

+180
-17
lines changed

Podfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ target 'WooCommerce' do
4242
pod 'Gridicons', '~> 1.2.0'
4343

4444
# To allow pod to pick up beta versions use -beta. E.g., 1.1.7-beta.1
45-
pod 'WordPressAuthenticator', '~> 2.3.0'
45+
pod 'WordPressAuthenticator', '~> 2.4.0-beta.1'
4646
# pod 'WordPressAuthenticator', :git => 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', :commit => ''
4747
# pod 'WordPressAuthenticator', :git => 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', :branch => ''
4848
# pod 'WordPressAuthenticator', :path => '../WordPressAuthenticator-iOS'

Podfile.lock

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ PODS:
4242
- WordPress-Aztec-iOS (1.11.0)
4343
- WordPress-Editor-iOS (1.11.0):
4444
- WordPress-Aztec-iOS (= 1.11.0)
45-
- WordPressAuthenticator (2.3.0):
45+
- WordPressAuthenticator (2.4.0-beta.1):
4646
- Alamofire (~> 4.8)
4747
- CocoaLumberjack (~> 3.5)
4848
- GoogleSignIn (~> 6.0.1)
@@ -92,7 +92,7 @@ DEPENDENCIES:
9292
- Sourcery (~> 1.0.3)
9393
- StripeTerminal (~> 2.7)
9494
- WordPress-Editor-iOS (~> 1.11.0)
95-
- WordPressAuthenticator (~> 2.3.0)
95+
- WordPressAuthenticator (~> 2.4.0-beta.1)
9696
- WordPressKit (~> 4.49.0)
9797
- WordPressShared (~> 1.15)
9898
- WordPressUI (~> 1.12.5)
@@ -163,7 +163,7 @@ SPEC CHECKSUMS:
163163
UIDeviceIdentifier: af4e11e25a2ea670078e2bd677bb0e8144f9f063
164164
WordPress-Aztec-iOS: 050b34d4c3adfb7c60363849049b13d60683b348
165165
WordPress-Editor-iOS: 304098424f1051cb271546c99f906aac296b1b81
166-
WordPressAuthenticator: df55cd04a8157fa38b2e8c7c9cb28ab0a82d00a8
166+
WordPressAuthenticator: 2f32568a4af71b5b464f65706ac64040e2e7775b
167167
WordPressKit: 96deb6ba37ea5eaec4ddcaa53eca04d653246152
168168
WordPressShared: 5477f179c7fe03b5d574f91adda66f67d131827e
169169
WordPressUI: c5be816f6c7b3392224ac21de9e521e89fa108ac
@@ -179,6 +179,6 @@ SPEC CHECKSUMS:
179179
ZendeskSupportProvidersSDK: 2bdf8544f7cd0fd4c002546f5704b813845beb2a
180180
ZendeskSupportSDK: 3a8e508ab1d9dd22dc038df6c694466414e037ba
181181

182-
PODFILE CHECKSUM: 8c1958091efafb7741ffe41719ea753dafe38041
182+
PODFILE CHECKSUM: 87786ee269bb59fb815d859df9cbe54bb00dac3d
183183

184184
COCOAPODS: 1.11.2

RELEASE-NOTES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
10.1
44
-----
55
- [*] In-Person Payments: The onboarding notice on the In-Person Payments menu is correctly dismissed after multiple prompts are shown. [https://github.com/woocommerce/woocommerce-ios/pull/7543]
6+
- [*] Help center: Added custom help center web page with FAQs for "Enter Store Address" screen. [https://github.com/woocommerce/woocommerce-ios/pull/7553]
67
- [*] In-Person Payments: The plugin selection is saved correctly after multiple onboarding prompts. [https://github.com/woocommerce/woocommerce-ios/pull/7544]
78

89
10.0

WooCommerce/Classes/Authentication/AuthenticationManager.swift

Lines changed: 44 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -379,17 +379,27 @@ extension AuthenticationManager: WordPressAuthenticatorDelegate {
379379
/// Presents the Support Interface from a given ViewController, with a specified SourceTag.
380380
///
381381
func presentSupport(from sourceViewController: UIViewController, sourceTag: WordPressSupportSourceTag) {
382-
let identifier = HelpAndSupportViewController.classNameWithoutNamespaces
383-
guard let supportViewController = UIStoryboard.dashboard.instantiateViewController(withIdentifier: identifier) as? HelpAndSupportViewController else {
382+
presentSupport(from: sourceViewController)
383+
}
384+
385+
/// Presents the Support Interface from a given ViewController.
386+
///
387+
/// - Parameters:
388+
/// - from: ViewController from which to present the support interface from
389+
/// - sourceTag: Support source tag of the view controller.
390+
/// - lastStep: Last `Step` tracked in `AuthenticatorAnalyticsTracker`
391+
/// - lastFlow: Last `Flow` tracked in `AuthenticatorAnalyticsTracker`
392+
///
393+
func presentSupport(from sourceViewController: UIViewController,
394+
sourceTag: WordPressSupportSourceTag,
395+
lastStep: AuthenticatorAnalyticsTracker.Step,
396+
lastFlow: AuthenticatorAnalyticsTracker.Flow) {
397+
guard let customHelpCenterContent = CustomHelpCenterContent(step: lastStep, flow: lastFlow) else {
398+
presentSupport(from: sourceViewController)
384399
return
385400
}
386401

387-
supportViewController.displaysDismissAction = true
388-
389-
let navController = WooNavigationController(rootViewController: supportViewController)
390-
navController.modalPresentationStyle = .formSheet
391-
392-
sourceViewController.present(navController, animated: true, completion: nil)
402+
presentSupport(from: sourceViewController, customHelpCenterContent: customHelpCenterContent)
393403
}
394404

395405
/// Presents the Support new request, from a given ViewController, with a specified SourceTag.
@@ -725,3 +735,29 @@ private extension AuthenticationManager {
725735
return wooAuthError != .unknown
726736
}
727737
}
738+
739+
// MARK: - Help and support helpers
740+
private extension AuthenticationManager {
741+
742+
func presentSupport(from sourceViewController: UIViewController,
743+
customHelpCenterContent: CustomHelpCenterContent? = nil) {
744+
let identifier = HelpAndSupportViewController.classNameWithoutNamespaces
745+
let supportViewController = UIStoryboard.dashboard.instantiateViewController(identifier: identifier,
746+
creator: { coder -> HelpAndSupportViewController? in
747+
guard let customHelpCenterContent = customHelpCenterContent else {
748+
/// Returning nil as we don't need to customise the HelpAndSupportViewController
749+
/// In this case `instantiateViewController` method will use the default `HelpAndSupportViewController` created from storyboard.
750+
///
751+
return nil
752+
}
753+
754+
return HelpAndSupportViewController(customHelpCenterContent: customHelpCenterContent, coder: coder)
755+
})
756+
supportViewController.displaysDismissAction = true
757+
758+
let navController = WooNavigationController(rootViewController: supportViewController)
759+
navController.modalPresentationStyle = .formSheet
760+
761+
sourceViewController.present(navController, animated: true, completion: nil)
762+
}
763+
}
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
import Foundation
2+
import WordPressAuthenticator
3+
4+
/// For holding the custom help center content URL
5+
/// and analytics tracking values
6+
///
7+
struct CustomHelpCenterContent {
8+
/// Custom help center web page's URL
9+
///
10+
let url: URL
11+
12+
/// Provides a dictionary for analytics tracking
13+
///
14+
let trackingProperties: [String: String]
15+
}
16+
17+
extension CustomHelpCenterContent {
18+
/// Used for tracking analytics events
19+
///
20+
enum Key: String {
21+
case step = "source_step"
22+
case flow = "source_flow"
23+
case url = "help_content_url"
24+
}
25+
26+
/// Initializes a `CustomHelpCenterContent` instance using `Step` and `Flow` from `AuthenticatorAnalyticsTracker`
27+
///
28+
init?(step: AuthenticatorAnalyticsTracker.Step, flow: AuthenticatorAnalyticsTracker.Flow) {
29+
switch step {
30+
case .start where flow == .loginWithSiteAddress:
31+
url = WooConstants.URLs.helpCenterForEnterStoreAddress.asURL()
32+
default:
33+
return nil
34+
}
35+
36+
trackingProperties = [
37+
Key.step.rawValue: step.rawValue,
38+
Key.flow.rawValue: flow.rawValue,
39+
Key.url.rawValue: url.absoluteString
40+
]
41+
}
42+
}

WooCommerce/Classes/System/WooConstants.swift

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,10 @@ extension WooConstants {
7777
///
7878
case helpCenter = "https://docs.woocommerce.com/document/woocommerce-ios/"
7979

80+
/// Help Center for "Enter your Store Address" screen
81+
///
82+
case helpCenterForEnterStoreAddress = "https://woocommerce.com/document/android-ios-apps-login-help-faq/#enter-store-address"
83+
8084
/// URL used for Learn More button in Orders empty state.
8185
///
8286
case blog = "https://woocommerce.com/blog/"

WooCommerce/Classes/ViewRelated/Dashboard/Settings/Help/HelpAndSupportViewController.swift

Lines changed: 30 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,13 @@
11
import UIKit
22
import Yosemite
33

4-
54
// MARK: - HelpAndSupportViewController
65
//
7-
class HelpAndSupportViewController: UIViewController {
6+
final class HelpAndSupportViewController: UIViewController {
87

98
/// Main TableView
109
///
11-
@IBOutlet weak var tableView: UITableView!
10+
@IBOutlet private weak var tableView: UITableView!
1211

1312
/// Table Sections to be rendered
1413
///
@@ -57,6 +56,20 @@ class HelpAndSupportViewController: UIViewController {
5756
///
5857
var displaysDismissAction = false
5958

59+
/// Custom help center web page related properties
60+
/// If non-nil this web page is launched instead of Zendesk
61+
///
62+
private let customHelpCenterContent: CustomHelpCenterContent?
63+
64+
init?(customHelpCenterContent: CustomHelpCenterContent, coder: NSCoder) {
65+
self.customHelpCenterContent = customHelpCenterContent
66+
super.init(coder: coder)
67+
}
68+
69+
required init?(coder: NSCoder) {
70+
self.customHelpCenterContent = nil
71+
super.init(coder: coder)
72+
}
6073

6174
// MARK: - Overridden Methods
6275
//
@@ -296,6 +309,15 @@ private extension HelpAndSupportViewController {
296309
func rowAtIndexPath(_ indexPath: IndexPath) -> Row {
297310
return sections[indexPath.section].rows[indexPath.row]
298311
}
312+
313+
/// Opens custom help center URL in a web view
314+
///
315+
func launchCustomHelpCenterWebPage(_ customHelpCenterContent: CustomHelpCenterContent) {
316+
WebviewHelper.launch(customHelpCenterContent.url, with: self)
317+
318+
ServiceLocator.analytics.track(.supportHelpCenterViewed,
319+
withProperties: customHelpCenterContent.trackingProperties)
320+
}
299321
}
300322

301323
// MARK: - Actions
@@ -305,7 +327,11 @@ private extension HelpAndSupportViewController {
305327
/// Help Center action
306328
///
307329
func helpCenterWasPressed() {
308-
ZendeskProvider.shared.showHelpCenter(from: self)
330+
if let customHelpCenterContent = customHelpCenterContent {
331+
launchCustomHelpCenterWebPage(customHelpCenterContent)
332+
} else {
333+
ZendeskProvider.shared.showHelpCenter(from: self)
334+
}
309335
}
310336

311337
/// Contact Support action

WooCommerce/WooCommerce.xcodeproj/project.pbxproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1767,6 +1767,8 @@
17671767
E1E636BB26FB467A00C9D0D7 /* Comparable+Woo.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1E636BA26FB467A00C9D0D7 /* Comparable+Woo.swift */; };
17681768
E1ED16E4266E10A10037B8DB /* ApplicationLogViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1ED16E3266E10A10037B8DB /* ApplicationLogViewModel.swift */; };
17691769
E1F52DC62668E03B00349D75 /* CardPresentModalBluetoothRequired.swift in Sources */ = {isa = PBXBuildFile; fileRef = E1F52DC52668E03B00349D75 /* CardPresentModalBluetoothRequired.swift */; };
1770+
EE0EE7A628B7415200F6061E /* CustomHelpCenterContent.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0EE7A528B7415200F6061E /* CustomHelpCenterContent.swift */; };
1771+
EE0EE7A828B74EF300F6061E /* CustomHelpCenterContentTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE0EE7A728B74EF300F6061E /* CustomHelpCenterContentTests.swift */; };
17701772
EE81B1382865BB0B0032E0D4 /* ProductImagesProductIDUpdaterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EE81B1372865BB0B0032E0D4 /* ProductImagesProductIDUpdaterTests.swift */; };
17711773
EEADF622281A40CB001B40F1 /* ShippingValueLocalizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEADF621281A40CB001B40F1 /* ShippingValueLocalizer.swift */; };
17721774
EEADF624281A421A001B40F1 /* DefaultShippingValueLocalizer.swift in Sources */ = {isa = PBXBuildFile; fileRef = EEADF623281A421A001B40F1 /* DefaultShippingValueLocalizer.swift */; };
@@ -3629,6 +3631,8 @@
36293631
E1E636BA26FB467A00C9D0D7 /* Comparable+Woo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "Comparable+Woo.swift"; sourceTree = "<group>"; };
36303632
E1ED16E3266E10A10037B8DB /* ApplicationLogViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ApplicationLogViewModel.swift; sourceTree = "<group>"; };
36313633
E1F52DC52668E03B00349D75 /* CardPresentModalBluetoothRequired.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CardPresentModalBluetoothRequired.swift; sourceTree = "<group>"; };
3634+
EE0EE7A528B7415200F6061E /* CustomHelpCenterContent.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomHelpCenterContent.swift; sourceTree = "<group>"; };
3635+
EE0EE7A728B74EF300F6061E /* CustomHelpCenterContentTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CustomHelpCenterContentTests.swift; sourceTree = "<group>"; };
36323636
EE81B1372865BB0B0032E0D4 /* ProductImagesProductIDUpdaterTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ProductImagesProductIDUpdaterTests.swift; sourceTree = "<group>"; };
36333637
EEADF621281A40CB001B40F1 /* ShippingValueLocalizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ShippingValueLocalizer.swift; sourceTree = "<group>"; };
36343638
EEADF623281A421A001B40F1 /* DefaultShippingValueLocalizer.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DefaultShippingValueLocalizer.swift; sourceTree = "<group>"; };
@@ -6685,6 +6689,7 @@
66856689
DE77889926FD7EF0008DFF44 /* ShippingLabelPackageItem.swift */,
66866690
DEF3300B270444060073AE29 /* ShippingLabelSelectedRate.swift */,
66876691
DECE13FF279A595200816ECD /* Coupon+Woo.swift */,
6692+
EE0EE7A528B7415200F6061E /* CustomHelpCenterContent.swift */,
66886693
);
66896694
path = Model;
66906695
sourceTree = "<group>";
@@ -6896,6 +6901,7 @@
68966901
455A2FDA246B1349000CA72C /* ProductVisibilityTests.swift */,
68976902
FEEB2F60268A215E0075A6E0 /* StorageEligibilityErrorInfoWooTests.swift */,
68986903
DE001322279A793A00EB0350 /* CouponWooTests.swift */,
6904+
EE0EE7A728B74EF300F6061E /* CustomHelpCenterContentTests.swift */,
68996905
);
69006906
path = Model;
69016907
sourceTree = "<group>";
@@ -9626,6 +9632,7 @@
96269632
B958A7CD28B3DD9100823EEF /* OrderDetailsRoute.swift in Sources */,
96279633
45DB7040261209B10064A6CF /* ItemToFulfillRow.swift in Sources */,
96289634
02564A8C246CE38E00D6DB2A /* SwappableSubviewContainerView.swift in Sources */,
9635+
EE0EE7A628B7415200F6061E /* CustomHelpCenterContent.swift in Sources */,
96299636
023453F22579DA1A00A6BB20 /* ShippingLabelPrintingInstructionsViewController.swift in Sources */,
96309637
024DF31223742B18006658FE /* AztecItalicFormatBarCommand.swift in Sources */,
96319638
02AAD54525023A8300BA1E26 /* ProductFormRemoteActionUseCase.swift in Sources */,
@@ -10280,6 +10287,7 @@
1028010287
D8610BF7256F5F0900A5DF27 /* ULErrorViewControllerTests.swift in Sources */,
1028110288
02279594237A60FD00787C63 /* AztecHeaderFormatBarCommandTests.swift in Sources */,
1028210289
0259EF77246BF4EC00B84FDF /* ProductDetailsFactoryTests.swift in Sources */,
10290+
EE0EE7A828B74EF300F6061E /* CustomHelpCenterContentTests.swift in Sources */,
1028310291
4574745F24EA9ADE00CF49BC /* ProductTypeBottomSheetListSelectorCommandTests.swift in Sources */,
1028410292
AEE2611126E6785400B142A0 /* EditOrderAddressFormViewModelTests.swift in Sources */,
1028510293
0212683724C049F000F8A892 /* ProductListMultiSelectorDataSourceTests.swift in Sources */,
Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
import XCTest
2+
@testable import WordPressAuthenticator
3+
@testable import WooCommerce
4+
5+
final class CustomHelpCenterContentTests: XCTestCase {
6+
7+
func test_step_key_has_correct_rawValue() {
8+
let sut = CustomHelpCenterContent.Key.step
9+
XCTAssertEqual(sut.rawValue, "source_step")
10+
}
11+
12+
func test_flow_key_has_correct_rawValue() {
13+
let sut = CustomHelpCenterContent.Key.flow
14+
XCTAssertEqual(sut.rawValue, "source_flow")
15+
}
16+
17+
func test_url_key_has_correct_rawValue() {
18+
let sut = CustomHelpCenterContent.Key.url
19+
XCTAssertEqual(sut.rawValue, "help_content_url")
20+
}
21+
22+
func test_init_using_step_and_flow_returns_valid_instance_for_enter_store_address_screen() throws {
23+
// Given
24+
let step: AuthenticatorAnalyticsTracker.Step = .start
25+
let flow: AuthenticatorAnalyticsTracker.Flow = .loginWithSiteAddress
26+
let helpContentURL = WooConstants.URLs.helpCenterForEnterStoreAddress.asURL()
27+
28+
// When
29+
let sut = try XCTUnwrap(CustomHelpCenterContent(step: step, flow: flow))
30+
31+
// Then
32+
XCTAssertEqual(sut.url, helpContentURL)
33+
34+
// Test the `trackingProperties` dictionary values
35+
XCTAssertEqual(sut.trackingProperties[CustomHelpCenterContent.Key.step.rawValue], step.rawValue)
36+
XCTAssertEqual(sut.trackingProperties[CustomHelpCenterContent.Key.flow.rawValue], flow.rawValue)
37+
XCTAssertEqual(sut.trackingProperties[CustomHelpCenterContent.Key.url.rawValue], helpContentURL.absoluteString)
38+
}
39+
40+
func test_init_using_invalid_step_and_flow_returns_nil() {
41+
let step: AuthenticatorAnalyticsTracker.Step = .magicLinkRequested
42+
let flow: AuthenticatorAnalyticsTracker.Flow = .prologue
43+
44+
XCTAssertNil(CustomHelpCenterContent(step: step, flow: flow))
45+
}
46+
}

0 commit comments

Comments
 (0)