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

Commit 206fee7

Browse files
authored
Merge pull request #170 from wordpress-mobile/issue/wp-13086-self-hosted-voiceover
[VoiceOver] Self-hosted Login Flow enhancements
2 parents 4ed0ead + f37be30 commit 206fee7

File tree

7 files changed

+65
-6
lines changed

7 files changed

+65
-6
lines changed

WordPressAuthenticator.podspec

Lines changed: 1 addition & 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.5"
3+
s.version = "1.10.6-beta.1"
44
s.summary = "WordPressAuthenticator implements an easy and elegant way to authenticate your WordPress Apps."
55

66
s.description = <<-DESC

WordPressAuthenticator/Authenticator/WordPressAuthenticatorDisplayStrings.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,6 @@ public extension WordPressAuthenticatorDisplayStrings {
2525
static var defaultStrings: WordPressAuthenticatorDisplayStrings {
2626
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."),
2727
jetpackLoginInstructions: NSLocalizedString("Log in to the WordPress.com account you used to connect Jetpack.", comment: "Instruction text on the login's email address screen."),
28-
siteLoginInstructions: NSLocalizedString("Enter the address of your WordPress site you'd like to connect.", comment: "Instruction text on the login's site addresss screen."))
28+
siteLoginInstructions: NSLocalizedString("Enter the address of the WordPress site you'd like to connect.", comment: "Instruction text on the login's site addresss screen."))
2929
}
3030
}

WordPressAuthenticator/Extensions/WPStyleGuide+Login.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,9 @@ extension WPStyleGuide {
4747
onePasswordButton.setImage(.onePasswordImage, for: .normal)
4848
onePasswordButton.sizeToFit()
4949

50+
onePasswordButton.accessibilityLabel =
51+
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). ")
52+
5053
textField.rightView = onePasswordButton
5154
textField.rightViewMode = .always
5255

WordPressAuthenticator/NUX/WPWalkthroughTextField.m

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ - (void)configureSecureTextEntryToggle {
120120
[self.secureTextEntryToggle addTarget:self action:@selector(secureTextEntryToggleAction:) forControlEvents:UIControlEventTouchUpInside];
121121

122122
[self updateSecureTextEntryToggleImage];
123+
[self updateSecureTextEntryForAccessibility];
124+
123125
self.rightView = self.secureTextEntryToggle;
124126
self.rightViewMode = UITextFieldViewModeAlways;
125127
}
@@ -253,6 +255,7 @@ - (void)setSecureTextEntry:(BOOL)secureTextEntry
253255

254256
[super setSecureTextEntry:secureTextEntry];
255257
[self updateSecureTextEntryToggleImage];
258+
[self updateSecureTextEntryForAccessibility];
256259
}
257260

258261
- (void)secureTextEntryToggleAction:(id)sender
@@ -272,4 +275,17 @@ - (void)updateSecureTextEntryToggleImage
272275
[self.secureTextEntryToggle sizeToFit];
273276
}
274277

278+
- (void)updateSecureTextEntryForAccessibility
279+
{
280+
self.secureTextEntryToggle.accessibilityLabel = NSLocalizedString(@"Show password", @"Accessibility label for the “Show password“ button in the login page's password field.");
281+
282+
NSString *accessibilityValue;
283+
if (self.isSecureTextEntry) {
284+
accessibilityValue = NSLocalizedString(@"Hidden", "Accessibility value if login page's password field is hiding the password (i.e. with asterisks).");
285+
} else {
286+
accessibilityValue = NSLocalizedString(@"Shown", "Accessibility value if login page's password field is displaying the password.");
287+
}
288+
self.secureTextEntryToggle.accessibilityValue = accessibilityValue;
289+
}
290+
275291
@end

WordPressAuthenticator/Signin/LoginSelfHostedViewController.swift

Lines changed: 24 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder {
3636
localizeControls()
3737
setupOnePasswordButtonIfNeeded()
3838
displayLoginMessage("")
39+
configureForAcessibility()
3940
}
4041

4142

@@ -90,6 +91,26 @@ class LoginSelfHostedViewController: LoginViewController, NUXKeyboardResponder {
9091
}
9192

9293

94+
/// Sets up necessary accessibility labels and attributes for the all the UI elements in self.
95+
///
96+
private func configureForAcessibility() {
97+
usernameField.accessibilityLabel =
98+
NSLocalizedString("Username", comment: "Accessibility label for the username text field in the self-hosted login page.")
99+
passwordField.accessibilityLabel =
100+
NSLocalizedString("Password", comment: "Accessibility label for the password text field in the self-hosted login page.")
101+
102+
if UIAccessibility.isVoiceOverRunning {
103+
// Remove the placeholder if VoiceOver is running. VoiceOver speaks the label and the
104+
// placeholder together. In this case, both labels and placeholders are the same so it's
105+
// like VoiceOver is reading the same thing twice.
106+
usernameField.placeholder = nil
107+
passwordField.placeholder = nil
108+
}
109+
110+
forgotPasswordButton.accessibilityTraits = .link
111+
}
112+
113+
93114
/// Sets up a 1Password button if 1Password is available.
94115
///
95116
@objc func setupOnePasswordButtonIfNeeded() {
@@ -294,7 +315,9 @@ extension LoginSelfHostedViewController {
294315
configureViewLoading(false)
295316
let err = error as NSError
296317
if err.code == 403 {
297-
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."))
318+
let message = NSLocalizedString("It looks like this username/password isn't associated with this site.",
319+
comment: "An error message shown during log in when the username or password is incorrect.")
320+
displayError(message: message, moveVoiceOverFocus: true)
298321
} else {
299322
displayError(error as NSError, sourceTag: sourceTag)
300323
}

WordPressAuthenticator/Signin/LoginSiteAddressViewController.swift

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder
3737
override func viewDidLoad() {
3838
super.viewDidLoad()
3939
localizeControls()
40+
configureForAccessibility()
4041
}
4142

4243

@@ -90,6 +91,12 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder
9091
siteAddressHelpButton.titleLabel?.numberOfLines = 0
9192
}
9293

94+
/// Sets up necessary accessibility labels and attributes for the all the UI elements in self.
95+
///
96+
private func configureForAccessibility() {
97+
siteURLField.accessibilityLabel =
98+
NSLocalizedString("Site address", comment: "Accessibility label of the site address field shown when adding a self-hosted site.")
99+
}
93100

94101
/// Configures the content of the text fields based on what is saved in `loginFields`.
95102
///
@@ -178,15 +185,15 @@ class LoginSiteAddressViewController: LoginViewController, NUXKeyboardResponder
178185
let err = self.originalErrorOrError(error: error as NSError)
179186

180187
if let xmlrpcValidatorError = err as? WordPressOrgXMLRPCValidatorError {
181-
self.displayError(message: xmlrpcValidatorError.localizedDescription)
188+
self.displayError(message: xmlrpcValidatorError.localizedDescription, moveVoiceOverFocus: true)
182189

183190
} else if (err.domain == NSURLErrorDomain && err.code == NSURLErrorCannotFindHost) ||
184191
(err.domain == NSURLErrorDomain && err.code == NSURLErrorNetworkConnectionLost) {
185192
// NSURLErrorNetworkConnectionLost can be returned when an invalid URL is entered.
186193
let msg = NSLocalizedString(
187194
"The site at this address is not a WordPress site. For us to connect to it, the site must use WordPress.",
188195
comment: "Error message shown a URL does not point to an existing site.")
189-
self.displayError(message: msg)
196+
self.displayError(message: msg, moveVoiceOverFocus: true)
190197

191198
} else {
192199
self.displayError(error as NSError, sourceTag: self.sourceTag)

WordPressAuthenticator/Signin/LoginViewController.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,14 +82,24 @@ open class LoginViewController: NUXViewController, LoginFacadeDelegate {
8282
}
8383

8484
/// Sets the text of the error label.
85-
func displayError(message: String) {
85+
///
86+
/// - Parameter message: The message to display in the `errorLabel`. If empty, the `errorLabel`
87+
/// will be hidden.
88+
/// - Parameter moveVoiceOverFocus: If `true`, moves the VoiceOver focus to the `errorLabel`.
89+
/// You will want to set this to `true` if the error was caused after pressing a button
90+
/// (e.g. Next button).
91+
func displayError(message: String, moveVoiceOverFocus: Bool = false) {
8692
guard message.count > 0 else {
8793
errorLabel?.isHidden = true
8894
return
8995
}
9096
errorLabel?.isHidden = false
9197
errorLabel?.text = message
9298
errorToPresent = nil
99+
100+
if moveVoiceOverFocus, let errorLabel = errorLabel {
101+
UIAccessibility.post(notification: .layoutChanged, argument: errorLabel)
102+
}
93103
}
94104

95105
private func mustShowLoginEpilogue() -> Bool {

0 commit comments

Comments
 (0)