Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add temporary survey to Passwords Settings screen #2753

Merged
merged 6 commits into from
May 9, 2024
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
2 changes: 1 addition & 1 deletion DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -12778,7 +12778,7 @@
repositoryURL = "https://github.com/duckduckgo/BrowserServicesKit";
requirement = {
kind = exactVersion;
version = 144.0.1;
version = "144.0.1-1";
};
};
9FF521422BAA8FF300B9819B /* XCRemoteSwiftPackageReference "lottie-spm" */ = {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/BrowserServicesKit",
"state" : {
"revision" : "f34b0a63938df11ef471aa3301dcc0de09b0d31b",
"version" : "144.0.1"
"revision" : "6ceabf1d257ff1d1164afb5b9139f9f20baf0c6e",
"version" : "144.0.1-1"
}
},
{
Expand All @@ -50,8 +50,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/duckduckgo-autofill.git",
"state" : {
"revision" : "6053999d6af384a716ab0ce7205dbab5d70ed1b3",
"version" : "11.0.1"
"revision" : "10aeff1ec7f533d1705233a9b14f9393a699b1c0",
"version" : "11.0.2"
}
},
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
{
"images" : [
{
"filename" : "Passwords-DDG-128.svg",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
}
}
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
27 changes: 27 additions & 0 deletions DuckDuckGo/Common/Surveys/SurveyURLBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import Foundation
import Common
import BrowserServicesKit

final class SurveyURLBuilder {

Expand Down Expand Up @@ -95,6 +96,23 @@ final class SurveyURLBuilder {
return components.url
}

func buildSurveyURLWithPasswordsCountSurveyParameter(from originalURLString: String) -> URL? {
let surveyURLWithParameters = buildSurveyURL(from: originalURLString)

guard let surveyURLWithParametersString = surveyURLWithParameters?.absoluteString,
var components = URLComponents(string: surveyURLWithParametersString),
let bucket = passwordsCountBucket() else {
return surveyURLWithParameters
}

var queryItems = components.queryItems ?? []
queryItems.append(URLQueryItem(name: "saved_passwords", value: bucket))

components.queryItems = queryItems

return components.url
}

private func queryItem(parameter: SurveyURLParameters, value: String) -> URLQueryItem {
let urlAllowed: CharacterSet = .alphanumerics.union(.init(charactersIn: "-._~"))
let sanitizedValue = value.addingPercentEncoding(withAllowedCharacters: urlAllowed)
Expand All @@ -105,4 +123,13 @@ final class SurveyURLBuilder {
return URLQueryItem(name: parameter.rawValue, value: String(describing: value))
}

private func passwordsCountBucket() -> String? {
guard let secureVault = try? AutofillSecureVaultFactory.makeVault(reporter: SecureVaultReporter.shared),
let bucket = try? secureVault.accountsCountBucket() else {
return nil
}

return bucket
}

}
1 change: 1 addition & 0 deletions DuckDuckGo/Common/Utilities/UserDefaultsWrapper.swift
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,7 @@ public struct UserDefaultsWrapper<T> {
case askToSavePaymentMethods = "preferences.ask-to-save.payment-methods"
case autolockLocksFormFilling = "preferences.lock-autofill-form-fill"
case autofillDebugScriptEnabled = "preferences.enable-autofill-debug-script"
case autofillSurveyEnabled = "preferences.enable-autofill-survey"

case saveAsPreferredFileType = "saveAs.selected.filetype"

Expand Down
5 changes: 5 additions & 0 deletions DuckDuckGo/Menus/MainMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,7 @@ import SubscriptionUI
}
NSMenuItem(title: "Reset Email Protection InContext Signup Prompt", action: #selector(MainViewController.resetEmailProtectionInContextPrompt))
NSMenuItem(title: "Reset Pixels Storage", action: #selector(MainViewController.resetDailyPixels))
NSMenuItem(title: "Reset Passwords Survey", action: #selector(enablePasswordsSurveyAction), target: self)
}.withAccessibilityIdentifier("MainMenu.resetData")
NSMenuItem(title: "UI Triggers") {
NSMenuItem(title: "Show Save Credentials Popover", action: #selector(MainViewController.showSaveCredentialsPopover))
Expand Down Expand Up @@ -729,6 +730,10 @@ import SubscriptionUI
updateAutofillDebugScriptMenuItem()
}

@objc private func enablePasswordsSurveyAction(_ sender: NSMenuItem) {
AutofillPreferences().autofillSurveyEnabled = true
}

@objc private func debugLoggingMenuItemAction(_ sender: NSMenuItem) {
#if APPSTORE
if !OSLog.isRunningInDebugEnvironment {
Expand Down
4 changes: 4 additions & 0 deletions DuckDuckGo/Preferences/Model/AutofillPreferences.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ protocol AutofillPreferencesPersistor {
var autolockLocksFormFilling: Bool { get set }
var passwordManager: PasswordManager { get set }
var debugScriptEnabled: Bool { get set }
var autofillSurveyEnabled: Bool { get set }
}

enum PasswordManager: String, CaseIterable {
Expand Down Expand Up @@ -149,6 +150,9 @@ final class AutofillPreferences: AutofillPreferencesPersistor {
}
}

@UserDefaultsWrapper(key: .autofillSurveyEnabled, defaultValue: true)
var autofillSurveyEnabled: Bool

private var statisticsStore: StatisticsStore {
return injectedDependencyStore ?? defaultDependencyStore
}
Expand Down
38 changes: 38 additions & 0 deletions DuckDuckGo/Preferences/Model/AutofillPreferencesModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
//

import Foundation
import BrowserServicesKit
import Common

final class AutofillPreferencesModel: ObservableObject {

Expand Down Expand Up @@ -59,6 +61,12 @@ final class AutofillPreferencesModel: ObservableObject {
}
}

@Published private(set) var autofillSurveyEnabled: Bool {
didSet {
persistor.autofillSurveyEnabled = autofillSurveyEnabled && Bundle.main.preferredLocalizations.first == "en"
}
}

@MainActor
@Published private(set) var passwordManager: PasswordManager {
didSet {
Expand Down Expand Up @@ -153,6 +161,7 @@ final class AutofillPreferencesModel: ObservableObject {
autolockLocksFormFilling = persistor.autolockLocksFormFilling
passwordManager = persistor.passwordManager
hasNeverPromptWebsites = !neverPromptWebsitesManager.neverPromptWebsites.isEmpty
autofillSurveyEnabled = persistor.autofillSurveyEnabled
}

private var persistor: AutofillPreferencesPersistor
Expand Down Expand Up @@ -192,4 +201,33 @@ final class AutofillPreferencesModel: ObservableObject {
NSWorkspace.shared.open(.fullDiskAccess)
}

func launchSurvey(statisticsStore: StatisticsStore = LocalStatisticsStore(),
activationDateStore: WaitlistActivationDateStore = DefaultWaitlistActivationDateStore(source: .netP),
operatingSystemVersion: String = ProcessInfo.processInfo.operatingSystemVersion.description,
appVersion: String = AppVersion.shared.versionNumber,
hardwareModel: String? = HardwareModel.model) {

let surveyURLBuilder = SurveyURLBuilder(
statisticsStore: statisticsStore,
operatingSystemVersion: operatingSystemVersion,
appVersion: appVersion,
hardwareModel: hardwareModel,
daysSinceActivation: activationDateStore.daysSinceActivation(),
daysSinceLastActive: activationDateStore.daysSinceLastActive()
)

guard let surveyUrl = surveyURLBuilder.buildSurveyURLWithPasswordsCountSurveyParameter(from: "https://selfserve.decipherinc.com/survey/selfserve/32ab/240307") else {
return
}

DispatchQueue.main.async {
WindowControllersManager.shared.showTab(with: .url(surveyUrl, credential: nil, source: .appOpenUrl))
}

disableAutofillSurvey()
}

func disableAutofillSurvey() {
autofillSurveyEnabled = false
}
}
37 changes: 37 additions & 0 deletions DuckDuckGo/Preferences/View/PreferencesAutofillView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,43 @@ extension Preferences {

// Autofill Content Button
PreferencePaneSection {

// New section
if model.autofillSurveyEnabled {
HStack(alignment: .top, spacing: 20) {
Image(.passwordsDDG128)
.frame(width: 64, height: 48)

VStack(alignment: .leading) {
Text(verbatim: "Help us improve!")
.bold()
Text(verbatim: "We want to make using passwords in DuckDuckGo better.")
.foregroundColor(.greyText)
.padding(.top, 1)

HStack {
Button(action: {
model.disableAutofillSurvey()
}, label: {
Text(verbatim: "No Thanks")
})
Button(action: {
model.launchSurvey()
}, label: {
Text(verbatim: "Take Survey")
})
.buttonStyle(DefaultActionButtonStyle(enabled: true))
}
.padding(.top, 12)
}

Spacer()
}
.padding()
.roundedBorder()
.padding(.bottom, 24)
}

Button(UserText.autofillViewContentButton) {
model.showAutofillPopover()
}
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/DataBrokerProtection/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ let package = Package(
targets: ["DataBrokerProtection"])
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "144.0.1"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "144.0.1-1"),
.package(path: "../SwiftUIExtensions"),
.package(path: "../XPCHelper"),
],
Expand Down
2 changes: 1 addition & 1 deletion LocalPackages/NetworkProtectionMac/Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ let package = Package(
.library(name: "NetworkProtectionUI", targets: ["NetworkProtectionUI"]),
],
dependencies: [
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "144.0.1"),
.package(url: "https://github.com/duckduckgo/BrowserServicesKit", exact: "144.0.1-1"),
.package(url: "https://github.com/airbnb/lottie-spm", exact: "4.4.1"),
.package(path: "../XPCHelper"),
.package(path: "../SwiftUIExtensions"),
Expand Down
Loading
Loading