Skip to content
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
39 changes: 35 additions & 4 deletions WordPress/Classes/ViewRelated/NUX/LoginEmailViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -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()
Expand Down Expand Up @@ -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)
}
}


Expand Down Expand Up @@ -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 {
}
65 changes: 65 additions & 0 deletions WordPress/Classes/ViewRelated/NUX/LoginSocialErrorCell.swift
Original file line number Diff line number Diff line change
@@ -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()
}
}
168 changes: 168 additions & 0 deletions WordPress/Classes/ViewRelated/NUX/LoginSocialErrorViewController.swift
Original file line number Diff line number Diff line change
@@ -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

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this method can be removed if tableView:viewForFooterInSection: returns UIView(frame: .zero). Seems that way when I test. Same for setting the footer.backgroundColor

@nheagy nheagy Oct 3, 2017

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This draws the dark line above and below the button cells.

The initial frame size of .zero will be ignored/modified by autolayout.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I totally missed that there were lines in the mock. Totally makes sense now. :)

The initial frame size of .zero will be ignored/modified by autolayout

This hasn't been my experience, but whatev 🤷‍♂️

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I usually just do UIView() not sure why I decided to use UIView(frame: .zero) here 😜 I'll probably switch it to the former, to make the result more clear.

}

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
}
}
Loading