diff --git a/firefox-ios/Client/AccessoryViewProvider.swift b/firefox-ios/Client/AccessoryViewProvider.swift index f29367cd96cb..f0f23a6ed365 100644 --- a/firefox-ios/Client/AccessoryViewProvider.swift +++ b/firefox-ios/Client/AccessoryViewProvider.swift @@ -7,7 +7,7 @@ import Common import Shared enum AccessoryType { - case standard, creditCard, address, login + case standard, creditCard, address, login, passwordGenerator } class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifiable { @@ -35,6 +35,7 @@ class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifiable { var savedCardsClosure: (() -> Void)? var savedAddressesClosure: (() -> Void)? var savedLoginsClosure: (() -> Void)? + var useStrongPasswordClosure: (() -> Void)? // MARK: - UI Elements private let toolbar: UIToolbar = .build { @@ -127,6 +128,20 @@ class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifiable { return accessoryView }() + private lazy var passwordGeneratorView: AutofillAccessoryViewButtonItem = { + let accessoryView = AutofillAccessoryViewButtonItem( + image: UIImage(named: StandardImageIdentifiers.Large.login), + labelText: .PasswordGenerator.KeyboardAccessoryButtonLabel, + tappedAction: { [weak self] in + self?.tappedUseStrongPasswordButton() + }) + accessoryView.accessibilityTraits = .button + accessoryView.accessibilityLabel = .PasswordAutofill.UseSavedPasswordFromKeyboard + accessoryView.accessibilityIdentifier = AccessibilityIdentifiers.Autofill.footerPrimaryAction + accessoryView.isAccessibilityElement = true + return accessoryView + }() + // MARK: - Initialization init(themeManager: ThemeManager = AppContainer.shared.resolve(), windowUUID: WindowUUID, @@ -169,6 +184,8 @@ class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifiable { currentAccessoryView = addressAutofillView case .login: currentAccessoryView = loginAutofillView + case .passwordGenerator: + currentAccessoryView = passwordGeneratorView } setNeedsLayout() @@ -224,7 +241,7 @@ class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifiable { $0.customView?.tintColor = theme.colors.iconAccentBlue } - [creditCardAutofillView, addressAutofillView, loginAutofillView].forEach { + [creditCardAutofillView, addressAutofillView, loginAutofillView, passwordGeneratorView].forEach { $0.accessoryImageViewTintColor = theme.colors.iconPrimary $0.backgroundColor = theme.colors.layer5Hover } @@ -262,6 +279,11 @@ class AccessoryViewProvider: UIView, Themeable, InjectedThemeUUIDIdentifiable { savedLoginsClosure?() } + @objc + private func tappedUseStrongPasswordButton() { + useStrongPasswordClosure?() + } + // MARK: - Telemetry fileprivate func sendCreditCardAutofillPromptShownTelemetry() { TelemetryWrapper.recordEvent(category: .action, diff --git a/firefox-ios/Client/Frontend/PasswordGenerator/PasswordGeneratorViewController.swift b/firefox-ios/Client/Frontend/PasswordGenerator/PasswordGeneratorViewController.swift index 6a5d3a4787d5..63068281db62 100644 --- a/firefox-ios/Client/Frontend/PasswordGenerator/PasswordGeneratorViewController.swift +++ b/firefox-ios/Client/Frontend/PasswordGenerator/PasswordGeneratorViewController.swift @@ -221,5 +221,5 @@ class PasswordGeneratorViewController: UIViewController, StoreSubscriber, Themea } extension PasswordGeneratorViewController: BottomSheetChild { - func willDismiss() { } + func willDismiss() { currentTab.webView?.accessoryView.reloadViewFor(.standard)} } diff --git a/firefox-ios/Client/Frontend/TabContentsScripts/LoginsHelper.swift b/firefox-ios/Client/Frontend/TabContentsScripts/LoginsHelper.swift index 78c6f8bfbe4e..a4fbb6fb4c73 100644 --- a/firefox-ios/Client/Frontend/TabContentsScripts/LoginsHelper.swift +++ b/firefox-ios/Client/Frontend/TabContentsScripts/LoginsHelper.swift @@ -42,6 +42,8 @@ class LoginsHelper: TabContentScript, FeatureFlaggable { public var foundFieldValues: ((FocusFieldType, String) -> Void)? + public var passwordFieldInteraction: (() -> Void)? + // Exposed for mocking purposes var logins: RustLogins { return profile.logins @@ -126,10 +128,20 @@ class LoginsHelper: TabContentScript, FeatureFlaggable { if self.featureFlags.isFeatureEnabled(.passwordGenerator, checking: .buildOnly) { if type == "generatePassword", let tab = self.tab, !tab.isPrivate { - let newAction = GeneralBrowserAction( - windowUUID: tab.windowUUID, - actionType: GeneralBrowserActionType.showPasswordGenerator) - store.dispatch(newAction) + let userDefaults = UserDefaults.standard + let showPasswordGeneratorClosure = { + let newAction = GeneralBrowserAction( + windowUUID: tab.windowUUID, + actionType: GeneralBrowserActionType.showPasswordGenerator) + store.dispatch(newAction) + } + if userDefaults.value(forKey: PrefsKeys.PasswordGeneratorShown) == nil { + userDefaults.set(true, forKey: PrefsKeys.PasswordGeneratorShown) + showPasswordGeneratorClosure() + } else { + tab.webView?.accessoryView.useStrongPasswordClosure = showPasswordGeneratorClosure + tab.webView?.accessoryView.reloadViewFor(.passwordGenerator) + } } } diff --git a/firefox-ios/Shared/Prefs.swift b/firefox-ios/Shared/Prefs.swift index ff71f40efb15..400514344323 100644 --- a/firefox-ios/Shared/Prefs.swift +++ b/firefox-ios/Shared/Prefs.swift @@ -189,6 +189,8 @@ public struct PrefsKeys { // Used to show splash screen only during first time on fresh install public static let splashScreenShownKey = "splashScreenShownKey" + + public static let PasswordGeneratorShown = "PasswordGeneratorShown" } public protocol Prefs {