Skip to content
This repository was archived by the owner on Feb 5, 2025. It is now read-only.

Commit 8121ebd

Browse files
authored
Merge pull request #665 from wordpress-mobile/wcios/7437-magic-link-i2
Show magic link login option as a secondary CTA instead of a table view row under a configuration
2 parents 5d98226 + 68a8748 commit 8121ebd

File tree

8 files changed

+182
-90
lines changed

8 files changed

+182
-90
lines changed

WordPressAuthenticator.podspec

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Pod::Spec.new do |s|
44
s.name = 'WordPressAuthenticator'
5-
s.version = '2.2.0'
5+
s.version = '2.2.1-beta.1'
66

77
s.summary = 'WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps.'
88
s.description = <<-DESC

WordPressAuthenticator.xcodeproj/project.pbxproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88

99
/* Begin PBXBuildFile section */
1010
020BE74A23B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020BE74923B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift */; };
11+
020DEF6428AA091100C85D51 /* MagicLinkRequester.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020DEF6328AA091100C85D51 /* MagicLinkRequester.swift */; };
1112
02A526CA28A3499C00FD1812 /* MagicLinkRequestedViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A526C828A3499C00FD1812 /* MagicLinkRequestedViewController.swift */; };
1213
02A526CB28A3499C00FD1812 /* MagicLinkRequestedViewController.xib in Resources */ = {isa = PBXBuildFile; fileRef = 02A526C928A3499C00FD1812 /* MagicLinkRequestedViewController.xib */; };
1314
02A526CD28A3A23900FD1812 /* UIButton+Styles.swift in Sources */ = {isa = PBXBuildFile; fileRef = 02A526CC28A3A23900FD1812 /* UIButton+Styles.swift */; };
@@ -213,6 +214,7 @@
213214

214215
/* Begin PBXFileReference section */
215216
020BE74923B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = WordPressAuthenticatorDisplayImages.swift; sourceTree = "<group>"; };
217+
020DEF6328AA091100C85D51 /* MagicLinkRequester.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MagicLinkRequester.swift; sourceTree = "<group>"; };
216218
02A526C828A3499C00FD1812 /* MagicLinkRequestedViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MagicLinkRequestedViewController.swift; sourceTree = "<group>"; };
217219
02A526C928A3499C00FD1812 /* MagicLinkRequestedViewController.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = MagicLinkRequestedViewController.xib; sourceTree = "<group>"; };
218220
02A526CC28A3A23900FD1812 /* UIButton+Styles.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIButton+Styles.swift"; sourceTree = "<group>"; };
@@ -861,6 +863,7 @@
861863
CE811D6824EDC14A00F4CCD6 /* LoginMagicLink.storyboard */,
862864
02A526C828A3499C00FD1812 /* MagicLinkRequestedViewController.swift */,
863865
02A526C928A3499C00FD1812 /* MagicLinkRequestedViewController.xib */,
866+
020DEF6328AA091100C85D51 /* MagicLinkRequester.swift */,
864867
);
865868
path = Login;
866869
sourceTree = "<group>";
@@ -1272,6 +1275,7 @@
12721275
98C9195B2308E3DA00A90E12 /* AppleAuthenticator.swift in Sources */,
12731276
B56090F9208A533200399AE4 /* WordPressAuthenticator+Events.swift in Sources */,
12741277
CEDE0D93242011E000CB3345 /* NSObject+Helpers.swift in Sources */,
1278+
020DEF6428AA091100C85D51 /* MagicLinkRequester.swift in Sources */,
12751279
020BE74A23B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift in Sources */,
12761280
B560913A208A563800399AE4 /* LoginLinkRequestViewController.swift in Sources */,
12771281
B560910C208A54F800399AE4 /* WordPressComOAuthClientFacade.m in Sources */,

WordPressAuthenticator/Analytics/AuthenticatorAnalyticsTracker.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,11 @@ public class AuthenticatorAnalyticsTracker {
7474
///
7575
case loginWithPassword = "login_password"
7676

77+
/// This flow starts when the user decides to login with a password instead, with magic link logic emphasis
78+
/// where the CTA is a secondary CTA instead of a table view row
79+
///
80+
case loginWithPasswordWithMagicLinkEmphasis = "login_password_magic_link_emphasis"
81+
7782
/// This flow starts when the user decides to log in with their site address
7883
///
7984
case loginWithSiteAddress = "login_site_address"

WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,10 @@ public struct WordPressAuthenticatorConfiguration {
108108
/// If disabled, password is shown by default with an option to send a magic link.
109109
let isWPComMagicLinkPreferredToPassword: Bool
110110

111+
/// If enabled, the alternative magic link action on the password screen is shown as a secondary call-to-action at the bottom.
112+
/// If disabled, the alternative magic link action on the password screen is shown below the reset password action.
113+
let isWPComMagicLinkShownAsSecondaryActionOnPasswordScreen: Bool
114+
111115
/// Designated Initializer
112116
///
113117
public init (wpcomClientId: String,
@@ -131,7 +135,8 @@ public struct WordPressAuthenticatorConfiguration {
131135
continueWithSiteAddressFirst: Bool = false,
132136
enableSiteCredentialsLoginForSelfHostedSites: Bool = false,
133137
isWPComLoginRequiredForSiteCredentialsLogin: Bool = false,
134-
isWPComMagicLinkPreferredToPassword: Bool = false) {
138+
isWPComMagicLinkPreferredToPassword: Bool = false,
139+
isWPComMagicLinkShownAsSecondaryActionOnPasswordScreen: Bool = false) {
135140

136141
self.wpcomClientId = wpcomClientId
137142
self.wpcomSecret = wpcomSecret
@@ -155,5 +160,6 @@ public struct WordPressAuthenticatorConfiguration {
155160
self.enableSiteCredentialsLoginForSelfHostedSites = enableSiteCredentialsLoginForSelfHostedSites
156161
self.isWPComLoginRequiredForSiteCredentialsLogin = isWPComLoginRequiredForSiteCredentialsLogin
157162
self.isWPComMagicLinkPreferredToPassword = isWPComMagicLinkPreferredToPassword
163+
self.isWPComMagicLinkShownAsSecondaryActionOnPasswordScreen = isWPComMagicLinkShownAsSecondaryActionOnPasswordScreen
158164
}
159165
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
import Foundation
2+
3+
/// Encapsulates the async request for a magic link and email validation for use cases that send a magic link.
4+
struct MagicLinkRequester {
5+
/// Makes the call to request a magic authentication link be emailed to the user if possible.
6+
func requestMagicLink(email: String, jetpackLogin: Bool) async -> Result<Void, Error> {
7+
await withCheckedContinuation { continuation in
8+
guard email.isValidEmail() else {
9+
return continuation.resume(returning: .failure(MagicLinkRequestError.invalidEmail))
10+
}
11+
12+
let service = WordPressComAccountService()
13+
service.requestAuthenticationLink(for: email,
14+
jetpackLogin: jetpackLogin,
15+
success: {
16+
continuation.resume(returning: .success(()))
17+
}, failure: { error in
18+
continuation.resume(returning: .failure(error))
19+
})
20+
}
21+
}
22+
}
23+
24+
extension MagicLinkRequester {
25+
enum MagicLinkRequestError: Error {
26+
case invalidEmail
27+
}
28+
}
Lines changed: 46 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
<?xml version="1.0" encoding="UTF-8"?>
2-
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="16097.2" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="aQT-Gx-U3x">
2+
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="21179.7" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="aQT-Gx-U3x">
33
<device id="retina4_7" orientation="portrait" appearance="light"/>
44
<dependencies>
55
<deployment identifier="iOS"/>
6-
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="16087"/>
6+
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="21169.4"/>
77
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
8+
<capability name="System colors in document resources" minToolsVersion="11.0"/>
89
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
910
</dependencies>
1011
<scenes>
@@ -20,50 +21,64 @@
2021
<rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
2122
<subviews>
2223
<tableView clipsSubviews="YES" contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" bounces="NO" dataMode="prototypes" style="plain" separatorStyle="none" rowHeight="-1" estimatedRowHeight="-1" sectionHeaderHeight="28" sectionFooterHeight="28" translatesAutoresizingMaskIntoConstraints="NO" id="KLl-Uz-wEP">
23-
<rect key="frame" x="0.0" y="0.0" width="375" height="591"/>
24+
<rect key="frame" x="0.0" y="0.0" width="375" height="561"/>
2425
<sections/>
2526
<connections>
2627
<outlet property="dataSource" destination="aQT-Gx-U3x" id="Sct-0G-HTk"/>
2728
<outlet property="delegate" destination="aQT-Gx-U3x" id="2xB-Wr-Hdh"/>
2829
</connections>
2930
</tableView>
3031
<view contentMode="scaleToFill" insetsLayoutMarginsFromSafeArea="NO" translatesAutoresizingMaskIntoConstraints="NO" id="xwA-rd-6jO" userLabel="Button background view">
31-
<rect key="frame" x="0.0" y="591" width="375" height="76"/>
32+
<rect key="frame" x="0.0" y="561" width="375" height="106"/>
3233
<subviews>
33-
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="roundedRect" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ClH-Cn-49d" userLabel="Primary Button" customClass="NUXButton" customModule="WordPressAuthenticatorResources" customModuleProvider="target">
34-
<rect key="frame" x="16" y="16" width="343" height="44"/>
35-
<constraints>
36-
<constraint firstAttribute="height" constant="44" id="iBk-Pi-8cv"/>
37-
</constraints>
38-
<state key="normal" title="Button"/>
39-
<userDefinedRuntimeAttributes>
40-
<userDefinedRuntimeAttribute type="boolean" keyPath="isPrimary" value="YES"/>
41-
</userDefinedRuntimeAttributes>
42-
<connections>
43-
<action selector="handleContinueButtonTapped:" destination="aQT-Gx-U3x" eventType="touchUpInside" id="Yeh-8i-cow"/>
44-
</connections>
45-
</button>
34+
<stackView opaque="NO" contentMode="scaleToFill" axis="vertical" spacing="16" translatesAutoresizingMaskIntoConstraints="NO" id="RjB-bg-t6D">
35+
<rect key="frame" x="16" y="8" width="343" height="90"/>
36+
<subviews>
37+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="ClH-Cn-49d" userLabel="Primary Button" customClass="NUXButton" customModule="WordPressAuthenticatorResources" customModuleProvider="target">
38+
<rect key="frame" x="0.0" y="0.0" width="343" height="44"/>
39+
<constraints>
40+
<constraint firstAttribute="height" constant="44" id="iBk-Pi-8cv"/>
41+
</constraints>
42+
<state key="normal" title="Button"/>
43+
<userDefinedRuntimeAttributes>
44+
<userDefinedRuntimeAttribute type="boolean" keyPath="isPrimary" value="YES"/>
45+
</userDefinedRuntimeAttributes>
46+
<connections>
47+
<action selector="handleContinueButtonTapped:" destination="aQT-Gx-U3x" eventType="touchUpInside" id="Yeh-8i-cow"/>
48+
</connections>
49+
</button>
50+
<button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="IAk-wS-Gex" customClass="NUXButton" customModule="WordPressAuthenticatorResources" customModuleProvider="target">
51+
<rect key="frame" x="0.0" y="60" width="343" height="30"/>
52+
<inset key="imageEdgeInsets" minX="0.0" minY="0.0" maxX="2.2250738585072014e-308" maxY="0.0"/>
53+
<state key="normal" title="Button"/>
54+
<userDefinedRuntimeAttributes>
55+
<userDefinedRuntimeAttribute type="boolean" keyPath="isPrimary" value="NO"/>
56+
</userDefinedRuntimeAttributes>
57+
</button>
58+
</subviews>
59+
</stackView>
4660
</subviews>
47-
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
61+
<viewLayoutGuide key="safeArea" id="VfW-kE-aWC"/>
62+
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
4863
<constraints>
49-
<constraint firstAttribute="bottomMargin" secondItem="ClH-Cn-49d" secondAttribute="bottom" constant="8" id="3Ba-yg-JKx"/>
50-
<constraint firstItem="ClH-Cn-49d" firstAttribute="top" secondItem="xwA-rd-6jO" secondAttribute="topMargin" constant="8" id="GgD-0x-Aud"/>
64+
<constraint firstItem="RjB-bg-t6D" firstAttribute="top" secondItem="xwA-rd-6jO" secondAttribute="top" constant="8" id="oia-aR-q8U"/>
65+
<constraint firstAttribute="bottom" secondItem="RjB-bg-t6D" secondAttribute="bottom" constant="8" id="rCm-Sg-bhf"/>
5166
</constraints>
52-
<viewLayoutGuide key="safeArea" id="VfW-kE-aWC"/>
5367
</view>
5468
</subviews>
55-
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
69+
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
5670
<constraints>
5771
<constraint firstItem="xwA-rd-6jO" firstAttribute="bottom" secondItem="dFS-Ic-byk" secondAttribute="bottomMargin" constant="8" id="85d-XY-Mr8"/>
5872
<constraint firstItem="xwA-rd-6jO" firstAttribute="trailing" secondItem="dFS-Ic-byk" secondAttribute="trailing" id="Bkw-QJ-Tbe"/>
59-
<constraint firstItem="KLl-Uz-wEP" firstAttribute="trailing" secondItem="ClH-Cn-49d" secondAttribute="trailing" constant="16" id="Bpv-qx-bHc"/>
60-
<constraint firstItem="ClH-Cn-49d" firstAttribute="leading" secondItem="KLl-Uz-wEP" secondAttribute="leading" constant="16" id="Rnp-SF-SGh"/>
6173
<constraint firstItem="xwA-rd-6jO" firstAttribute="top" secondItem="KLl-Uz-wEP" secondAttribute="bottom" id="gkZ-OV-HMi"/>
74+
<constraint firstItem="RjB-bg-t6D" firstAttribute="leading" secondItem="KLl-Uz-wEP" secondAttribute="leading" constant="16" id="kXv-Ig-Ty3"/>
6275
<constraint firstItem="xwA-rd-6jO" firstAttribute="leading" secondItem="dFS-Ic-byk" secondAttribute="leading" id="wBE-xi-42q"/>
76+
<constraint firstItem="KLl-Uz-wEP" firstAttribute="trailing" secondItem="RjB-bg-t6D" secondAttribute="trailing" constant="16" id="wPg-N4-vkn"/>
6377
</constraints>
6478
</view>
6579
</subviews>
66-
<color key="backgroundColor" systemColor="systemBackgroundColor" cocoaTouchSystemColor="whiteColor"/>
80+
<viewLayoutGuide key="safeArea" id="ihD-pY-rg9"/>
81+
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
6782
<constraints>
6883
<constraint firstItem="KLl-Uz-wEP" firstAttribute="leading" secondItem="ihD-pY-rg9" secondAttribute="leading" id="7Fn-Eh-Xx9"/>
6984
<constraint firstItem="ihD-pY-rg9" firstAttribute="trailing" secondItem="KLl-Uz-wEP" secondAttribute="trailing" id="7MD-ux-8i0"/>
@@ -73,10 +88,10 @@
7388
<constraint firstItem="dFS-Ic-byk" firstAttribute="leading" secondItem="ljV-kF-TaY" secondAttribute="leading" id="msS-7X-Za9"/>
7489
<constraint firstItem="dFS-Ic-byk" firstAttribute="trailing" secondItem="ljV-kF-TaY" secondAttribute="trailing" id="zY1-Yz-kTf"/>
7590
</constraints>
76-
<viewLayoutGuide key="safeArea" id="ihD-pY-rg9"/>
7791
</view>
7892
<connections>
7993
<outlet property="bottomContentConstraint" destination="Dva-c1-u2U" id="Mq1-PI-MuN"/>
94+
<outlet property="secondaryButton" destination="IAk-wS-Gex" id="psV-zJ-3Yd"/>
8095
<outlet property="submitButton" destination="ClH-Cn-49d" id="kBa-QN-0oH"/>
8196
<outlet property="tableView" destination="KLl-Uz-wEP" id="MGk-sG-xGv"/>
8297
<outlet property="tableViewLeadingConstraint" destination="7Fn-Eh-Xx9" id="yKO-sE-7mh"/>
@@ -88,4 +103,9 @@
88103
<point key="canvasLocation" x="-162.40000000000001" y="20.239880059970016"/>
89104
</scene>
90105
</scenes>
106+
<resources>
107+
<systemColor name="systemBackgroundColor">
108+
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
109+
</systemColor>
110+
</resources>
91111
</document>

0 commit comments

Comments
 (0)