diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index b2c9aedd16..5cf4fc734c 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -275,6 +275,14 @@ 317295D32AF058D3002C3206 /* MockWaitlistTermsAndConditionsActionHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317295D02AF058D3002C3206 /* MockWaitlistTermsAndConditionsActionHandler.swift */; }; 317295D42AF058D3002C3206 /* MockWaitlistFeatureSetupHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317295D12AF058D3002C3206 /* MockWaitlistFeatureSetupHandler.swift */; }; 317295D52AF058D3002C3206 /* MockWaitlistFeatureSetupHandler.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317295D12AF058D3002C3206 /* MockWaitlistFeatureSetupHandler.swift */; }; + 317307262CD248DB00C492AB /* AutofillToolbarOnboardingPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317307252CD248DA00C492AB /* AutofillToolbarOnboardingPopover.swift */; }; + 317307272CD248DB00C492AB /* AutofillToolbarOnboardingPopover.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317307252CD248DA00C492AB /* AutofillToolbarOnboardingPopover.swift */; }; + 317307292CD248EA00C492AB /* AutofillToolbarOnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317307282CD248EA00C492AB /* AutofillToolbarOnboardingViewController.swift */; }; + 3173072A2CD248EA00C492AB /* AutofillToolbarOnboardingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 317307282CD248EA00C492AB /* AutofillToolbarOnboardingViewController.swift */; }; + 3173072C2CD2490700C492AB /* AutofillToolbarOnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3173072B2CD2490300C492AB /* AutofillToolbarOnboardingView.swift */; }; + 3173072D2CD2490700C492AB /* AutofillToolbarOnboardingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3173072B2CD2490300C492AB /* AutofillToolbarOnboardingView.swift */; }; + 3173072F2CD2493900C492AB /* AutofillToolbarOnboardingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3173072E2CD2493700C492AB /* AutofillToolbarOnboardingViewModel.swift */; }; + 317307302CD2493900C492AB /* AutofillToolbarOnboardingViewModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3173072E2CD2493700C492AB /* AutofillToolbarOnboardingViewModel.swift */; }; 3184AC6D288F29D800C35E4B /* BadgeNotificationAnimationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3184AC6C288F29D800C35E4B /* BadgeNotificationAnimationModel.swift */; }; 3184AC6F288F2A1100C35E4B /* CookieNotificationAnimationModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3184AC6E288F2A1100C35E4B /* CookieNotificationAnimationModel.swift */; }; 3199AF6F2C80734A003AEBDC /* DuckPlayerOnboardingDecider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 3199AF632C80734A003AEBDC /* DuckPlayerOnboardingDecider.swift */; }; @@ -3398,6 +3406,10 @@ 3171D6DA2889B64D0068632A /* CookieManagedNotificationContainerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CookieManagedNotificationContainerView.swift; sourceTree = ""; }; 317295D02AF058D3002C3206 /* MockWaitlistTermsAndConditionsActionHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockWaitlistTermsAndConditionsActionHandler.swift; sourceTree = ""; }; 317295D12AF058D3002C3206 /* MockWaitlistFeatureSetupHandler.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockWaitlistFeatureSetupHandler.swift; sourceTree = ""; }; + 317307252CD248DA00C492AB /* AutofillToolbarOnboardingPopover.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillToolbarOnboardingPopover.swift; sourceTree = ""; }; + 317307282CD248EA00C492AB /* AutofillToolbarOnboardingViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillToolbarOnboardingViewController.swift; sourceTree = ""; }; + 3173072B2CD2490300C492AB /* AutofillToolbarOnboardingView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillToolbarOnboardingView.swift; sourceTree = ""; }; + 3173072E2CD2493700C492AB /* AutofillToolbarOnboardingViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AutofillToolbarOnboardingViewModel.swift; sourceTree = ""; }; 3184AC6C288F29D800C35E4B /* BadgeNotificationAnimationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = BadgeNotificationAnimationModel.swift; sourceTree = ""; }; 3184AC6E288F2A1100C35E4B /* CookieNotificationAnimationModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CookieNotificationAnimationModel.swift; sourceTree = ""; }; 3192A2702A4C4E330084EA89 /* DataBrokerProtection */ = {isa = PBXFileReference; lastKnownFileType = wrapper; path = DataBrokerProtection; sourceTree = ""; }; @@ -5327,6 +5339,17 @@ path = CookieManaged; sourceTree = ""; }; + 317307242CD2489900C492AB /* Onboarding */ = { + isa = PBXGroup; + children = ( + 3173072E2CD2493700C492AB /* AutofillToolbarOnboardingViewModel.swift */, + 3173072B2CD2490300C492AB /* AutofillToolbarOnboardingView.swift */, + 317307282CD248EA00C492AB /* AutofillToolbarOnboardingViewController.swift */, + 317307252CD248DA00C492AB /* AutofillToolbarOnboardingPopover.swift */, + ); + path = Onboarding; + sourceTree = ""; + }; 3184AC6B288F29C600C35E4B /* BadgeAnimationContainer */ = { isa = PBXGroup; children = ( @@ -6768,6 +6791,7 @@ 7B1E819A27C8874900FF0E60 /* Autofill */ = { isa = PBXGroup; children = ( + 317307242CD2489900C492AB /* Onboarding */, C10529482C9F45720041E502 /* Debug */, 7B1E819B27C8874900FF0E60 /* ContentOverlayPopover.swift */, 7B1E819C27C8874900FF0E60 /* ContentOverlay.storyboard */, @@ -11303,6 +11327,7 @@ 3706FBE1293F65D500E42796 /* AppStateRestorationManager.swift in Sources */, 9FA173EC2B7B232200EE4E6E /* AddEditBookmarkDialogView.swift in Sources */, 3706FBE2293F65D500E42796 /* ClickToLoadUserScript.swift in Sources */, + 3173072C2CD2490700C492AB /* AutofillToolbarOnboardingView.swift in Sources */, EED4D3E02C8A298D00C79EEA /* AutofillPixelEvent.swift in Sources */, 3706FBE3293F65D500E42796 /* WindowControllersManager.swift in Sources */, 37197EAA2942443D00394917 /* ModalSheetCancellable.swift in Sources */, @@ -11313,6 +11338,7 @@ 3706FBE7293F65D500E42796 /* PasswordManagementItemListModel.swift in Sources */, 3706FBE8293F65D500E42796 /* SuggestionTableCellView.swift in Sources */, 3706FBE9293F65D500E42796 /* FireViewModel.swift in Sources */, + 317307292CD248EA00C492AB /* AutofillToolbarOnboardingViewController.swift in Sources */, B68D21D02ACBC9FD002DA3C2 /* ContentBlockerRulesManagerMock.swift in Sources */, BD7090D02C5182FB009EED82 /* UnifiedFeedbackFormView.swift in Sources */, 3199AF742C80734A003AEBDC /* DuckPlayerOnboardingModalManager.swift in Sources */, @@ -11434,6 +11460,7 @@ B6F1B02F2BCE6B47005E863C /* TunnelControllerProvider.swift in Sources */, 31A83FB62BE28D7D00F74E67 /* UserText+DBP.swift in Sources */, 3706FC31293F65D500E42796 /* PermissionButton.swift in Sources */, + 317307262CD248DB00C492AB /* AutofillToolbarOnboardingPopover.swift in Sources */, 9F6434622BEC82B700D2D8A0 /* AttributionPixelHandler.swift in Sources */, 3706FC32293F65D500E42796 /* MoreOptionsMenu.swift in Sources */, 3706FC34293F65D500E42796 /* PermissionAuthorizationViewController.swift in Sources */, @@ -11547,6 +11574,7 @@ 9FDA6C222B79A59D00E099A9 /* BookmarkFavoriteView.swift in Sources */, C1372EF52BBC5BAD003F8793 /* SecureTextField.swift in Sources */, 316913242BD2B6250051B46D /* DataBrokerProtectionPixelsHandler.swift in Sources */, + 317307302CD2493900C492AB /* AutofillToolbarOnboardingViewModel.swift in Sources */, 843D73BC2C786E5400E4F9DC /* BookmarkListPopover.swift in Sources */, 3706FC77293F65D500E42796 /* PageObserverUserScript.swift in Sources */, 4BF0E5132AD25A2600FFEC9E /* DuckDuckGoUserAgent.swift in Sources */, @@ -12496,6 +12524,7 @@ 9826B0A02747DF3D0092F683 /* ContentBlocking.swift in Sources */, 4B379C2227BDBA29008A968E /* LocalAuthenticationService.swift in Sources */, 37CEFCA92A6737A2001EF741 /* CredentialsCleanupErrorHandling.swift in Sources */, + 317307272CD248DB00C492AB /* AutofillToolbarOnboardingPopover.swift in Sources */, 4BB99D0326FE191E001E4761 /* SafariBookmarksReader.swift in Sources */, 316913292BD2C7570051B46D /* DataBrokerProtectionErrorViewController.swift in Sources */, 1DA6D0FD2A1FF9A100540406 /* HTTPCookie.swift in Sources */, @@ -12572,6 +12601,7 @@ B6F1C80B2761C45400334924 /* LocalUnprotectedDomains.swift in Sources */, 1E25A4FE2CC937120080EFD4 /* SubscriptionCookieManageEventPixelMapping.swift in Sources */, B69A14FA2B4D705D00B9417D /* BookmarkFolderPicker.swift in Sources */, + 3173072F2CD2493900C492AB /* AutofillToolbarOnboardingViewModel.swift in Sources */, 1D36E658298AA3BA00AA485D /* InternalUserDeciderStore.swift in Sources */, B634DBE5293C944700C3C99E /* NewWindowPolicy.swift in Sources */, 31CF3432288B0B1B0087244B /* NavigationBarBadgeAnimator.swift in Sources */, @@ -12690,6 +12720,7 @@ AA5FA69D275F945C00DCE9C9 /* FaviconStore.swift in Sources */, 4B9DB0352A983B24000927DB /* WaitlistTermsAndConditionsView.swift in Sources */, AAB8203C26B2DE0D00788AC3 /* SuggestionListCharacteristics.swift in Sources */, + 3173072A2CD248EA00C492AB /* AutofillToolbarOnboardingViewController.swift in Sources */, 4B6785472AA8DE68008A5004 /* VPNUninstaller.swift in Sources */, 4B9292D42667123700AD2C21 /* BookmarkListViewController.swift in Sources */, BD88A83E2C4F3E4300460A26 /* FeedbackCategoryProviding.swift in Sources */, @@ -13203,6 +13234,7 @@ 4B4D60D32A0C84F700BCD287 /* UserText+NetworkProtection.swift in Sources */, 843D73BB2C786E5400E4F9DC /* BookmarkListPopover.swift in Sources */, B6B2400E28083B49001B8F3A /* WebViewContainerView.swift in Sources */, + 3173072D2CD2490700C492AB /* AutofillToolbarOnboardingView.swift in Sources */, AAC5E4D925D6A711007F5990 /* BookmarkStore.swift in Sources */, B6FA893F269C424500588ECD /* PrivacyDashboardViewController.swift in Sources */, 37D2771527E870D4003365FD /* PreferencesAppearanceView.swift in Sources */, diff --git a/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingPopover.swift b/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingPopover.swift new file mode 100644 index 0000000000..71a63ba148 --- /dev/null +++ b/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingPopover.swift @@ -0,0 +1,44 @@ +// +// AutofillToolbarOnboardingPopover.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +final class AutofillToolbarOnboardingPopover: NSPopover { + let ctaCallback: (Bool) -> Void + + init(ctaCallback: @escaping (Bool) -> Void) { + self.ctaCallback = ctaCallback + + super.init() + + self.animates = false + self.behavior = .semitransient + + setupContentController() + } + + required init?(coder: NSCoder) { + fatalError("\(Self.self): Bad initializer") + } + + private func setupContentController() { + let controller = AutofillToolbarOnboardingViewController() + controller.ctaCallback = self.ctaCallback + contentViewController = controller + } +} diff --git a/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingView.swift b/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingView.swift new file mode 100644 index 0000000000..fcd26d3102 --- /dev/null +++ b/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingView.swift @@ -0,0 +1,68 @@ +// +// AutofillToolbarOnboardingView.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI +import SwiftUIExtensions + +struct AutofillToolbarOnboardingView: View { + @ObservedObject var viewModel: AutofillToolbarOnboardingViewModel + + enum Constants { + static let verticalSpacing: CGFloat = 16 + static let panelWidth: CGFloat = 310 + static let panelHeight: CGFloat = 148 + } + + var body: some View { + VStack(spacing: Constants.verticalSpacing) { + VStack(alignment: .leading, spacing: Constants.verticalSpacing) { + Text(UserText.autofillOnboardingPopoverTitle) + .font(.headline) + Text(UserText.autofillOnboardingPopoverMessage) + } + + HStack { + createButton(title: UserText.autofillOnboardingPopoverCTAReject, + style: StandardButtonStyle(), + action: viewModel.rejectToolbarIcon) + + createButton(title: UserText.autofillOnboardingPopoverCTAAccept, + style: DefaultActionButtonStyle(enabled: true), + action: viewModel.acceptToolbarIcon) + } + } + .padding() + .frame(width: Constants.panelWidth, height: Constants.panelHeight) + } + + private func createButton(title: String, style: some ButtonStyle, action: @escaping () -> Void) -> some View { + Button(action: action) { + Text(title) + .font(.system(size: 13)) + .fontWeight(.light) + .frame(maxWidth: .infinity) + .frame(height: 22) + } + .buttonStyle(style) + .padding(0) + } +} + +#Preview { + AutofillToolbarOnboardingView(viewModel: AutofillToolbarOnboardingViewModel()) +} diff --git a/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingViewController.swift b/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingViewController.swift new file mode 100644 index 0000000000..4e780de28c --- /dev/null +++ b/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingViewController.swift @@ -0,0 +1,38 @@ +// +// AutofillToolbarOnboardingViewController.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +import SwiftUI + +final class AutofillToolbarOnboardingViewController: NSViewController { + var ctaCallback: ((Bool) -> Void)? + + private let viewModel = AutofillToolbarOnboardingViewModel() + private var hostingView: NSHostingView! + + override func loadView() { + let onboardingView = AutofillToolbarOnboardingView(viewModel: viewModel) + hostingView = NSHostingView(rootView: onboardingView) + self.view = hostingView + + self.setupViewModelCallbacks() + } + + private func setupViewModelCallbacks() { + viewModel.ctaCallback = ctaCallback + } +} diff --git a/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingViewModel.swift b/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingViewModel.swift new file mode 100644 index 0000000000..2edf3ed10d --- /dev/null +++ b/DuckDuckGo/Autofill/Onboarding/AutofillToolbarOnboardingViewModel.swift @@ -0,0 +1,33 @@ +// +// AutofillToolbarOnboardingViewModel.swift +// +// Copyright © 2024 DuckDuckGo. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// + +final class AutofillToolbarOnboardingViewModel: ObservableObject { + var ctaCallback: ((Bool) -> Void)? + + internal init(ctaCallback: ((Bool) -> Void)? = nil) { + self.ctaCallback = ctaCallback + } + + func rejectToolbarIcon() { + ctaCallback?(false) + } + + func acceptToolbarIcon() { + ctaCallback?(true) + } +} diff --git a/DuckDuckGo/Common/Localizables/UserText.swift b/DuckDuckGo/Common/Localizables/UserText.swift index b228bdc9f8..388e1386e5 100644 --- a/DuckDuckGo/Common/Localizables/UserText.swift +++ b/DuckDuckGo/Common/Localizables/UserText.swift @@ -405,6 +405,11 @@ struct UserText { static let gpcExplanation = NSLocalizedString("gpc.explanation", value: "Tells participating websites not to sell or share your data.", comment: "GPC explanation in settings") static let learnMore = NSLocalizedString("learnmore.link", value: "Learn More", comment: "Learn More link") + static let autofillOnboardingPopoverCTAReject = NSLocalizedString("autofill.onboarding.popover.reject", value: "No Thanks", comment: "Autofill onboarding CTA for rejection") + static let autofillOnboardingPopoverCTAAccept = NSLocalizedString("autofill.onboarding.popover.accept", value: "Add Shortcut", comment: "Autofill onboarding CTA for approval") + static let autofillOnboardingPopoverTitle = NSLocalizedString("autofill.onboarding.popover.title", value: "Add passwords shortcut?", comment: "Autofill onboarding popover title") + static let autofillOnboardingPopoverMessage = NSLocalizedString("autofill.onboarding.popover.message1", value: "You can manage your toolbar shortcuts at any time by right-clicking on the toolbar.", comment: "Autofill onboarding popover message") + static let autofillPasswordManager = NSLocalizedString("autofill.password-manager", value: "Password Manager", comment: "Autofill settings section title") static let autofillPasswordManagerDuckDuckGo = NSLocalizedString("autofill.password-manager.duckduckgo", value: "DuckDuckGo built-in password manager", comment: "Autofill password manager row title") static let autofillPasswordManagerBitwarden = NSLocalizedString("autofill.password-manager.bitwarden", value: "Bitwarden", comment: "Autofill password manager row title") diff --git a/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift b/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift index c31a28ead3..e3c8d4ea5d 100644 --- a/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift +++ b/DuckDuckGo/NavigationBar/View/NavigationBarPopovers.swift @@ -59,6 +59,7 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { private(set) var autofillPopoverPresenter: AutofillPopoverPresenter private(set) var downloadsPopover: DownloadsPopover? private(set) var aiChatOnboardingPopover: AIChatOnboardingPopover? + private(set) var autofillOnboardingPopover: AutofillToolbarOnboardingPopover? private var privacyDashboardPopover: PrivacyDashboardPopover? private var privacyInfoCancellable: AnyCancellable? @@ -229,6 +230,10 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { aiChatOnboardingPopover?.close() } + if autofillOnboardingPopover?.isShown ?? false { + autofillOnboardingPopover?.close() + } + return true } @@ -245,6 +250,17 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { show(popover, positionedBelow: button) } + func showAutofillOnboardingPopover(from button: MouseOverButton, + withDelegate delegate: NSPopoverDelegate, + ctaCallback: @escaping (Bool) -> Void) { + guard closeTransientPopovers() else { return } + let popover = autofillOnboardingPopover ?? AutofillToolbarOnboardingPopover(ctaCallback: ctaCallback) + + popover.delegate = delegate + autofillOnboardingPopover = popover + show(popover, positionedBelow: button) + } + func showBookmarkListPopover(from button: MouseOverButton, withDelegate delegate: NSPopoverDelegate, forTab tab: Tab?) { guard closeTransientPopovers() else { return } @@ -294,6 +310,10 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { aiChatOnboardingPopover?.close() } + func closeAutofillOnboardingPopover() { + autofillOnboardingPopover?.close() + } + func openPrivacyDashboard(for tabViewModel: TabViewModel, from button: MouseOverButton) { guard closeTransientPopovers() else { return } @@ -403,6 +423,10 @@ final class NavigationBarPopovers: NSObject, PopoverPresenter { aiChatOnboardingPopover = nil } + func autofillOnboardingPopoverClosed() { + autofillOnboardingPopover = nil + } + func saveIdentityPopoverClosed() { saveIdentityPopover = nil } diff --git a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift index b859dec1af..241c0e37d7 100644 --- a/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift +++ b/DuckDuckGo/NavigationBar/View/NavigationBarViewController.swift @@ -507,20 +507,15 @@ final class NavigationBarViewController: NSViewController { guard view.window?.isKeyWindow == true else { return } DispatchQueue.main.async { - let popoverMessage = PopoverMessageViewController(message: UserText.passwordManagerPinnedPromptPopoverText, - buttonText: UserText.passwordManagerPinnedPromptPopoverButtonText, - buttonAction: {}, - onDismiss: { - self.passwordManagementButton.isHidden = !LocalPinningManager.shared.isPinned(.autofill) - }) + self.popovers.showAutofillOnboardingPopover(from: self.passwordManagementButton, + withDelegate: self) { [weak self] didAddShortcut in + guard let self = self else { return } + self.popovers.closeAutofillOnboardingPopover() - popoverMessage.viewModel.buttonAction = { [weak popoverMessage] in - LocalPinningManager.shared.pin(.autofill) - popoverMessage?.dismiss() + if didAddShortcut { + LocalPinningManager.shared.pin(.autofill) + } } - - self.passwordManagementButton.isHidden = false - popoverMessage.show(onParent: self, relativeTo: self.passwordManagementButton) } } @@ -1228,9 +1223,11 @@ extension NavigationBarViewController: NSPopoverDelegate { } else if let popover = popovers.aiChatOnboardingPopover, notification.object as AnyObject? === popover { popovers.aiChatOnboardingPopoverClosed() updateAIChatButton() + } else if let popover = popovers.autofillOnboardingPopover, notification.object as AnyObject? === popover { + popovers.autofillOnboardingPopoverClosed() + updatePasswordManagementButton() } } - } extension NavigationBarViewController: DownloadsViewControllerDelegate {