Skip to content
This repository was archived by the owner on Feb 5, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion WordPressAuthenticator.podspec
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Pod::Spec.new do |s|
s.name = "WordPressAuthenticator"
s.version = "1.10.6"
s.version = "1.10.7"
s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps."

s.description = <<-DESC
Expand All @@ -21,6 +21,7 @@ Pod::Spec.new do |s|
s.resource_bundles = {
'WordPressAuthenticatorResources': [
'WordPressAuthenticator/Resources/Assets.xcassets',
'WordPressAuthenticator/Resources/SupportedEmailClients/*.plist',
'WordPressAuthenticator/Resources/Animations/*.json',
'WordPressAuthenticator/**/*.{storyboard,xib}'
]
Expand Down
52 changes: 52 additions & 0 deletions WordPressAuthenticator.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@
020BE74A23B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift in Sources */ = {isa = PBXBuildFile; fileRef = 020BE74923B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift */; };
1A21EE9822832BC300C940C6 /* WordPressComOAuthClientFacade+Swift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A21EE9722832BC200C940C6 /* WordPressComOAuthClientFacade+Swift.swift */; };
1A4095182271AEFC009AA86D /* WPAuthenticator-Swift.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4095152271AEFC009AA86D /* WPAuthenticator-Swift.h */; settings = {ATTRIBUTES = (Private, ); }; };
3F550D4E23DA429B007E5897 /* AppSelectorTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F550D4D23DA429B007E5897 /* AppSelectorTests.swift */; };
3F550D5123DA4A9C007E5897 /* LinkMailPresenter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F550D5023DA4A9C007E5897 /* LinkMailPresenter.swift */; };
3F550D5323DA4AC6007E5897 /* URLHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3F550D5223DA4AC6007E5897 /* URLHandler.swift */; };
3FFF2FC123D7ED7C00D38C77 /* EmailClients.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3FFF2FC023D7ED7C00D38C77 /* EmailClients.plist */; };
3FFF2FC323D7F53200D38C77 /* AppSelector.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3FFF2FC223D7F53200D38C77 /* AppSelector.swift */; };
7A7A9B9CD2D81959F9AB9AF6 /* Pods_WordPressAuthenticator.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C736FF243DE333FCAB1C2614 /* Pods_WordPressAuthenticator.framework */; };
982C8E7923021C20003F1BA0 /* LoginPrologueLoginMethodViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 982C8E7823021C20003F1BA0 /* LoginPrologueLoginMethodViewController.swift */; };
98AA5A5720AA1A7000A5958A /* WPHelpIndicatorView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 98AA5A5620AA1A7000A5958A /* WPHelpIndicatorView.swift */; };
Expand Down Expand Up @@ -149,6 +154,11 @@
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>"; };
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>"; };
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>"; };
3F550D4D23DA429B007E5897 /* AppSelectorTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSelectorTests.swift; sourceTree = "<group>"; };
3F550D5023DA4A9C007E5897 /* LinkMailPresenter.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LinkMailPresenter.swift; sourceTree = "<group>"; };
3F550D5223DA4AC6007E5897 /* URLHandler.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = URLHandler.swift; sourceTree = "<group>"; };
3FFF2FC023D7ED7C00D38C77 /* EmailClients.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = EmailClients.plist; sourceTree = "<group>"; };
3FFF2FC223D7F53200D38C77 /* AppSelector.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppSelector.swift; sourceTree = "<group>"; };
5A441EC80D2B8D2209C2E228 /* Pods_WordPressAuthenticatorTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WordPressAuthenticatorTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
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>"; };
982C8E7823021C20003F1BA0 /* LoginPrologueLoginMethodViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginPrologueLoginMethodViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -294,6 +304,39 @@
path = Private;
sourceTree = "<group>";
};
3F550D4B23DA3B59007E5897 /* SupportedEmailClients */ = {
isa = PBXGroup;
children = (
3FFF2FC023D7ED7C00D38C77 /* EmailClients.plist */,
);
path = SupportedEmailClients;
sourceTree = "<group>";
};
3F550D4C23DA4191007E5897 /* UI */ = {
isa = PBXGroup;
children = (
);
path = UI;
sourceTree = "<group>";
};
3F550D4F23DA4A6B007E5897 /* Email Client Picker */ = {
isa = PBXGroup;
children = (
3FFF2FC223D7F53200D38C77 /* AppSelector.swift */,
3F550D5023DA4A9C007E5897 /* LinkMailPresenter.swift */,
3F550D5223DA4AC6007E5897 /* URLHandler.swift */,
);
path = "Email Client Picker";
sourceTree = "<group>";
};
3F550D5423DA5094007E5897 /* Email Client Picker */ = {
isa = PBXGroup;
children = (
3F550D4D23DA429B007E5897 /* AppSelectorTests.swift */,
);
path = "Email Client Picker";
sourceTree = "<group>";
};
6205895375D954F46B1DFE53 /* Pods */ = {
isa = PBXGroup;
children = (
Expand Down Expand Up @@ -477,6 +520,7 @@
children = (
B5A5274020B478160065BE81 /* Animations */,
B5E07FF3208FD13800657A9A /* Assets.xcassets */,
3F550D4B23DA3B59007E5897 /* SupportedEmailClients */,
);
path = Resources;
sourceTree = "<group>";
Expand Down Expand Up @@ -519,6 +563,7 @@
children = (
CE1B18CA20EEC31000BECC3F /* Credentials */,
B5609099208A4EAF00399AE4 /* Authenticator */,
3F550D4F23DA4A6B007E5897 /* Email Client Picker */,
B560909B208A4EB000399AE4 /* Extensions */,
B5ED7917207E993E00A8FD8C /* Logging */,
B5609098208A4EAF00399AE4 /* Model */,
Expand All @@ -538,9 +583,11 @@
B5ED7901207E976500A8FD8C /* WordPressAuthenticatorTests */ = {
isa = PBXGroup;
children = (
3F550D5423DA5094007E5897 /* Email Client Picker */,
B501C03D208FC52500D1E58F /* Authenticator */,
B501C03B208FC52400D1E58F /* Model */,
B501C03F208FC52500D1E58F /* Services */,
3F550D4C23DA4191007E5897 /* UI */,
B5ED7904207E976500A8FD8C /* Info.plist */,
);
path = WordPressAuthenticatorTests;
Expand Down Expand Up @@ -699,6 +746,7 @@
B5609118208A555600399AE4 /* SearchTableViewCell.xib in Resources */,
B560913F208A563800399AE4 /* Login.storyboard in Resources */,
B5609137208A563800399AE4 /* EmailMagicLink.storyboard in Resources */,
3FFF2FC123D7ED7C00D38C77 /* EmailClients.plist in Resources */,
FF629D9622393500004C4106 /* WordPressAuthenticator.podspec in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
Expand Down Expand Up @@ -880,6 +928,7 @@
CE30A2AD2257CECC00DF3CDA /* AuthenticatorCredentials.swift in Sources */,
B5609145208A563800399AE4 /* LoginViewController.swift in Sources */,
B5609139208A563800399AE4 /* LoginEmailViewController.swift in Sources */,
3F550D5323DA4AC6007E5897 /* URLHandler.swift in Sources */,
98C9195B2308E3DA00A90E12 /* AppleAuthenticator.swift in Sources */,
B56090F9208A533200399AE4 /* WordPressAuthenticator+Events.swift in Sources */,
020BE74A23B0BD2E007FE54C /* WordPressAuthenticatorDisplayImages.swift in Sources */,
Expand Down Expand Up @@ -915,11 +964,13 @@
B560911F208A555E00399AE4 /* SignupGoogleViewController.swift in Sources */,
B5609142208A563800399AE4 /* LoginNavigationController.swift in Sources */,
B56090E4208A4F9D00399AE4 /* WPNUXMainButton.m in Sources */,
3FFF2FC323D7F53200D38C77 /* AppSelector.swift in Sources */,
B560913B208A563800399AE4 /* LoginSelfHostedViewController.swift in Sources */,
B5609136208A563800399AE4 /* Login2FAViewController.swift in Sources */,
B56090E1208A4F9D00399AE4 /* WPWalkthroughTextField.m in Sources */,
B56090EF208A527000399AE4 /* WPStyleGuide+Login.swift in Sources */,
B56090D0208A4F5400399AE4 /* NUXViewControllerBase.swift in Sources */,
3F550D5123DA4A9C007E5897 /* LinkMailPresenter.swift in Sources */,
B56090DE208A4F9D00399AE4 /* WPWalkthroughOverlayView.m in Sources */,
B560910A208A54F800399AE4 /* WordPressComAccountService.swift in Sources */,
B56090FA208A533200399AE4 /* WordPressAuthenticator.swift in Sources */,
Expand All @@ -931,6 +982,7 @@
buildActionMask = 2147483647;
files = (
B501C045208FC68700D1E58F /* LoginFieldsValidationTests.swift in Sources */,
3F550D4E23DA429B007E5897 /* AppSelectorTests.swift in Sources */,
CE16177821B70C1A00B82A47 /* WordPressAuthenticatorDisplayTextTests.swift in Sources */,
B501C048208FC79C00D1E58F /* LoginFacadeTests.m in Sources */,
B501C046208FC6A700D1E58F /* WordPressAuthenticatorTests.swift in Sources */,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ public struct WordPressAuthenticatorConfiguration {
let userAgent: String

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

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

/// Flag indicating if the unified login/signup flow should be displayed.
///
let enableUnifiedAuth: Bool

/// Designated Initializer
///
public init (wpcomClientId: String,
Expand All @@ -73,9 +77,10 @@ public struct WordPressAuthenticatorConfiguration {
googleLoginServerClientId: String,
googleLoginScheme: String,
userAgent: String,
showNewLoginFlow: Bool = false,
showLoginOptions: Bool = false,
showLoginOptionsFromSiteAddress: Bool = false,
enableSignInWithApple: Bool = false) {
enableSignInWithApple: Bool = false,
enableUnifiedAuth: Bool = false) {

self.wpcomClientId = wpcomClientId
self.wpcomSecret = wpcomSecret
Expand All @@ -87,8 +92,9 @@ public struct WordPressAuthenticatorConfiguration {
self.googleLoginServerClientId = googleLoginServerClientId
self.googleLoginScheme = googleLoginScheme
self.userAgent = userAgent
self.showNewLoginFlow = showNewLoginFlow
self.showLoginOptions = showLoginOptions
self.showLoginOptionsFromSiteAddress = showLoginOptionsFromSiteAddress
self.enableSignInWithApple = enableSignInWithApple
self.enableUnifiedAuth = enableUnifiedAuth
}
}
136 changes: 136 additions & 0 deletions WordPressAuthenticator/Email Client Picker/AppSelector.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,136 @@
import MessageUI
import UIKit

/// App selector that selects an app from a list and opens it
/// Note: it's a wrapper of UIAlertController (which cannot be sublcassed)
class AppSelector {
// the action sheet that will contain the list of apps that can be called
let alertController: UIAlertController

/// initializes the picker with a dictionary. Initialization will fail if an empty/invalid app list is passed
/// - Parameters:
/// - appList: collection of apps to be added to the selector
/// - defaultAction: default action, if not nil, will be the first element of the list
/// - sourceView: the sourceView to anchor the action sheet to
/// - urlHandler: object that handles app URL schemes; defaults to UIApplication.shared
init?(with appList: [String: String],
defaultAction: UIAlertAction? = nil,
sourceView: UIView,
urlHandler: URLHandler = UIApplication.shared) {
/// inline method that builds a list of app calls to be inserted in the action sheet
func makeAlertActions(from appList: [String: String]) -> [UIAlertAction]? {
guard !appList.isEmpty else {
return nil
}

var actions = [UIAlertAction]()
for (name, urlString) in appList {
guard let url = URL(string: urlString), urlHandler.canOpenURL(url) else {
continue
}
actions.append(UIAlertAction(title: AppSelectorTitles(rawValue: name)?.localized ?? name, style: .default) { action in
urlHandler.open(url, options: [:], completionHandler: nil)
})
}

guard !actions.isEmpty else {
return nil
}
//sort the apps alphabetically
actions = actions.sorted { $0.title ?? "" < $1.title ?? "" }
actions.append(UIAlertAction(title: AppSelectorTitles.cancel.localized, style: .cancel, handler: nil))

if let action = defaultAction {
actions.insert(action, at: 0)
}
return actions
}

guard let appCalls = makeAlertActions(from: appList) else {
return nil
}

alertController = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
alertController.popoverPresentationController?.sourceView = sourceView
alertController.popoverPresentationController?.sourceRect = sourceView.bounds
appCalls.forEach {
alertController.addAction($0)
}
}
}


/// Initializers for Email Picker
extension AppSelector {
/// initializes the picker with a plist file in a specified bundle
convenience init?(with plistFile: String,
in bundle: Bundle,
defaultAction: UIAlertAction? = nil,
sourceView: UIView) {

guard let plistPath = bundle.path(forResource: plistFile, ofType: "plist"),
let availableApps = NSDictionary(contentsOfFile: plistPath) as? [String: String] else {
return nil
}
self.init(with: availableApps,
defaultAction: defaultAction,
sourceView: sourceView)
}

/// Convenience init for a picker that calls supported email clients apps, defined in EmailClients.plist
convenience init?(sourceView: UIView) {
guard let bundlePath = Bundle(for: type(of: self))
.path(forResource: "WordPressAuthenticatorResources", ofType: "bundle"),
let wpAuthenticatorBundle = Bundle(path: bundlePath) else {
return nil
}

let plistFile = "EmailClients"
var defaultAction: UIAlertAction?

// if available, prepend apple mail
if MFMailComposeViewController.canSendMail(), let url = URL(string: "message://") {
defaultAction = UIAlertAction(title: AppSelectorTitles.appleMail.localized, style: .default) { action in
UIApplication.shared.open(url)
}
}
self.init(with: plistFile,
in: wpAuthenticatorBundle,
defaultAction: defaultAction,
sourceView: sourceView)
}
}


/// Localizable app selector titles
enum AppSelectorTitles: String {
case appleMail
case gmail
case airmail
case msOutlook
case spark
case yahooMail
case fastmail
case cancel

var localized: String {
switch self {
case .appleMail:
return NSLocalizedString("Mail (Default)", comment: "Option to select the Apple Mail app when logging in with magic links")
case .gmail:
return NSLocalizedString("Gmail", comment: "Option to select the Gmail app when logging in with magic links")
case .airmail:
return NSLocalizedString("Airmail", comment: "Option to select the Airmail app when logging in with magic links")
case .msOutlook:
return NSLocalizedString("Microsoft Outlook", comment: "Option to select the Microsft Outlook app when logging in with magic links")
case .spark:
return NSLocalizedString("Spark", comment: "Option to select the Spark email app when logging in with magic links")
case .yahooMail:
return NSLocalizedString("Yahoo Mail", comment: "Option to select the Yahoo Mail app when logging in with magic links")
case .fastmail:
return NSLocalizedString("Fastmail", comment: "Option to select the Fastmail app when logging in with magic links")
case .cancel:
return NSLocalizedString("Cancel", comment: "Option to cancel the email app selection when logging in with magic links")
}
}
}
Loading