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

Privacy Dashboard 8.0.0: Improved breakage form #1160

Open
wants to merge 12 commits into
base: main
Choose a base branch
from
Open
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
8 changes: 4 additions & 4 deletions Package.resolved
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/content-scope-scripts",
"state" : {
"revision" : "7958ddab724c26326333cae13fe81478290607fa",
"version" : "7.6.0"
"revision" : "0502ed7de4130bd8705daebaca9aeb20d3e62d15",
"version" : "7.5.0"
}
},
{
Expand Down Expand Up @@ -50,8 +50,8 @@
"kind" : "remoteSourceControl",
"location" : "https://github.com/duckduckgo/privacy-dashboard",
"state" : {
"revision" : "bea4d750913ef82c10cd06e791686501c8e648e4",
"version" : "7.6.0"
"branch" : "pr-releases/pr-302",
"revision" : "05d04de7505117b32949b2007e5a56ba2d39469b"
}
},
{
Expand Down
4 changes: 2 additions & 2 deletions Package.swift
Original file line number Diff line number Diff line change
Expand Up @@ -55,8 +55,8 @@ let package = Package(
.package(url: "https://github.com/duckduckgo/TrackerRadarKit", exact: "3.0.0"),
.package(url: "https://github.com/duckduckgo/sync_crypto", exact: "0.4.0"),
.package(url: "https://github.com/gumob/PunycodeSwift.git", exact: "3.0.0"),
.package(url: "https://github.com/duckduckgo/content-scope-scripts", exact: "7.6.0"),
.package(url: "https://github.com/duckduckgo/privacy-dashboard", exact: "7.6.0"),
.package(url: "https://github.com/duckduckgo/content-scope-scripts", exact: "7.5.0"),
.package(url: "https://github.com/duckduckgo/privacy-dashboard", branch: "pr-releases/pr-302"),
.package(url: "https://github.com/httpswift/swifter.git", exact: "1.5.0"),
.package(url: "https://github.com/duckduckgo/bloom_cpp.git", exact: "3.0.0"),
.package(url: "https://github.com/1024jp/GzipSwift.git", exact: "6.0.1"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ public enum PrivacyFeature: String {
case performanceMetrics
case privacyPro
case sslCertificates
case brokenSiteReportExperiment
case toggleReports
case maliciousSiteProtection
case brokenSitePrompt
Expand Down
56 changes: 15 additions & 41 deletions Sources/PrivacyDashboard/PrivacyDashboardController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,9 @@ public protocol PrivacyDashboardControllerDelegate: AnyObject {
didRequestOpenUrlInNewTab url: URL)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didRequestOpenSettings target: PrivacyDashboardOpenSettingsTarget)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didSelectBreakageCategory category: String)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didRequestSubmitBrokenSiteReportWithCategory category: String,
description: String)
func privacyDashboardControllerDidRequestShowAlertForMissingDescription(_ privacyDashboardController: PrivacyDashboardController)
func privacyDashboardControllerDidRequestShowGeneralFeedback(_ privacyDashboardController: PrivacyDashboardController)
func privacyDashboardController(_ privacyDashboardController: PrivacyDashboardController,
didRequestSubmitToggleReportWithSource source: BrokenSiteReport.Source)
Expand Down Expand Up @@ -89,7 +86,6 @@ public protocol PrivacyDashboardControllerDelegate: AnyObject {

public private(set) weak var privacyInfo: PrivacyInfo?
private let entryPoint: PrivacyDashboardEntryPoint
private let variant: PrivacyDashboardVariant
private let eventMapping: EventMapping<PrivacyDashboardEvents>

weak var webView: WKWebView?
Expand All @@ -103,12 +99,10 @@ public protocol PrivacyDashboardControllerDelegate: AnyObject {

public init(privacyInfo: PrivacyInfo?,
entryPoint: PrivacyDashboardEntryPoint,
variant: PrivacyDashboardVariant,
toggleReportingManager: ToggleReportingManaging,
eventMapping: EventMapping<PrivacyDashboardEvents>) {
self.privacyInfo = privacyInfo
self.entryPoint = entryPoint
self.variant = variant
self.eventMapping = eventMapping
self.toggleReportingManager = toggleReportingManager
script = PrivacyDashboardUserScript()
Expand All @@ -118,6 +112,12 @@ public protocol PrivacyDashboardControllerDelegate: AnyObject {
self.webView = webView
webView.navigationDelegate = self

if #available(iOS 16.4, macOS 13.3, *) {
webView.isInspectable = true
} else {
// Fallback on earlier versions
}

setupPrivacyDashboardUserScript()
loadStartScreen()
startToggleReportingFlowIfNeeded()
Expand All @@ -141,8 +141,8 @@ public protocol PrivacyDashboardControllerDelegate: AnyObject {
}

private func loadStartScreen() {
let url = PrivacyDashboardURLBuilder(configuration: .startScreen(entryPoint: entryPoint, variant: variant)).build()
webView?.loadHTMLString(dashboardHtml, baseURL: url.deletingLastPathComponent())
let url = PrivacyDashboardURLBuilder(configuration: .startScreen(entryPoint: entryPoint)).build()
webView?.loadFileURL(url, allowingReadAccessTo: url.deletingLastPathComponent().deletingLastPathComponent())
}

public func updatePrivacyInfo(_ privacyInfo: PrivacyInfo?) {
Expand Down Expand Up @@ -181,7 +181,6 @@ public protocol PrivacyDashboardControllerDelegate: AnyObject {
case .dashboard: source = .dashboard
case .prompt: source = .prompt
case .toggleReport: source = .onProtectionsOffMenu
case .afterTogglePrompt: source = .afterTogglePrompt
}
if let toggleReportingSource = toggleReportingFlow?.entryPoint.source {
source = toggleReportingSource
Expand Down Expand Up @@ -335,9 +334,6 @@ extension PrivacyDashboardController: PrivacyDashboardUserScriptDelegate {
}

func userScript(_ userScript: PrivacyDashboardUserScript, didChangeProtectionState protectionState: ProtectionState) {
if protectionState.eventOrigin.screen == .choiceToggle {
eventMapping.fire(.toggleProtectionOff)
}
if shouldSegueToToggleReportScreen(with: protectionState) {
segueToToggleReportScreen(with: protectionState)
} else {
Expand Down Expand Up @@ -372,23 +368,23 @@ extension PrivacyDashboardController: PrivacyDashboardUserScriptDelegate {
}

func userScriptDidRequestShowReportBrokenSite(_ userScript: PrivacyDashboardUserScript) {
eventMapping.fire(.showReportBrokenSite)
}

func userScriptDidRequestReportBrokenSiteShown(_ userScript: PrivacyDashboardUserScript) {
eventMapping.fire(.reportBrokenSiteShown, parameters: [
PrivacyDashboardEvents.Parameters.variant: variant.rawValue,
PrivacyDashboardEvents.Parameters.source: source.rawValue
])
eventMapping.fire(.showReportBrokenSite)
}

func userScript(_ userScript: PrivacyDashboardUserScript, setHeight height: Int) {
delegate?.privacyDashboardController(self, didSetHeight: height)
}

func userScript(_ userScript: PrivacyDashboardUserScript, didRequestSubmitBrokenSiteReportWithCategory category: String, description: String) {
var parameters = [PrivacyDashboardEvents.Parameters.variant: variant.rawValue]
if case let .afterTogglePrompt(_, didToggleProtectionsFixIssue) = entryPoint {
parameters[PrivacyDashboardEvents.Parameters.didToggleProtectionsFixIssue] = didToggleProtectionsFixIssue.description
}
eventMapping.fire(.reportBrokenSiteSent, parameters: parameters)
eventMapping.fire(.reportBrokenSiteSent, parameters: [
PrivacyDashboardEvents.Parameters.source: source.rawValue
])
delegate?.privacyDashboardController(self, didRequestSubmitBrokenSiteReportWithCategory: category, description: description)
}

Expand All @@ -410,30 +406,8 @@ extension PrivacyDashboardController: PrivacyDashboardUserScriptDelegate {
toggleReportingFlow?.userScriptDidSelectReportAction(shouldSendReport: shouldSendReport)
}

// MARK: - Experiment flows (soon to be removed)

func userScript(_ userScript: PrivacyDashboardUserScript, didSelectOverallCategory category: String) {
eventMapping.fire(.overallCategorySelected, parameters: [PrivacyDashboardEvents.Parameters.category: category])
}

func userScript(_ userScript: PrivacyDashboardUserScript, didSelectBreakageCategory category: String) {
eventMapping.fire(.breakageCategorySelected, parameters: [
PrivacyDashboardEvents.Parameters.variant: variant.rawValue,
PrivacyDashboardEvents.Parameters.category: category
])
delegate?.privacyDashboardController(self, didSelectBreakageCategory: category)
}

func userScriptDidRequestShowAlertForMissingDescription(_ userScript: PrivacyDashboardUserScript) {
delegate?.privacyDashboardControllerDidRequestShowAlertForMissingDescription(self)
}

func userScriptDidRequestShowNativeFeedback(_ userScript: PrivacyDashboardUserScript) {
delegate?.privacyDashboardControllerDidRequestShowGeneralFeedback(self)
}

func userScriptDidSkipTogglingStep(_ userScript: PrivacyDashboardUserScript) {
eventMapping.fire(.skipToggleStep)
}

}
28 changes: 7 additions & 21 deletions Sources/PrivacyDashboard/PrivacyDashboardEntryPoint.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,25 +33,12 @@ public enum PrivacyDashboardEntryPoint: Equatable {
/// The prompt report screen, which is triggered whenever the user taps report from the toast 'Site not working?"
case prompt

/// The experimental after toggle prompt screen, presented in variant B.
/// After the user toggles off protection, this prompt asks if the action helped and allows the user to report their experience.
/// - Parameters:
/// - category: The category of the issue reported by the user.
/// - didToggleProtectionsFixIssue: A Boolean indicating whether toggling protections resolved the issue.
case afterTogglePrompt(category: String, didToggleProtectionsFixIssue: Bool)

func screen(for variant: PrivacyDashboardVariant) -> Screen {
switch (self, variant) {
case (.dashboard, _): return .primaryScreen

case (.report, .control): return .breakageForm
case (.report, .a): return .categorySelection
case (.report, .b): return .categoryTypeSelection

case (.afterTogglePrompt, _): return .choiceBreakageForm

case (.prompt, _): return .promptBreakageForm
case (.toggleReport, _): return .toggleReport
var screen: Screen {
switch self {
case .dashboard: return .primaryScreen
case .report: return .breakageForm
case .prompt: return .breakageForm
case .toggleReport: return .toggleReport
}
}

Expand All @@ -61,8 +48,7 @@ public enum PrivacyDashboardEntryPoint: Equatable {
(.dashboard, .dashboard),
(.report, .report),
(.toggleReport, .toggleReport),
(.prompt, .prompt),
(.afterTogglePrompt, .afterTogglePrompt):
(.prompt, .prompt):
return true
default:
return false
Expand Down
6 changes: 0 additions & 6 deletions Sources/PrivacyDashboard/PrivacyDashboardEvents.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,20 +22,14 @@ public enum PrivacyDashboardEvents {

public enum Parameters {

public static let variant = "variant"
public static let source = "source"
public static let category = "category"
public static let didToggleProtectionsFixIssue = "didToggleProtectionsFixIssue"

}

case showReportBrokenSite

case reportBrokenSiteShown
case breakageCategorySelected
case reportBrokenSiteSent
case overallCategorySelected
case skipToggleStep
case toggleProtectionOff

}
45 changes: 11 additions & 34 deletions Sources/PrivacyDashboard/PrivacyDashboardURLBuilder.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ final class PrivacyDashboardURLBuilder {

enum Configuration {

case startScreen(entryPoint: PrivacyDashboardEntryPoint, variant: PrivacyDashboardVariant)
case startScreen(entryPoint: PrivacyDashboardEntryPoint)
case segueToScreen(_ screen: Screen, entryPoint: PrivacyDashboardEntryPoint)

}
Expand All @@ -38,31 +38,16 @@ final class PrivacyDashboardURLBuilder {

func build() -> URL {
url.addingScreenParameter(from: configuration)
.addingBreakageScreenParameterIfNeeded(from: configuration)
.addingCategoryParameterIfNeeded(from: configuration)
.addingOpenerParameterIfNeeded(from: configuration)
}

}

private extension PrivacyDashboardVariant {

var breakageScreen: BreakageScreen? {
switch self {
case .control: return nil
case .a: return .categorySelection
case .b: return .categoryTypeSelection
}
}

}

private extension URL {

private enum Constant {

static let screenKey = "screen"
static let breakageScreenKey = "breakageScreen"
static let openerKey = "opener"
static let categoryKey = "category"

Expand All @@ -74,32 +59,24 @@ private extension URL {
func addingScreenParameter(from configuration: PrivacyDashboardURLBuilder.Configuration) -> URL {
var screen: Screen
switch configuration {
case .startScreen(let entryPoint, let variant):
screen = entryPoint.screen(for: variant)
case .startScreen(let entryPoint):
screen = entryPoint.screen
case .segueToScreen(let destinationScreen, _):
screen = destinationScreen
}
return appendingParameter(name: Constant.screenKey, value: screen.rawValue)
}

func addingBreakageScreenParameterIfNeeded(from configuration: PrivacyDashboardURLBuilder.Configuration) -> URL {
if case .startScreen(_, let variant) = configuration, let breakageScreen = variant.breakageScreen?.rawValue {
return appendingParameter(name: Constant.breakageScreenKey, value: breakageScreen)
}
return self
}

func addingCategoryParameterIfNeeded(from configuration: PrivacyDashboardURLBuilder.Configuration) -> URL {
if case .startScreen(let entryPoint, _) = configuration, case .afterTogglePrompt(let category, _) = entryPoint {
return appendingParameter(name: Constant.categoryKey, value: category)
}
return self
}

func addingOpenerParameterIfNeeded(from configuration: PrivacyDashboardURLBuilder.Configuration) -> URL {
if case .startScreen(let entryPoint, _) = configuration, case .toggleReport = entryPoint {
return appendingParameter(name: Constant.openerKey, value: Constant.menuScreenKey)
if case .startScreen(let entryPoint) = configuration {
switch entryPoint {
case .toggleReport, .report:
return appendingParameter(name: Constant.openerKey, value: Constant.menuScreenKey)
default:
break
}
}

if case .segueToScreen(_, let entryPoint) = configuration, entryPoint == .dashboard {
return appendingParameter(name: Constant.openerKey, value: Constant.dashboardScreenKey)
}
Expand Down
Loading
Loading