Skip to content

Commit c703aed

Browse files
authored
Merge pull request #7748 from woocommerce/issue/7745-account-mismatch-login-site-credentials
Login: Handle Jetpack connection for WP.com login
2 parents 7986122 + 2980bf2 commit c703aed

12 files changed

+544
-90
lines changed

Podfile

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

5454
# To allow pod to pick up beta versions use -beta. E.g., 1.1.7-beta.1
55-
pod 'WordPressAuthenticator', '~> 3.1.0'
55+
pod 'WordPressAuthenticator', '~> 3.2.0-beta.1'
5656
# pod 'WordPressAuthenticator', :git => 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', :commit => ''
5757
# pod 'WordPressAuthenticator', :git => 'https://github.com/wordpress-mobile/WordPressAuthenticator-iOS.git', :branch => ''
5858
# 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 (3.1.0):
45+
- WordPressAuthenticator (3.2.0-beta.2):
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 (~> 3.1.0)
95+
- WordPressAuthenticator (~> 3.2.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: 6e20b44d9743aa26e5089c16fbec35cd55748642
166+
WordPressAuthenticator: 74f808d6cef4e261843f50d9378dc8bdb5ef1299
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: a49b41520538bf9a2976016136166162186d972a
182+
PODFILE CHECKSUM: c8a3ba7544776c3fac1ba06550b2597fc5a03ba6
183183

184184
COCOAPODS: 1.11.3

RELEASE-NOTES.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
10.5
44
-----
55
- [**] Products: Now you can duplicate products from the More menu of the product detail screen. [https://github.com/woocommerce/woocommerce-ios/pull/7727]
6+
- [**] Login: Added Jetpack connection support from the Account Mismatch error screen. [https://github.com/woocommerce/woocommerce-ios/pull/7748]
67
- [*] Orders: We are bringing back the ability to add/edit customer notes and addresses from the main order screen [https://github.com/woocommerce/woocommerce-ios/pull/7750]
78
- [*] Help center: Added help center web page with FAQs for "Wrong WordPress.com account error" screen. [https://github.com/woocommerce/woocommerce-ios/pull/7747]
89
- [*] Widgets: The Today's Stat Widget adds support for bigger fonts. [https://github.com/woocommerce/woocommerce-ios/pull/7752]

WooCommerce/Classes/Authentication/AuthenticationManager.swift

Lines changed: 22 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -195,14 +195,8 @@ class AuthenticationManager: Authentication {
195195

196196
/// Account mismatched case
197197
guard matcher.match(originalURL: siteURL) else {
198-
/// Account mismatch experiment iteration 1: show jetpack connection error
199-
/// if the error happens during site credential login.
200-
if let credentials = credentials?.wporg {
201-
DDLogWarn("⚠️ Present Jetpack connection error for site: \(String(describing: siteURL))")
202-
return jetpackConnectionUI(for: siteURL, with: credentials, in: navigationController)
203-
}
204198
DDLogWarn("⚠️ Present account mismatch error for site: \(String(describing: siteURL))")
205-
return accountMismatchUI(for: siteURL, with: matcher)
199+
return accountMismatchUI(for: siteURL, siteCredentials: credentials?.wporg, with: matcher, in: navigationController)
206200
}
207201

208202
/// No Woo found
@@ -618,30 +612,29 @@ private extension AuthenticationManager {
618612
return ULErrorViewController(viewModel: viewModel)
619613
}
620614

621-
/// The error screen to be displayed when the user tries to enter as site
622-
/// whose Jetpack is not connected to their WP.com account.
623-
/// This screen is currently displayed when user logged in with site credentials.
624-
///
625-
func jetpackConnectionUI(for siteURL: String,
626-
with credentials: WordPressOrgCredentials,
627-
in navigationController: UINavigationController) -> UIViewController {
628-
let viewModel = JetpackConnectionErrorViewModel(siteURL: siteURL, credentials: credentials, onJetpackSetupCompletion: { email in
629-
return WordPressAuthenticator.showVerifyEmailForWPCom(
615+
/// The error screen to be displayed when the user tries to enter a site
616+
/// whose Jetpack is not associated with their account.
617+
/// - Parameters:
618+
/// - siteURL: URL for the site to log in to.
619+
/// - siteCredentials: WP.org credentials used to log in to the site if available.
620+
/// - matcher: the matcher used to check for matching sites.
621+
/// - navigationController: the controller that will present the view.
622+
///
623+
func accountMismatchUI(for siteURL: String,
624+
siteCredentials: WordPressOrgCredentials?,
625+
with matcher: ULAccountMatcher,
626+
in navigationController: UINavigationController) -> UIViewController {
627+
let viewModel = WrongAccountErrorViewModel(siteURL: siteURL,
628+
showsConnectedStores: matcher.hasConnectedStores,
629+
siteCredentials: siteCredentials,
630+
onJetpackSetupCompletion: { email, xmlrpc in
631+
WordPressAuthenticator.showVerifyEmailForWPCom(
630632
from: navigationController,
631-
xmlrpc: credentials.xmlrpc,
633+
xmlrpc: xmlrpc,
632634
connectedEmail: email,
633635
siteURL: siteURL
634636
)
635637
})
636-
return ULErrorViewController(viewModel: viewModel)
637-
}
638-
639-
/// The error screen to be displayed when the user tries to enter a site
640-
/// whose Jetpack is not associated with their account.
641-
/// This screen is currently displayed when user logged in with a WP.com account.
642-
///
643-
func accountMismatchUI(for siteURL: String, with matcher: ULAccountMatcher) -> UIViewController {
644-
let viewModel = WrongAccountErrorViewModel(siteURL: siteURL, showsConnectedStores: matcher.hasConnectedStores)
645638
let mismatchAccountUI = ULAccountMismatchViewController(viewModel: viewModel)
646639
return mismatchAccountUI
647640
}
@@ -682,15 +675,15 @@ private extension AuthenticationManager {
682675

683676
guard !site.isWPCom else {
684677
// The site doesn't belong to the current account since it was not included in the site picker.
685-
return accountMismatchUI(for: site.url, with: matcher)
678+
return accountMismatchUI(for: site.url, siteCredentials: nil, with: matcher, in: navigationController)
686679
}
687680

688681
/// Jetpack is required. Present an error if we don't detect a valid installation.
689-
guard site.isJetpackConnected == true else {
682+
guard site.hasJetpack && site.isJetpackActive else {
690683
return jetpackErrorUI(for: site.url, with: matcher, in: navigationController)
691684
}
692685

693-
return accountMismatchUI(for: site.url, with: matcher)
686+
return accountMismatchUI(for: site.url, siteCredentials: nil, with: matcher, in: navigationController)
694687
}
695688
}
696689

WooCommerce/Classes/Authentication/Navigation Exceptions/ULAccountMismatchViewController.swift

Lines changed: 56 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import Combine
12
import UIKit
23
import WordPressAuthenticator
34
import SafariServices
@@ -17,12 +18,17 @@ final class ULAccountMismatchViewController: UIViewController {
1718
return AccountHeaderView.instantiateFromNib()
1819
}()
1920

21+
private var subscriptions: Set<AnyCancellable> = []
22+
2023
@IBOutlet private weak var gravatarImageView: CircularImageView!
2124
@IBOutlet private weak var userNameLabel: UILabel!
2225
@IBOutlet private weak var singedInAsLabel: UILabel!
2326
@IBOutlet private weak var wrongAccountLabel: UILabel!
2427
@IBOutlet private weak var logOutButton: UIButton!
2528
@IBOutlet private weak var primaryButton: NUXButton!
29+
@IBOutlet private weak var secondaryButton: NUXButton!
30+
@IBOutlet private weak var activityIndicator: UIActivityIndicatorView!
31+
2632
@IBOutlet private weak var imageView: UIImageView!
2733
@IBOutlet private weak var errorMessage: UILabel!
2834
@IBOutlet private weak var extraInfoButton: UIButton!
@@ -58,8 +64,12 @@ final class ULAccountMismatchViewController: UIViewController {
5864
configureExtraInfoButton()
5965

6066
configurePrimaryButton()
67+
configureSecondaryButon()
68+
configureActivityIndicator()
6169

6270
setUnifiedMargins(forWidth: view.frame.width)
71+
72+
viewModel.viewDidLoad(self)
6373
}
6474

6575
override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
@@ -142,13 +152,46 @@ private extension ULAccountMismatchViewController {
142152

143153
func configurePrimaryButton() {
144154
primaryButton.isPrimary = true
145-
primaryButton.isHidden = viewModel.isPrimaryButtonHidden
146155
primaryButton.setTitle(viewModel.primaryButtonTitle, for: .normal)
147156
primaryButton.on(.touchUpInside) { [weak self] _ in
148157
self?.didTapPrimaryButton()
149158
}
159+
160+
viewModel.isPrimaryButtonLoading
161+
.sink { [weak self] isLoading in
162+
self?.primaryButton.showActivityIndicator(isLoading)
163+
}
164+
.store(in: &subscriptions)
165+
166+
viewModel.isPrimaryButtonHidden
167+
.sink { [weak self] isHidden in
168+
self?.primaryButton.isHidden = isHidden
169+
}
170+
.store(in: &subscriptions)
171+
}
172+
173+
func configureSecondaryButon() {
174+
secondaryButton.isPrimary = false
175+
secondaryButton.isHidden = viewModel.isSecondaryButtonHidden
176+
secondaryButton.setTitle(viewModel.secondaryButtonTitle, for: .normal)
177+
secondaryButton.on(.touchUpInside) { [weak self] _ in
178+
self?.didTapSecondaryButton()
179+
}
150180
}
151181

182+
func configureActivityIndicator() {
183+
activityIndicator.hidesWhenStopped = true
184+
185+
viewModel.isShowingActivityIndicator
186+
.sink { [weak self] showing in
187+
if showing {
188+
self?.activityIndicator.startAnimating()
189+
} else {
190+
self?.activityIndicator.stopAnimating()
191+
}
192+
}
193+
.store(in: &subscriptions)
194+
}
152195

153196
/// This logic is lifted from WPAuthenticator's LoginPrologueViewController
154197
/// This View Controller will be provided to WPAuthenticator. WPAuthenticator
@@ -192,6 +235,10 @@ private extension ULAccountMismatchViewController {
192235
viewModel.didTapPrimaryButton(in: self)
193236
}
194237

238+
func didTapSecondaryButton() {
239+
viewModel.didTapSecondaryButton(in: self)
240+
}
241+
195242
func didTapLogOutButton() {
196243
viewModel.didTapLogOutButton(in: self)
197244
}
@@ -231,6 +278,14 @@ extension ULAccountMismatchViewController {
231278
return primaryButton
232279
}
233280

281+
func getSecondaryActionButton() -> UIButton {
282+
return secondaryButton
283+
}
284+
285+
func getActivityIndicator() -> UIActivityIndicatorView {
286+
return activityIndicator
287+
}
288+
234289
func getUserNameLabel() -> UILabel {
235290
return userNameLabel
236291
}

WooCommerce/Classes/Authentication/Navigation Exceptions/ULAccountMismatchViewController.xib

Lines changed: 24 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,17 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="3.0" toolsVersion="21225" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES">
33
<device id="retina6_1" orientation="portrait" appearance="light"/>
44
<dependencies>
55
<deployment identifier="iOS"/>
6-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21207"/>
77
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
88
<capability name="System colors in document resources" minToolsVersion="11.0"/>
99
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
1010
</dependencies>
1111
<objects>
1212
<placeholder placeholderIdentifier="IBFilesOwner" id="-1" userLabel="File's Owner" customClass="ULAccountMismatchViewController" customModule="WooCommerce" customModuleProvider="target">
1313
<connections>
14+
<outlet property="activityIndicator" destination="GcM-pl-Wag" id="SyY-Mz-h3S"/>
1415
<outlet property="buttonViewLeadingConstraint" destination="r9Z-y5-j3W" id="bWb-vV-0U2"/>
1516
<outlet property="buttonViewTrailingConstraint" destination="3Fe-tr-bmb" id="DjF-95-KFx"/>
1617
<outlet property="errorMessage" destination="a2d-le-aKc" id="YgT-Ex-Gwh"/>
@@ -19,6 +20,7 @@
1920
<outlet property="imageView" destination="Osv-Wo-lxW" id="yIN-vL-DOA"/>
2021
<outlet property="logOutButton" destination="s2i-wr-qJf" id="yxc-ia-1rX"/>
2122
<outlet property="primaryButton" destination="ZHa-is-GJK" id="wzn-TJ-1Sm"/>
23+
<outlet property="secondaryButton" destination="0ZR-ma-6pq" id="W3d-H4-h81"/>
2224
<outlet property="singedInAsLabel" destination="emS-Tp-OXA" id="ajb-UO-YDy"/>
2325
<outlet property="stackViewLeadingConstraint" destination="jMe-jj-6Bt" id="JnU-my-QgI"/>
2426
<outlet property="stackViewTrailingConstraint" destination="Z7E-hC-lbB" id="RHp-Ac-R58"/>
@@ -33,23 +35,34 @@
3335
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
3436
<subviews>
3537
<view contentMode="scaleToFill" translatesAutoresizingMaskIntoConstraints="NO" id="10Z-y1-ZQ6" userLabel="Action Background View">
36-
<rect key="frame" x="0.0" y="772" width="414" height="90"/>
38+
<rect key="frame" x="0.0" y="662" width="414" height="200"/>
3739
<subviews>
3840
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="20" translatesAutoresizingMaskIntoConstraints="NO" id="mhI-fa-Yzw">
39-
<rect key="frame" x="20" y="20" width="374" height="50"/>
41+
<rect key="frame" x="20" y="20" width="374" height="160"/>
4042
<subviews>
43+
<activityIndicatorView opaque="NO" contentMode="scaleToFill" horizontalHuggingPriority="750" verticalHuggingPriority="750" style="medium" id="GcM-pl-Wag">
44+
<rect key="frame" x="0.0" y="0.0" width="374" height="20"/>
45+
<autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMaxY="YES"/>
46+
</activityIndicatorView>
4147
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ZHa-is-GJK" userLabel="secondary action button" customClass="NUXButton" customModule="WordPressAuthenticator">
42-
<rect key="frame" x="0.0" y="0.0" width="374" height="50"/>
48+
<rect key="frame" x="0.0" y="40" width="374" height="50"/>
4349
<constraints>
4450
<constraint firstAttribute="height" constant="50" id="Gcd-Af-CS9"/>
4551
</constraints>
4652
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
4753
<state key="normal" title="Primary Action Button">
4854
<color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
4955
</state>
50-
<userDefinedRuntimeAttributes>
51-
<userDefinedRuntimeAttribute type="boolean" keyPath="isPrimary" value="YES"/>
52-
</userDefinedRuntimeAttributes>
56+
</button>
57+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="0ZR-ma-6pq" userLabel="secondary action button" customClass="NUXButton" customModule="WordPressAuthenticator">
58+
<rect key="frame" x="0.0" y="110" width="374" height="50"/>
59+
<constraints>
60+
<constraint firstAttribute="height" constant="50" id="BTA-bw-h4s"/>
61+
</constraints>
62+
<fontDescription key="fontDescription" type="system" weight="semibold" pointSize="17"/>
63+
<state key="normal" title="Primary Action Button">
64+
<color key="titleColor" white="0.0" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
65+
</state>
5366
</button>
5467
</subviews>
5568
</stackView>
@@ -62,7 +75,7 @@
6275
</constraints>
6376
</view>
6477
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" alignment="center" spacing="32" translatesAutoresizingMaskIntoConstraints="NO" id="jIt-xb-rrN">
65-
<rect key="frame" x="34" y="190" width="346" height="486"/>
78+
<rect key="frame" x="34" y="176" width="346" height="486"/>
6679
<subviews>
6780
<imageView clipsSubviews="YES" userInteractionEnabled="NO" contentMode="scaleAspectFit" horizontalHuggingPriority="251" verticalHuggingPriority="251" translatesAutoresizingMaskIntoConstraints="NO" id="Np4-PU-IRZ" customClass="CircularImageView" customModule="WooCommerce" customModuleProvider="target">
6881
<rect key="frame" x="143" y="0.0" width="60" height="60"/>
@@ -131,12 +144,12 @@
131144
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
132145
<constraints>
133146
<constraint firstItem="fnl-2z-Ty3" firstAttribute="trailing" secondItem="10Z-y1-ZQ6" secondAttribute="trailing" id="3Fe-tr-bmb"/>
134-
<constraint firstItem="jIt-xb-rrN" firstAttribute="top" relation="greaterThanOrEqual" secondItem="fnl-2z-Ty3" secondAttribute="top" constant="8" id="4vu-ll-3S2"/>
135147
<constraint firstAttribute="trailing" secondItem="jIt-xb-rrN" secondAttribute="trailing" constant="34" id="Z7E-hC-lbB"/>
136-
<constraint firstItem="jIt-xb-rrN" firstAttribute="centerY" secondItem="fnl-2z-Ty3" secondAttribute="centerY" constant="-20" id="ZZg-jd-e4d"/>
137148
<constraint firstItem="jIt-xb-rrN" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" constant="34" id="jMe-jj-6Bt"/>
138149
<constraint firstItem="10Z-y1-ZQ6" firstAttribute="leading" secondItem="fnl-2z-Ty3" secondAttribute="leading" id="r9Z-y5-j3W"/>
139150
<constraint firstItem="fnl-2z-Ty3" firstAttribute="bottom" secondItem="10Z-y1-ZQ6" secondAttribute="bottom" id="rPP-rT-zVR"/>
151+
<constraint firstItem="10Z-y1-ZQ6" firstAttribute="top" relation="greaterThanOrEqual" secondItem="jIt-xb-rrN" secondAttribute="bottom" id="yet-32-SBz"/>
152+
<constraint firstItem="jIt-xb-rrN" firstAttribute="centerY" secondItem="fnl-2z-Ty3" secondAttribute="centerY" priority="250" constant="-20" id="z5R-69-jBg"/>
140153
</constraints>
141154
<point key="canvasLocation" x="137.68115942028987" y="86.383928571428569"/>
142155
</view>

0 commit comments

Comments
 (0)