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

Commit c0481b3

Browse files
authored
Merge pull request #181 from wordpress-mobile/release/1.10.7
Release/1.10.7
2 parents a084f94 + 2047372 commit c0481b3

File tree

12 files changed

+361
-34
lines changed

12 files changed

+361
-34
lines changed

WordPressAuthenticator.podspec

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
Pod::Spec.new do |s|
22
s.name = "WordPressAuthenticator"
3-
s.version = "1.10.6"
3+
s.version = "1.10.7"
44
s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps."
55

66
s.description = <<-DESC
@@ -21,6 +21,7 @@ Pod::Spec.new do |s|
2121
s.resource_bundles = {
2222
'WordPressAuthenticatorResources': [
2323
'WordPressAuthenticator/Resources/Assets.xcassets',
24+
'WordPressAuthenticator/Resources/SupportedEmailClients/*.plist',
2425
'WordPressAuthenticator/Resources/Animations/*.json',
2526
'WordPressAuthenticator/**/*.{storyboard,xib}'
2627
]

WordPressAuthenticator.xcodeproj/project.pbxproj

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@
1010
020BE74A23B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020BE74923B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift */; };
1111
1A21EE9822832BC300C940C6 /* WordPressComOAuthClientFacade+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A21EE9722832BC200C940C6 /* WordPressComOAuthClientFacade+Swift.swift */; };
1212
1A4095182271AEFC009AA86D /* WPAuthenticator-Swift.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4095152271AEFC009AA86D /* WPAuthenticator-Swift.h */; settings = {ATTRIBUTES = (Private, ); }; };
13+
3F550D4E23DA429B007E5897 /* AppSelectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F550D4D23DA429B007E5897 /* AppSelectorTests.swift */; };
14+
3F550D5123DA4A9C007E5897 /* LinkMailPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F550D5023DA4A9C007E5897 /* LinkMailPresenter.swift */; };
15+
3F550D5323DA4AC6007E5897 /* URLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F550D5223DA4AC6007E5897 /* URLHandler.swift */; };
16+
3FFF2FC123D7ED7C00D38C77 /* EmailClients.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3FFF2FC023D7ED7C00D38C77 /* EmailClients.plist */; };
17+
3FFF2FC323D7F53200D38C77 /* AppSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FFF2FC223D7F53200D38C77 /* AppSelector.swift */; };
1318
7A7A9B9CD2D81959F9AB9AF6 /* Pods_WordPressAuthenticator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C736FF243DE333FCAB1C2614 /* Pods_WordPressAuthenticator.framework */; };
1419
982C8E7923021C20003F1BA0 /* LoginPrologueLoginMethodViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982C8E7823021C20003F1BA0 /* LoginPrologueLoginMethodViewController.swift */; };
1520
98AA5A5720AA1A7000A5958A /* WPHelpIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AA5A5620AA1A7000A5958A /* WPHelpIndicatorView.swift */; };
@@ -149,6 +154,11 @@
149154
276354F054C34AD36CA32AB6 /* Pods-WordPressAuthenticator.release-alpha.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WordPressAuthenticator.release-alpha.xcconfig"; path = "Pods/Target Support Files/Pods-WordPressAuthenticator/Pods-WordPressAuthenticator.release-alpha.xcconfig"; sourceTree = "<group>"; };
150155
33FEF45B466FF8EAAE5F3923 /* Pods-WordPressAuthenticator.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WordPressAuthenticator.release.xcconfig"; path = "Pods/Target Support Files/Pods-WordPressAuthenticator/Pods-WordPressAuthenticator.release.xcconfig"; sourceTree = "<group>"; };
151156
37AFD4EF492B00CA7AEC11A3 /* Pods-WordPressAuthenticatorTests.release-alpha.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WordPressAuthenticatorTests.release-alpha.xcconfig"; path = "Pods/Target Support Files/Pods-WordPressAuthenticatorTests/Pods-WordPressAuthenticatorTests.release-alpha.xcconfig"; sourceTree = "<group>"; };
157+
3F550D4D23DA429B007E5897 /* AppSelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSelectorTests.swift; sourceTree = "<group>"; };
158+
3F550D5023DA4A9C007E5897 /* LinkMailPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkMailPresenter.swift; sourceTree = "<group>"; };
159+
3F550D5223DA4AC6007E5897 /* URLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLHandler.swift; sourceTree = "<group>"; };
160+
3FFF2FC023D7ED7C00D38C77 /* EmailClients.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = EmailClients.plist; sourceTree = "<group>"; };
161+
3FFF2FC223D7F53200D38C77 /* AppSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSelector.swift; sourceTree = "<group>"; };
152162
5A441EC80D2B8D2209C2E228 /* Pods_WordPressAuthenticatorTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WordPressAuthenticatorTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
153163
8F7217C3F7A6285D9C6CF786 /* Pods-WordPressAuthenticator.release-internal.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WordPressAuthenticator.release-internal.xcconfig"; path = "Pods/Target Support Files/Pods-WordPressAuthenticator/Pods-WordPressAuthenticator.release-internal.xcconfig"; sourceTree = "<group>"; };
154164
982C8E7823021C20003F1BA0 /* LoginPrologueLoginMethodViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginPrologueLoginMethodViewController.swift; sourceTree = "<group>"; };
@@ -294,6 +304,39 @@
294304
path = Private;
295305
sourceTree = "<group>";
296306
};
307+
3F550D4B23DA3B59007E5897 /* SupportedEmailClients */ = {
308+
isa = PBXGroup;
309+
children = (
310+
3FFF2FC023D7ED7C00D38C77 /* EmailClients.plist */,
311+
);
312+
path = SupportedEmailClients;
313+
sourceTree = "<group>";
314+
};
315+
3F550D4C23DA4191007E5897 /* UI */ = {
316+
isa = PBXGroup;
317+
children = (
318+
);
319+
path = UI;
320+
sourceTree = "<group>";
321+
};
322+
3F550D4F23DA4A6B007E5897 /* Email Client Picker */ = {
323+
isa = PBXGroup;
324+
children = (
325+
3FFF2FC223D7F53200D38C77 /* AppSelector.swift */,
326+
3F550D5023DA4A9C007E5897 /* LinkMailPresenter.swift */,
327+
3F550D5223DA4AC6007E5897 /* URLHandler.swift */,
328+
);
329+
path = "Email Client Picker";
330+
sourceTree = "<group>";
331+
};
332+
3F550D5423DA5094007E5897 /* Email Client Picker */ = {
333+
isa = PBXGroup;
334+
children = (
335+
3F550D4D23DA429B007E5897 /* AppSelectorTests.swift */,
336+
);
337+
path = "Email Client Picker";
338+
sourceTree = "<group>";
339+
};
297340
6205895375D954F46B1DFE53 /* Pods */ = {
298341
isa = PBXGroup;
299342
children = (
@@ -477,6 +520,7 @@
477520
children = (
478521
B5A5274020B478160065BE81 /* Animations */,
479522
B5E07FF3208FD13800657A9A /* Assets.xcassets */,
523+
3F550D4B23DA3B59007E5897 /* SupportedEmailClients */,
480524
);
481525
path = Resources;
482526
sourceTree = "<group>";
@@ -519,6 +563,7 @@
519563
children = (
520564
CE1B18CA20EEC31000BECC3F /* Credentials */,
521565
B5609099208A4EAF00399AE4 /* Authenticator */,
566+
3F550D4F23DA4A6B007E5897 /* Email Client Picker */,
522567
B560909B208A4EB000399AE4 /* Extensions */,
523568
B5ED7917207E993E00A8FD8C /* Logging */,
524569
B5609098208A4EAF00399AE4 /* Model */,
@@ -538,9 +583,11 @@
538583
B5ED7901207E976500A8FD8C /* WordPressAuthenticatorTests */ = {
539584
isa = PBXGroup;
540585
children = (
586+
3F550D5423DA5094007E5897 /* Email Client Picker */,
541587
B501C03D208FC52500D1E58F /* Authenticator */,
542588
B501C03B208FC52400D1E58F /* Model */,
543589
B501C03F208FC52500D1E58F /* Services */,
590+
3F550D4C23DA4191007E5897 /* UI */,
544591
B5ED7904207E976500A8FD8C /* Info.plist */,
545592
);
546593
path = WordPressAuthenticatorTests;
@@ -699,6 +746,7 @@
699746
B5609118208A555600399AE4 /* SearchTableViewCell.xib in Resources */,
700747
B560913F208A563800399AE4 /* Login.storyboard in Resources */,
701748
B5609137208A563800399AE4 /* EmailMagicLink.storyboard in Resources */,
749+
3FFF2FC123D7ED7C00D38C77 /* EmailClients.plist in Resources */,
702750
FF629D9622393500004C4106 /* WordPressAuthenticator.podspec in Resources */,
703751
);
704752
runOnlyForDeploymentPostprocessing = 0;
@@ -880,6 +928,7 @@
880928
CE30A2AD2257CECC00DF3CDA /* AuthenticatorCredentials.swift in Sources */,
881929
B5609145208A563800399AE4 /* LoginViewController.swift in Sources */,
882930
B5609139208A563800399AE4 /* LoginEmailViewController.swift in Sources */,
931+
3F550D5323DA4AC6007E5897 /* URLHandler.swift in Sources */,
883932
98C9195B2308E3DA00A90E12 /* AppleAuthenticator.swift in Sources */,
884933
B56090F9208A533200399AE4 /* WordPressAuthenticator+Events.swift in Sources */,
885934
020BE74A23B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift in Sources */,
@@ -915,11 +964,13 @@
915964
B560911F208A555E00399AE4 /* SignupGoogleViewController.swift in Sources */,
916965
B5609142208A563800399AE4 /* LoginNavigationController.swift in Sources */,
917966
B56090E4208A4F9D00399AE4 /* WPNUXMainButton.m in Sources */,
967+
3FFF2FC323D7F53200D38C77 /* AppSelector.swift in Sources */,
918968
B560913B208A563800399AE4 /* LoginSelfHostedViewController.swift in Sources */,
919969
B5609136208A563800399AE4 /* Login2FAViewController.swift in Sources */,
920970
B56090E1208A4F9D00399AE4 /* WPWalkthroughTextField.m in Sources */,
921971
B56090EF208A527000399AE4 /* WPStyleGuide+Login.swift in Sources */,
922972
B56090D0208A4F5400399AE4 /* NUXViewControllerBase.swift in Sources */,
973+
3F550D5123DA4A9C007E5897 /* LinkMailPresenter.swift in Sources */,
923974
B56090DE208A4F9D00399AE4 /* WPWalkthroughOverlayView.m in Sources */,
924975
B560910A208A54F800399AE4 /* WordPressComAccountService.swift in Sources */,
925976
B56090FA208A533200399AE4 /* WordPressAuthenticator.swift in Sources */,
@@ -931,6 +982,7 @@
931982
buildActionMask = 2147483647;
932983
files = (
933984
B501C045208FC68700D1E58F /* LoginFieldsValidationTests.swift in Sources */,
985+
3F550D4E23DA429B007E5897 /* AppSelectorTests.swift in Sources */,
934986
CE16177821B70C1A00B82A47 /* WordPressAuthenticatorDisplayTextTests.swift in Sources */,
935987
B501C048208FC79C00D1E58F /* LoginFacadeTests.m in Sources */,
936988
B501C046208FC6A700D1E58F /* WordPressAuthenticatorTests.swift in Sources */,

WordPressAuthenticator/Authenticator/WordPressAuthenticatorConfiguration.swift

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -46,10 +46,10 @@ public struct WordPressAuthenticatorConfiguration {
4646
let userAgent: String
4747

4848
/// Flag indicating which Log In flow to display.
49-
/// In the new flow, when Log In is selected, a button view is displayed with options.
50-
/// In the old flow, when Log In is selected, the email login view is displayed with alternative options.
49+
/// If enabled, when Log In is selected, a button view is displayed with options.
50+
/// If disabled, when Log In is selected, the email login view is displayed with alternative options.
5151
///
52-
let showNewLoginFlow: Bool
52+
let showLoginOptions: Bool
5353

5454
/// Flag indicating if the login options button view should be displayed in the site address flow.
5555
/// If enabled, the options button view will be displayed after the site address has been entered
@@ -61,6 +61,10 @@ public struct WordPressAuthenticatorConfiguration {
6161
///
6262
let enableSignInWithApple: Bool
6363

64+
/// Flag indicating if the unified login/signup flow should be displayed.
65+
///
66+
let enableUnifiedAuth: Bool
67+
6468
/// Designated Initializer
6569
///
6670
public init (wpcomClientId: String,
@@ -73,9 +77,10 @@ public struct WordPressAuthenticatorConfiguration {
7377
googleLoginServerClientId: String,
7478
googleLoginScheme: String,
7579
userAgent: String,
76-
showNewLoginFlow: Bool = false,
80+
showLoginOptions: Bool = false,
7781
showLoginOptionsFromSiteAddress: Bool = false,
78-
enableSignInWithApple: Bool = false) {
82+
enableSignInWithApple: Bool = false,
83+
enableUnifiedAuth: Bool = false) {
7984

8085
self.wpcomClientId = wpcomClientId
8186
self.wpcomSecret = wpcomSecret
@@ -87,8 +92,9 @@ public struct WordPressAuthenticatorConfiguration {
8792
self.googleLoginServerClientId = googleLoginServerClientId
8893
self.googleLoginScheme = googleLoginScheme
8994
self.userAgent = userAgent
90-
self.showNewLoginFlow = showNewLoginFlow
95+
self.showLoginOptions = showLoginOptions
9196
self.showLoginOptionsFromSiteAddress = showLoginOptionsFromSiteAddress
9297
self.enableSignInWithApple = enableSignInWithApple
98+
self.enableUnifiedAuth = enableUnifiedAuth
9399
}
94100
}
Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
import MessageUI
2+
import UIKit
3+
4+
/// App selector that selects an app from a list and opens it
5+
/// Note: it's a wrapper of UIAlertController (which cannot be sublcassed)
6+
class AppSelector {
7+
// the action sheet that will contain the list of apps that can be called
8+
let alertController: UIAlertController
9+
10+
/// initializes the picker with a dictionary. Initialization will fail if an empty/invalid app list is passed
11+
/// - Parameters:
12+
/// - appList: collection of apps to be added to the selector
13+
/// - defaultAction: default action, if not nil, will be the first element of the list
14+
/// - sourceView: the sourceView to anchor the action sheet to
15+
/// - urlHandler: object that handles app URL schemes; defaults to UIApplication.shared
16+
init?(with appList: [String: String],
17+
defaultAction: UIAlertAction? = nil,
18+
sourceView: UIView,
19+
urlHandler: URLHandler = UIApplication.shared) {
20+
/// inline method that builds a list of app calls to be inserted in the action sheet
21+
func makeAlertActions(from appList: [String: String]) -> [UIAlertAction]? {
22+
guard !appList.isEmpty else {
23+
return nil
24+
}
25+
26+
var actions = [UIAlertAction]()
27+
for (name, urlString) in appList {
28+
guard let url = URL(string: urlString), urlHandler.canOpenURL(url) else {
29+
continue
30+
}
31+
actions.append(UIAlertAction(title: AppSelectorTitles(rawValue: name)?.localized ?? name, style: .default) { action in
32+
urlHandler.open(url, options: [:], completionHandler: nil)
33+
})
34+
}
35+
36+
guard !actions.isEmpty else {
37+
return nil
38+
}
39+
//sort the apps alphabetically
40+
actions = actions.sorted { $0.title ?? "" < $1.title ?? "" }
41+
actions.append(UIAlertAction(title: AppSelectorTitles.cancel.localized, style: .cancel, handler: nil))
42+
43+
if let action = defaultAction {
44+
actions.insert(action, at: 0)
45+
}
46+
return actions
47+
}
48+
49+
guard let appCalls = makeAlertActions(from: appList) else {
50+
return nil
51+
}
52+
53+
alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
54+
alertController.popoverPresentationController?.sourceView = sourceView
55+
alertController.popoverPresentationController?.sourceRect = sourceView.bounds
56+
appCalls.forEach {
57+
alertController.addAction($0)
58+
}
59+
}
60+
}
61+
62+
63+
/// Initializers for Email Picker
64+
extension AppSelector {
65+
/// initializes the picker with a plist file in a specified bundle
66+
convenience init?(with plistFile: String,
67+
in bundle: Bundle,
68+
defaultAction: UIAlertAction? = nil,
69+
sourceView: UIView) {
70+
71+
guard let plistPath = bundle.path(forResource: plistFile, ofType: "plist"),
72+
let availableApps = NSDictionary(contentsOfFile: plistPath) as? [String: String] else {
73+
return nil
74+
}
75+
self.init(with: availableApps,
76+
defaultAction: defaultAction,
77+
sourceView: sourceView)
78+
}
79+
80+
/// Convenience init for a picker that calls supported email clients apps, defined in EmailClients.plist
81+
convenience init?(sourceView: UIView) {
82+
guard let bundlePath = Bundle(for: type(of: self))
83+
.path(forResource: "WordPressAuthenticatorResources", ofType: "bundle"),
84+
let wpAuthenticatorBundle = Bundle(path: bundlePath) else {
85+
return nil
86+
}
87+
88+
let plistFile = "EmailClients"
89+
var defaultAction: UIAlertAction?
90+
91+
// if available, prepend apple mail
92+
if MFMailComposeViewController.canSendMail(), let url = URL(string: "message://") {
93+
defaultAction = UIAlertAction(title: AppSelectorTitles.appleMail.localized, style: .default) { action in
94+
UIApplication.shared.open(url)
95+
}
96+
}
97+
self.init(with: plistFile,
98+
in: wpAuthenticatorBundle,
99+
defaultAction: defaultAction,
100+
sourceView: sourceView)
101+
}
102+
}
103+
104+
105+
/// Localizable app selector titles
106+
enum AppSelectorTitles: String {
107+
case appleMail
108+
case gmail
109+
case airmail
110+
case msOutlook
111+
case spark
112+
case yahooMail
113+
case fastmail
114+
case cancel
115+
116+
var localized: String {
117+
switch self {
118+
case .appleMail:
119+
return NSLocalizedString("Mail (Default)", comment: "Option to select the Apple Mail app when logging in with magic links")
120+
case .gmail:
121+
return NSLocalizedString("Gmail", comment: "Option to select the Gmail app when logging in with magic links")
122+
case .airmail:
123+
return NSLocalizedString("Airmail", comment: "Option to select the Airmail app when logging in with magic links")
124+
case .msOutlook:
125+
return NSLocalizedString("Microsoft Outlook", comment: "Option to select the Microsft Outlook app when logging in with magic links")
126+
case .spark:
127+
return NSLocalizedString("Spark", comment: "Option to select the Spark email app when logging in with magic links")
128+
case .yahooMail:
129+
return NSLocalizedString("Yahoo Mail", comment: "Option to select the Yahoo Mail app when logging in with magic links")
130+
case .fastmail:
131+
return NSLocalizedString("Fastmail", comment: "Option to select the Fastmail app when logging in with magic links")
132+
case .cancel:
133+
return NSLocalizedString("Cancel", comment: "Option to cancel the email app selection when logging in with magic links")
134+
}
135+
}
136+
}

0 commit comments

Comments
 (0)