diff --git a/WordPress/Classes/ViewRelated/NUX/LoginEmailViewController.swift b/WordPress/Classes/ViewRelated/NUX/LoginEmailViewController.swift index 4eb783c67a84..6c483ced8171 100644 --- a/WordPress/Classes/ViewRelated/NUX/LoginEmailViewController.swift +++ b/WordPress/Classes/ViewRelated/NUX/LoginEmailViewController.swift @@ -13,6 +13,7 @@ class LoginEmailViewController: LoginViewController, SigninKeyboardResponder { var didFindSafariSharedCredentials = false var didRequestSafariSharedCredentials = false + fileprivate var awaitingGoogle = false override var restrictToWPCom: Bool { didSet { if isViewLoaded { @@ -144,10 +145,9 @@ class LoginEmailViewController: LoginViewController, SigninKeyboardResponder { } func googleLoginTapped() { - // For paranoia, make sure a Google account is not already signed in / cached. + awaitingGoogle = true GIDSignIn.sharedInstance().disconnect() - // Configure all the things and sign in. GIDSignIn.sharedInstance().delegate = self GIDSignIn.sharedInstance().uiDelegate = self GIDSignIn.sharedInstance().clientID = ApiCredentials.googleLoginClientId() @@ -309,8 +309,17 @@ class LoginEmailViewController: LoginViewController, SigninKeyboardResponder { override func displayRemoteError(_ error: Error!) { configureViewLoading(false) - errorToPresent = error - performSegue(withIdentifier: .showWPComLogin, sender: self) + if awaitingGoogle { + awaitingGoogle = false + + let socialErrorVC = LoginSocialErrorViewController(title: NSLocalizedString("Unable To Connect", comment: "Shown when a user logs in with Google but it subsequently fails to work as login to WordPress.com"), description: error.localizedDescription) + let socialErrorNav = LoginNavigationController(rootViewController: socialErrorVC) + socialErrorVC.delegate = self + present(socialErrorNav, animated: true) {} + } else { + errorToPresent = error + performSegue(withIdentifier: .showWPComLogin, sender: self) + } } @@ -414,5 +423,27 @@ extension LoginEmailViewController: GIDSignInDelegate { } } +extension LoginEmailViewController: LoginSocialErrorViewControllerDelegate { + private func cleanupAfterSocialErrors() { + loginFields.username = "" + dismiss(animated: true) {} + } + + func retryWithEmail() { + cleanupAfterSocialErrors() + } + func retryWithAddress() { + cleanupAfterSocialErrors() + loginToSelfHostedSite() + } + func retryAsSignup() { + cleanupAfterSocialErrors() + let storyboard = UIStoryboard(name: "Login", bundle: nil) + if let controller = storyboard.instantiateViewController(withIdentifier: "SignupViewController") as? NUXAbstractViewController { + navigationController?.pushViewController(controller, animated: true) + } + } +} + extension LoginEmailViewController: GIDSignInUIDelegate { } diff --git a/WordPress/Classes/ViewRelated/NUX/LoginSocialErrorCell.swift b/WordPress/Classes/ViewRelated/NUX/LoginSocialErrorCell.swift new file mode 100644 index 000000000000..7e3fcecd638e --- /dev/null +++ b/WordPress/Classes/ViewRelated/NUX/LoginSocialErrorCell.swift @@ -0,0 +1,65 @@ +class LoginSocialErrorCell: UITableViewCell { + private let errorTitle: String + private let errorDescription: String + private let titleLabel: UILabel + private let descriptionLabel: UILabel + private let labelStack: UIStackView + + private struct Constants { + static let labelSpacing: CGFloat = 15.0 + static let labelVerticalMargin: CGFloat = 20.0 + static let descriptionMinHeight: CGFloat = 14.0 + } + + init(title: String, description: String) { + errorTitle = title + errorDescription = description + titleLabel = UILabel() + descriptionLabel = UILabel() + labelStack = UIStackView() + + super.init(style: .default, reuseIdentifier: "LoginSocialErrorCell") + + layoutLabels() + } + + required init?(coder aDecoder: NSCoder) { + errorTitle = aDecoder.value(forKey: "errorTitle") as? String ?? "" + errorDescription = aDecoder.value(forKey: "errorDescription") as? String ?? "" + titleLabel = UILabel() + descriptionLabel = UILabel() + labelStack = UIStackView() + + super.init(coder: aDecoder) + + layoutLabels() + } + + private func layoutLabels() { + contentView.addSubview(labelStack) + labelStack.translatesAutoresizingMaskIntoConstraints = false + labelStack.addArrangedSubview(titleLabel) + labelStack.addArrangedSubview(descriptionLabel) + labelStack.axis = .vertical + labelStack.spacing = Constants.labelSpacing + + titleLabel.font = WPStyleGuide.fontForTextStyle(.footnote) + titleLabel.textColor = WPStyleGuide.greyDarken30() + descriptionLabel.font = WPStyleGuide.mediumWeightFont(forStyle: .subheadline) + descriptionLabel.textColor = WPStyleGuide.darkGrey() + descriptionLabel.numberOfLines = 0 + descriptionLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: Constants.descriptionMinHeight).isActive = true + + contentView.addConstraints([ + contentView.topAnchor.constraint(equalTo: labelStack.topAnchor, constant: Constants.labelVerticalMargin * -1.0), + contentView.bottomAnchor.constraint(equalTo: labelStack.bottomAnchor, constant: Constants.labelVerticalMargin), + contentView.layoutMarginsGuide.leadingAnchor.constraint(equalTo: labelStack.leadingAnchor), + contentView.layoutMarginsGuide.trailingAnchor.constraint(equalTo: labelStack.trailingAnchor) + ]) + + titleLabel.text = errorTitle.localizedUppercase + descriptionLabel.text = errorDescription + + backgroundColor = WPStyleGuide.greyLighten30() + } +} diff --git a/WordPress/Classes/ViewRelated/NUX/LoginSocialErrorViewController.swift b/WordPress/Classes/ViewRelated/NUX/LoginSocialErrorViewController.swift new file mode 100644 index 000000000000..c7982d3604da --- /dev/null +++ b/WordPress/Classes/ViewRelated/NUX/LoginSocialErrorViewController.swift @@ -0,0 +1,168 @@ +import Foundation +import Gridicons + +@objc +protocol LoginSocialErrorViewControllerDelegate { + func retryWithEmail() + func retryWithAddress() + func retryAsSignup() +} + +/// ViewController for presenting recovery options when social login fails +class LoginSocialErrorViewController: UITableViewController, LoginWithLogoAndHelpViewController { + fileprivate var errorTitle: String + fileprivate var errorDescription: String + var delegate: LoginSocialErrorViewControllerDelegate? + + fileprivate enum Sections: Int { + case titleAndDescription = 0 + case buttons = 1 + + static var count: Int { + return buttons.rawValue + 1 + } + } + + fileprivate enum Buttons: Int { + case tryEmail = 0 + case tryAddress = 1 + case signup = 2 + } + + /// Create and instance of LoginSocialErrorViewController + /// + /// - Parameters: + /// - title: The title that will be shown on the error VC + /// - description: A brief explination of what failed during social login + init(title: String, description: String) { + errorTitle = title + errorDescription = description + + super.init(nibName: nil, bundle: nil) + } + + required init?(coder aDecoder: NSCoder) { + errorTitle = aDecoder.value(forKey: "errorTitle") as? String ?? "" + errorDescription = aDecoder.value(forKey: "errorDescription") as? String ?? "" + + super.init(coder: aDecoder) + } + + override func viewDidLoad() { + super.viewDidLoad() + + view.backgroundColor = WPStyleGuide.greyLighten30() + addHelpButtonToNavController() + addWordPressLogoToNavController() + } + + override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { + guard indexPath.section == Sections.buttons.rawValue, + let delegate = delegate else { + return + } + + switch indexPath.row { + case Buttons.tryEmail.rawValue: + delegate.retryWithEmail() + case Buttons.tryAddress.rawValue: + delegate.retryWithAddress() + case Buttons.signup.rawValue: + fallthrough + default: + delegate.retryAsSignup() + } + } +} + + +// MARK: UITableViewDelegate methods + +extension LoginSocialErrorViewController { + private struct RowHeightConstants { + static let estimate: CGFloat = 45.0 + static let automatic: CGFloat = UITableViewAutomaticDimension + } + + override func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat { + return RowHeightConstants.estimate + } + + override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { + return RowHeightConstants.automatic + } +} + + +// MARK: UITableViewDataSource methods + +extension LoginSocialErrorViewController { + private struct Constants { + static let buttonCount = 3 + } + + override func numberOfSections(in tableView: UITableView) -> Int { + return Sections.count + } + + override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { + switch section { + case Sections.titleAndDescription.rawValue: + return 1 + case Sections.buttons.rawValue: + return Constants.buttonCount + default: + return 0 + } + } + + override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { + let cell: UITableViewCell + switch indexPath.section { + case Sections.titleAndDescription.rawValue: + cell = titleAndDescriptionCell() + case Sections.buttons.rawValue: + fallthrough + default: + cell = buttonCell(index: indexPath.row) + } + return cell + } + + override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? { + let footer = UIView() + footer.backgroundColor = WPStyleGuide.greyLighten20() + return footer + } + + override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat { + return 0.5 + } + + private func titleAndDescriptionCell() -> UITableViewCell { + return LoginSocialErrorCell(title: errorTitle, description: errorDescription) + } + + private func buttonCell(index: Int) -> UITableViewCell { + let cell = UITableViewCell() + let buttonText: String + let buttonIcon: UIImage + switch index { + case Buttons.tryEmail.rawValue: + buttonText = NSLocalizedString("Try with another email", comment: "When social login fails, this button offers to let the user try again with a differen email address") + buttonIcon = Gridicon.iconOfType(.undo) + case Buttons.tryAddress.rawValue: + buttonText = NSLocalizedString("Try with the site address", comment: "When social login fails, this button offers to let them try tp login using a URL") + buttonIcon = Gridicon.iconOfType(.domains) + case Buttons.signup.rawValue: + fallthrough + default: + buttonText = NSLocalizedString("Sign up", comment: "When social login fails, this button offers to let them signup for a new WordPress.com account") + buttonIcon = Gridicon.iconOfType(.mySites) + } + cell.textLabel?.text = buttonText + cell.textLabel?.textColor = WPStyleGuide.darkGrey() + cell.imageView?.image = buttonIcon.imageWithTintColor(WPStyleGuide.grey()) + return cell + } +} diff --git a/WordPress/Classes/ViewRelated/NUX/LoginViewController.swift b/WordPress/Classes/ViewRelated/NUX/LoginViewController.swift index 28958d1c59cc..5680875fcbed 100644 --- a/WordPress/Classes/ViewRelated/NUX/LoginViewController.swift +++ b/WordPress/Classes/ViewRelated/NUX/LoginViewController.swift @@ -1,7 +1,58 @@ import Foundation import Gridicons -class LoginViewController: NUXAbstractViewController { +protocol LoginWithLogoAndHelpViewController { + func addWordPressLogoToNavController() + func addHelpButtonToNavController() -> (UIButton, WPNUXHelpBadgeLabel) +} + +extension LoginWithLogoAndHelpViewController where Self: UIViewController { + func addWordPressLogoToNavController() { + let image = Gridicon.iconOfType(.mySites) + let imageView = UIImageView(image: image.imageWithTintColor(UIColor.white)) + navigationItem.titleView = imageView + } + func addHelpButtonToNavController() -> (UIButton, WPNUXHelpBadgeLabel) { + let helpButtonMarginSpacerWidth = CGFloat(-8) + let helpBadgeSize = CGSize(width: 12, height: 10) + let helpButtonContainerFrame = CGRect(x: 0, y: 0, width: 44, height: 44) + + NotificationCenter.default.addObserver(self, selector: #selector(NUXAbstractViewController.handleHelpshiftUnreadCountUpdated(_:)), name: NSNotification.Name.HelpshiftUnreadCountUpdated, object: nil) + + let customView = UIView(frame: helpButtonContainerFrame) + + let helpButton = UIButton(type: .custom) + helpButton.setTitle(NSLocalizedString("Help", comment: "Help button"), for: .normal) + helpButton.setTitleColor(UIColor(white: 1.0, alpha: 0.4), for: .highlighted) + helpButton.addTarget(self, action: #selector(NUXAbstractViewController.handleHelpButtonTapped(_:)), for: .touchUpInside) + + customView.addSubview(helpButton) + helpButton.translatesAutoresizingMaskIntoConstraints = false + helpButton.leadingAnchor.constraint(equalTo: customView.leadingAnchor).isActive = true + helpButton.trailingAnchor.constraint(equalTo: customView.trailingAnchor).isActive = true + helpButton.topAnchor.constraint(equalTo: customView.topAnchor).isActive = true + helpButton.bottomAnchor.constraint(equalTo: customView.bottomAnchor).isActive = true + + let helpBadge = WPNUXHelpBadgeLabel() + helpBadge.translatesAutoresizingMaskIntoConstraints = false + helpBadge.isHidden = true + customView.addSubview(helpBadge) + helpBadge.centerXAnchor.constraint(equalTo: helpButton.trailingAnchor).isActive = true + helpBadge.centerYAnchor.constraint(equalTo: helpButton.topAnchor).isActive = true + helpBadge.widthAnchor.constraint(equalToConstant: helpBadgeSize.width).isActive = true + helpBadge.heightAnchor.constraint(equalToConstant: helpBadgeSize.height).isActive = true + + let spacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) + spacer.width = helpButtonMarginSpacerWidth + + let barButton = UIBarButtonItem(customView: customView) + navigationItem.rightBarButtonItems = [spacer, barButton] + + return (helpButton, helpBadge) + } +} + +class LoginViewController: NUXAbstractViewController, LoginWithLogoAndHelpViewController { @IBOutlet var instructionLabel: UILabel? @IBOutlet var errorLabel: UILabel? @IBOutlet var submitButton: NUXSubmitButton? @@ -33,9 +84,7 @@ class LoginViewController: NUXAbstractViewController { /// Places the WordPress logo in the navbar /// func setupNavBarIcon() { - let image = Gridicon.iconOfType(.mySites) - let imageView = UIImageView(image: image.imageWithTintColor(UIColor.white)) - navigationItem.titleView = imageView + addWordPressLogoToNavController() } /// Configures instruction label font @@ -47,36 +96,9 @@ class LoginViewController: NUXAbstractViewController { /// Sets up the help button and the helpshift conversation badge. /// override func setupHelpButtonAndBadge() { - NotificationCenter.default.addObserver(self, selector: #selector(NUXAbstractViewController.handleHelpshiftUnreadCountUpdated(_:)), name: NSNotification.Name.HelpshiftUnreadCountUpdated, object: nil) - - let customView = UIView(frame: helpButtonContainerFrame) - - helpButton = UIButton(type: .custom) - helpButton.setTitle(NSLocalizedString("Help", comment: "Help button"), for: .normal) - helpButton.setTitleColor(UIColor(white: 1.0, alpha: 0.4), for: .highlighted) - helpButton.addTarget(self, action: #selector(NUXAbstractViewController.handleHelpButtonTapped(_:)), for: .touchUpInside) - - customView.addSubview(helpButton) - helpButton.translatesAutoresizingMaskIntoConstraints = false - helpButton.leadingAnchor.constraint(equalTo: customView.leadingAnchor).isActive = true - helpButton.trailingAnchor.constraint(equalTo: customView.trailingAnchor).isActive = true - helpButton.topAnchor.constraint(equalTo: customView.topAnchor).isActive = true - helpButton.bottomAnchor.constraint(equalTo: customView.bottomAnchor).isActive = true - - helpBadge = WPNUXHelpBadgeLabel() - helpBadge.translatesAutoresizingMaskIntoConstraints = false - helpBadge.isHidden = true - customView.addSubview(helpBadge) - helpBadge.centerXAnchor.constraint(equalTo: helpButton.trailingAnchor).isActive = true - helpBadge.centerYAnchor.constraint(equalTo: helpButton.topAnchor).isActive = true - helpBadge.widthAnchor.constraint(equalToConstant: helpBadgeSize.width).isActive = true - helpBadge.heightAnchor.constraint(equalToConstant: helpBadgeSize.height).isActive = true - - let spacer = UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) - spacer.width = helpButtonMarginSpacerWidth - - let barButton = UIBarButtonItem(customView: customView) - navigationItem.rightBarButtonItems = [spacer, barButton] + let (helpButtonResult, helpBadgeResult) = addHelpButtonToNavController() + helpButton = helpButtonResult + helpBadge = helpBadgeResult } /// Sets the text of the error label. diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 5f6db62c4e3f..086f99e6ccb6 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -200,6 +200,8 @@ 43D2AE441EF704A70009387E /* LoginProloguePromoViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D2AE431EF704A70009387E /* LoginProloguePromoViewController.swift */; }; 43D54D131DCAA070007F575F /* PostPostViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43D54D121DCAA070007F575F /* PostPostViewController.swift */; }; 43F258AA1ED7772C0075406B /* LoginPrologueViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F258A91ED7772C0075406B /* LoginPrologueViewController.swift */; }; + 43F283C01F82DEAC00DC00F1 /* LoginSocialErrorCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43C5A3E11F80AED50008BE81 /* LoginSocialErrorCell.swift */; }; + 43F283C11F82DEAE00DC00F1 /* LoginSocialErrorViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43F295951F7EA74E00E51E2A /* LoginSocialErrorViewController.swift */; }; 43FB3F411EBD215C00FC8A62 /* LoginEpilogueBlogCell.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43FB3F401EBD215C00FC8A62 /* LoginEpilogueBlogCell.swift */; }; 43FB3F431EC0DDAD00FC8A62 /* LoginEpilogueSectionHeader.xib in Resources */ = {isa = PBXBuildFile; fileRef = 43FB3F421EC0DDAD00FC8A62 /* LoginEpilogueSectionHeader.xib */; }; 43FB3F451EC1020600FC8A62 /* LoginEpilogueSectionHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 43FB3F441EC1020600FC8A62 /* LoginEpilogueSectionHeader.swift */; }; @@ -1288,12 +1290,14 @@ 43A85B301E9E815B00FA990B /* Login.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = Login.storyboard; sourceTree = ""; }; 43AB7C5D1D3E70510066CB6A /* PostListFilterSettings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostListFilterSettings.swift; sourceTree = ""; }; 43AD9F9B1F4F756C00565CE6 /* LoginTextButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginTextButton.swift; sourceTree = ""; }; + 43C5A3E11F80AED50008BE81 /* LoginSocialErrorCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginSocialErrorCell.swift; sourceTree = ""; }; 43CC1EBF1ED898E30097E334 /* LoginTextField.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginTextField.swift; sourceTree = ""; }; 43CE48B21F103C1F00768B87 /* FancyAlertViewController+LoginError.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "FancyAlertViewController+LoginError.swift"; sourceTree = ""; }; 43D2436C1EAFCE3C00D0C77B /* LoginSegueHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginSegueHandler.swift; sourceTree = ""; }; 43D2AE431EF704A70009387E /* LoginProloguePromoViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginProloguePromoViewController.swift; sourceTree = ""; }; 43D54D121DCAA070007F575F /* PostPostViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PostPostViewController.swift; sourceTree = ""; }; 43F258A91ED7772C0075406B /* LoginPrologueViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginPrologueViewController.swift; sourceTree = ""; }; + 43F295951F7EA74E00E51E2A /* LoginSocialErrorViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = LoginSocialErrorViewController.swift; sourceTree = ""; }; 43FB3F401EBD215C00FC8A62 /* LoginEpilogueBlogCell.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginEpilogueBlogCell.swift; sourceTree = ""; }; 43FB3F421EC0DDAD00FC8A62 /* LoginEpilogueSectionHeader.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = LoginEpilogueSectionHeader.xib; sourceTree = ""; }; 43FB3F441EC1020600FC8A62 /* LoginEpilogueSectionHeader.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = LoginEpilogueSectionHeader.swift; sourceTree = ""; }; @@ -3055,6 +3059,15 @@ path = Animations; sourceTree = ""; }; + 43F295941F7EA72800E51E2A /* Social Login */ = { + isa = PBXGroup; + children = ( + 43F295951F7EA74E00E51E2A /* LoginSocialErrorViewController.swift */, + 43C5A3E11F80AED50008BE81 /* LoginSocialErrorCell.swift */, + ); + name = "Social Login"; + sourceTree = ""; + }; 45C73C23113C36F50024D0D2 /* Resources-iPad */ = { isa = PBXGroup; children = ( @@ -5050,6 +5063,7 @@ E6C1E8441EF1D25D00D139D9 /* Magic Links */, E6C1E8451EF1D28500D139D9 /* SelfHosted */, E6C1E8431EF1D21F00D139D9 /* Epilogue */, + 43F295941F7EA72800E51E2A /* Social Login */, 434D96051EA92A4A00B90B89 /* Login2FAViewController.swift */, 438A80971EA5666B005D4651 /* LoginEmailViewController.swift */, 438A809D1EA5DC31005D4651 /* LoginWPComViewController.swift */, @@ -6080,6 +6094,7 @@ B587797D19B799D800E57C5A /* UIDevice+Helpers.swift in Sources */, E2AA87A518523E5300886693 /* UIView+Subviews.m in Sources */, 5D51ADAF19A832AF00539C0B /* WordPress-20-21.xcmappingmodel in Sources */, + 43F283C01F82DEAC00DC00F1 /* LoginSocialErrorCell.swift in Sources */, 434D96061EA92A4A00B90B89 /* Login2FAViewController.swift in Sources */, 43FB3F471EC10F1E00FC8A62 /* LoginEpilogueTableView.swift in Sources */, 93C486511810445D00A24725 /* ActivityLogViewController.m in Sources */, @@ -6339,6 +6354,7 @@ 5926E1E31AC4468300964783 /* WPCrashlytics.m in Sources */, E16273E11B2ACEB600088AF7 /* BlogToBlog32to33.swift in Sources */, E678FC151C76241000F55F55 /* WPStyleGuide+ApplicationStyles.swift in Sources */, + 43F283C11F82DEAE00DC00F1 /* LoginSocialErrorViewController.swift in Sources */, E66EB6F91C1B7A76003DABC5 /* ReaderSpacerView.swift in Sources */, B55853F31962337500FAF6C3 /* NSScanner+Helpers.m in Sources */, 17EC9FC61DDC761D00D5BE8E /* UIWindow+Helpers.swift in Sources */,