From dd1cc245ac0959c656e2862f60bbb42a0246c59b Mon Sep 17 00:00:00 2001 From: Shiki Date: Thu, 12 Dec 2019 15:13:30 -0700 Subject: [PATCH 01/11] LoginSelfHosted: Add a11y label for URL field --- .../Signin/LoginSiteAddressViewController.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift index e51faf76b..28317c52b 100644 --- a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift @@ -37,6 +37,7 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder override func viewDidLoad() { super.viewDidLoad() localizeControls() + configureForAccessibility() } @@ -90,6 +91,10 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder siteAddressHelpButton.titleLabel?.numberOfLines = 0 } + private func configureForAccessibility() { + siteURLField.accessibilityLabel = + NSLocalizedString("Site address", comment: "Accessibility label of the site address field shown when adding a self-hosted site.") + } /// Configures the content of the text fields based on what is saved in `loginFields`. /// From f68cc1deeea4cdb6fd984fa240cb59400adb3cea Mon Sep 17 00:00:00 2001 From: Shiki Date: Thu, 12 Dec 2019 15:39:07 -0700 Subject: [PATCH 02/11] LoginSiteAddressVC: Focus on error label if needed For errors shown on the error label and triggered by the Next button, this makes VoiceOver focus on the error label so that it will speak the contents. --- .../Signin/LoginSiteAddressViewController.swift | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift index 28317c52b..80ae82ca8 100644 --- a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift @@ -180,10 +180,17 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder WordPressAuthenticator.track(.loginFailed, error: error) self.configureViewLoading(false) + let displayAndFocusOnErrorLabel: (String) -> () = { message in + if let errorLabel = self.errorLabel { + UIAccessibility.post(notification: .layoutChanged, argument: self.errorLabel) + } + self.displayError(message: message) + } + let err = self.originalErrorOrError(error: error as NSError) if let xmlrpcValidatorError = err as? WordPressOrgXMLRPCValidatorError { - self.displayError(message: xmlrpcValidatorError.localizedDescription) + displayAndFocusOnErrorLabel(xmlrpcValidatorError.localizedDescription) } else if (err.domain == NSURLErrorDomain && err.code == NSURLErrorCannotFindHost) || (err.domain == NSURLErrorDomain && err.code == NSURLErrorNetworkConnectionLost) { @@ -191,7 +198,7 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder let msg = NSLocalizedString( "The site at this address is not a WordPress site. For us to connect to it, the site must use WordPress.", comment: "Error message shown a URL does not point to an existing site.") - self.displayError(message: msg) + displayAndFocusOnErrorLabel(msg) } else { self.displayError(error as NSError, sourceTag: self.sourceTag) From 0c3a93ff5bf435f8b059fb4973dbf1d6ffc492d4 Mon Sep 17 00:00:00 2001 From: Shiki Date: Thu, 12 Dec 2019 15:42:54 -0700 Subject: [PATCH 03/11] Login Self-hosted: Fix instructions --- .../Authenticator/WordPressAuthenticatorDisplayStrings.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDisplayStrings.swift b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDisplayStrings.swift index 2224db768..0fa5e7b4e 100644 --- a/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDisplayStrings.swift +++ b/WordPressAuthenticator/Authenticator/WordPressAuthenticatorDisplayStrings.swift @@ -25,6 +25,6 @@ public extension WordPressAuthenticatorDisplayStrings { static var defaultStrings: WordPressAuthenticatorDisplayStrings { return WordPressAuthenticatorDisplayStrings(emailLoginInstructions: NSLocalizedString("Log in to your WordPress.com account with your email address.", comment: "Instruction text on the login's email address screen."), jetpackLoginInstructions: NSLocalizedString("Log in to the WordPress.com account you used to connect Jetpack.", comment: "Instruction text on the login's email address screen."), - siteLoginInstructions: NSLocalizedString("Enter the address of your WordPress site you'd like to connect.", comment: "Instruction text on the login's site addresss screen.")) + siteLoginInstructions: NSLocalizedString("Enter the address of the WordPress site you'd like to connect.", comment: "Instruction text on the login's site addresss screen.")) } } From 34348290efebe8e602a6b0bd975b92a5e3eef44c Mon Sep 17 00:00:00 2001 From: Shiki Date: Thu, 12 Dec 2019 16:10:48 -0700 Subject: [PATCH 04/11] Self-hosted: Add a11y labels for username and pass --- .../Signin/LoginSelfHostedViewController.swift | 11 +++++++++++ .../Signin/LoginSiteAddressViewController.swift | 2 ++ 2 files changed, 13 insertions(+) diff --git a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift index 8db550889..2dccebf68 100644 --- a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift @@ -36,6 +36,7 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { localizeControls() setupOnePasswordButtonIfNeeded() displayLoginMessage("") + configureForAcessibility() } @@ -90,6 +91,16 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { } + /// Sets up necessary accessibility labels and attributes for the all the UI elements in self. + /// + private func configureForAcessibility() { + usernameField.accessibilityLabel = + NSLocalizedString("Username", comment: "Accessibility label for the username text field in the self-hosted login page.") + passwordField.accessibilityLabel = + NSLocalizedString("Password", comment: "Accessibility label for the password text field in the self-hosted login page.") + } + + /// Sets up a 1Password button if 1Password is available. /// @objc func setupOnePasswordButtonIfNeeded() { diff --git a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift index 80ae82ca8..295f2fb99 100644 --- a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift @@ -91,6 +91,8 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder siteAddressHelpButton.titleLabel?.numberOfLines = 0 } + /// Sets up necessary accessibility labels and attributes for the all the UI elements in self. + /// private func configureForAccessibility() { siteURLField.accessibilityLabel = NSLocalizedString("Site address", comment: "Accessibility label of the site address field shown when adding a self-hosted site.") From 77a4ba428e9b993007ba0a3939636a87dc6ee041 Mon Sep 17 00:00:00 2001 From: Shiki Date: Fri, 13 Dec 2019 10:52:26 -0700 Subject: [PATCH 05/11] LoginSelfHostedVC: Remove placeholder for VO --- .../Signin/LoginSelfHostedViewController.swift | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift index 2dccebf68..bc961f8a4 100644 --- a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift @@ -98,6 +98,14 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { NSLocalizedString("Username", comment: "Accessibility label for the username text field in the self-hosted login page.") passwordField.accessibilityLabel = NSLocalizedString("Password", comment: "Accessibility label for the password text field in the self-hosted login page.") + + if UIAccessibility.isVoiceOverRunning { + // Remove the placeholder if VoiceOver is running. VoiceOver speaks the label and the + // placeholder together. In this case, both labels and placeholders are the same so it's + // like VoiceOver is reading the same thing twice. + usernameField.placeholder = nil + passwordField.placeholder = nil + } } From b42f7777938b9676063984023192c687ea9bd5ab Mon Sep 17 00:00:00 2001 From: Shiki Date: Fri, 13 Dec 2019 10:58:43 -0700 Subject: [PATCH 06/11] Add a11y label for 1Password button --- WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift | 3 +++ 1 file changed, 3 insertions(+) diff --git a/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift b/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift index 29c086e88..7f4e3c031 100644 --- a/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift +++ b/WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift @@ -47,6 +47,9 @@ extension WPStyleGuide { onePasswordButton.setImage(.onePasswordImage, for: .normal) onePasswordButton.sizeToFit() + onePasswordButton.accessibilityLabel = + NSLocalizedString("Fill with password manager", comment: "The password manager button in login pages. The button opens a dialog showing which password manager to use (e.g. 1Password, LastPass). ") + textField.rightView = onePasswordButton textField.rightViewMode = .always From 2dcd8ec19472e8dd7325bd89f53cd0c7bb109c6c Mon Sep 17 00:00:00 2001 From: Shiki Date: Fri, 13 Dec 2019 11:35:18 -0700 Subject: [PATCH 07/11] Add a11y label and value for Show Password button --- .../NUX/WPWalkthroughTextField.m | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/WordPressAuthenticator/NUX/WPWalkthroughTextField.m b/WordPressAuthenticator/NUX/WPWalkthroughTextField.m index 81c0c788c..e8896561c 100644 --- a/WordPressAuthenticator/NUX/WPWalkthroughTextField.m +++ b/WordPressAuthenticator/NUX/WPWalkthroughTextField.m @@ -120,6 +120,8 @@ - (void)configureSecureTextEntryToggle { [self.secureTextEntryToggle addTarget:self action:@selector(secureTextEntryToggleAction:) forControlEvents:UIControlEventTouchUpInside]; [self updateSecureTextEntryToggleImage]; + [self updateSecureTextEntryForAccessibility]; + self.rightView = self.secureTextEntryToggle; self.rightViewMode = UITextFieldViewModeAlways; } @@ -253,6 +255,7 @@ - (void)setSecureTextEntry:(BOOL)secureTextEntry [super setSecureTextEntry:secureTextEntry]; [self updateSecureTextEntryToggleImage]; + [self updateSecureTextEntryForAccessibility]; } - (void)secureTextEntryToggleAction:(id)sender @@ -272,4 +275,17 @@ - (void)updateSecureTextEntryToggleImage [self.secureTextEntryToggle sizeToFit]; } +- (void)updateSecureTextEntryForAccessibility +{ + self.secureTextEntryToggle.accessibilityLabel = NSLocalizedString(@"Show password", @"Accessibility label for the “Show password“ button in the login page's password field."); + + NSString *accessibilityValue; + if (self.isSecureTextEntry) { + accessibilityValue = NSLocalizedString(@"Hidden", "Accessibility value if login page's password field is hiding the password (i.e. with asterisks)."); + } else { + accessibilityValue = NSLocalizedString(@"Shown", "Accessibility value if login page's password field is displaying the password."); + } + self.secureTextEntryToggle.accessibilityValue = accessibilityValue; +} + @end From e7a6fb0d26dd7e3338bd7c64c4eef5ec5d81eff3 Mon Sep 17 00:00:00 2001 From: Shiki Date: Fri, 13 Dec 2019 12:08:28 -0700 Subject: [PATCH 08/11] LoginSelfHostedVC: Make forgotPassword a link The forgotPasswordButton opens Safari when tapped. Buttons with behaviors like this should be announced as a link by VoiceOver. --- .../Signin/LoginSelfHostedViewController.swift | 2 ++ 1 file changed, 2 insertions(+) diff --git a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift index bc961f8a4..49b697625 100644 --- a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift @@ -106,6 +106,8 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder { usernameField.placeholder = nil passwordField.placeholder = nil } + + forgotPasswordButton.accessibilityTraits = .link } From d36d0cafb49797a295eebb3a4d508a4235ee2522 Mon Sep 17 00:00:00 2001 From: Shiki Date: Fri, 13 Dec 2019 12:10:24 -0700 Subject: [PATCH 09/11] Refactor displayError to house VoiceOver focus The same functionality will be needed from other VCs later. --- .../Signin/LoginSiteAddressViewController.swift | 11 ++--------- .../Signin/LoginViewController.swift | 12 +++++++++++- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift index 295f2fb99..04b1d6238 100644 --- a/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift @@ -182,17 +182,10 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder WordPressAuthenticator.track(.loginFailed, error: error) self.configureViewLoading(false) - let displayAndFocusOnErrorLabel: (String) -> () = { message in - if let errorLabel = self.errorLabel { - UIAccessibility.post(notification: .layoutChanged, argument: self.errorLabel) - } - self.displayError(message: message) - } - let err = self.originalErrorOrError(error: error as NSError) if let xmlrpcValidatorError = err as? WordPressOrgXMLRPCValidatorError { - displayAndFocusOnErrorLabel(xmlrpcValidatorError.localizedDescription) + self.displayError(message: xmlrpcValidatorError.localizedDescription, moveVoiceOverFocus: true) } else if (err.domain == NSURLErrorDomain && err.code == NSURLErrorCannotFindHost) || (err.domain == NSURLErrorDomain && err.code == NSURLErrorNetworkConnectionLost) { @@ -200,7 +193,7 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder let msg = NSLocalizedString( "The site at this address is not a WordPress site. For us to connect to it, the site must use WordPress.", comment: "Error message shown a URL does not point to an existing site.") - displayAndFocusOnErrorLabel(msg) + self.displayError(message: msg, moveVoiceOverFocus: true) } else { self.displayError(error as NSError, sourceTag: self.sourceTag) diff --git a/WordPressAuthenticator/Signin/LoginViewController.swift b/WordPressAuthenticator/Signin/LoginViewController.swift index a41528fda..68cfadde3 100644 --- a/WordPressAuthenticator/Signin/LoginViewController.swift +++ b/WordPressAuthenticator/Signin/LoginViewController.swift @@ -82,7 +82,13 @@ open class LoginViewController: NUXViewController, LoginFacadeDelegate { } /// Sets the text of the error label. - func displayError(message: String) { + /// + /// - Parameter message: The message to display in the `errorLabel`. If empty, the `errorLabel` + /// will be hidden. + /// - Parameter moveVoiceOverFocus: If `true`, moves the VoiceOver focus to the `errorLabel`. + /// You will want to set this to `true` if the error was caused after pressing a button + /// (e.g. Next button). + func displayError(message: String, moveVoiceOverFocus: Bool = false) { guard message.count > 0 else { errorLabel?.isHidden = true return @@ -90,6 +96,10 @@ open class LoginViewController: NUXViewController, LoginFacadeDelegate { errorLabel?.isHidden = false errorLabel?.text = message errorToPresent = nil + + if moveVoiceOverFocus, let errorLabel = errorLabel { + UIAccessibility.post(notification: .layoutChanged, argument: errorLabel) + } } private func mustShowLoginEpilogue() -> Bool { From 9c8ba151eadb03386d5816782a7e943716149e53 Mon Sep 17 00:00:00 2001 From: Shiki Date: Fri, 13 Dec 2019 12:20:26 -0700 Subject: [PATCH 10/11] LoginSelfHostedVC: Announce errors --- .../Signin/LoginSelfHostedViewController.swift | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift index 49b697625..a009818ec 100644 --- a/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift +++ b/WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift @@ -315,7 +315,9 @@ extension LoginSelfHostedViewController { configureViewLoading(false) let err = error as NSError if err.code == 403 { - displayError(message: NSLocalizedString("It looks like this username/password isn't associated with this site.", comment: "An error message shown during log in when the username or password is incorrect.")) + let message = NSLocalizedString("It looks like this username/password isn't associated with this site.", + comment: "An error message shown during log in when the username or password is incorrect.") + displayError(message: message, moveVoiceOverFocus: true) } else { displayError(error as NSError, sourceTag: sourceTag) } From cafee3d971f3212631d8dd063980925db8ab9480 Mon Sep 17 00:00:00 2001 From: Shiki Date: Fri, 13 Dec 2019 12:30:04 -0700 Subject: [PATCH 11/11] Update podspec version to 1.10.5-beta.4 --- WordPressAuthenticator.podspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/WordPressAuthenticator.podspec b/WordPressAuthenticator.podspec index cd5adddaf..4cc86c2d5 100644 --- a/WordPressAuthenticator.podspec +++ b/WordPressAuthenticator.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = "WordPressAuthenticator" - s.version = "1.10.5-beta.3" + s.version = "1.10.5-beta.4" s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps." s.description = <<-DESC