Skip to content

Commit

Permalink
Subscription UI updates (#2303)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/1200019156869587/1206362116109071/f

**Description**:
Update to MacOS screens following design and copy changes.

**Steps to test this PR**:
Please refer to the linked task for the scope of the changes and Figma
designs attached therein.
Scope of the updates is contained in for both authenticated and
unauthenticated states:
- more menu
- settings
- address bar styling for DBP, ITR and subscription pages

---
###### Internal references:
[Pull Request Review
Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f)
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
[Pull Request
Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f)
  • Loading branch information
miasma13 authored Mar 5, 2024
1 parent 2286885 commit 774adaa
Show file tree
Hide file tree
Showing 45 changed files with 242 additions and 370 deletions.
2 changes: 1 addition & 1 deletion Configuration/App/DuckDuckGoPrivacyPro.xcconfig
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,6 @@

#include "DuckDuckGo.xcconfig"

FEATURE_FLAGS = FEEDBACK NETWORK_PROTECTION SPARKLE SUBSCRIPTION DBP STRIPE SUBSCRIPTION_OVERRIDE_ENABLED
FEATURE_FLAGS = FEEDBACK NETWORK_PROTECTION SPARKLE SUBSCRIPTION DBP NONONOSTRIPE SUBSCRIPTION_OVERRIDE_ENABLED
PRODUCT_NAME = $(PRODUCT_NAME_PREFIX) Privacy Pro
PRODUCT_MODULE_NAME = $(PRIVACY_PRO_PRODUCT_MODULE_NAME_OVERRIDE:default=$(DEFAULT_PRODUCT_MODULE_NAME))
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
{
"images" : [
{
"filename" : "CreditCard-16.pdf",
"filename" : "ITR-Icon.pdf",
"idiom" : "universal"
}
],
Expand All @@ -10,7 +10,6 @@
"version" : 1
},
"properties" : {
"preserves-vector-representation" : true,
"template-rendering-intent" : "template"
}
}
Binary file not shown.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -1,15 +1,12 @@
{
"images" : [
{
"filename" : "pir-service-icon.pdf",
"filename" : "PrivacyPro.pdf",
"idiom" : "universal"
}
],
"info" : {
"author" : "xcode",
"version" : 1
},
"properties" : {
"template-rendering-intent" : "template"
}
}
Binary file not shown.
5 changes: 4 additions & 1 deletion DuckDuckGo/Common/Extensions/URLExtension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -477,6 +477,9 @@ extension URL {
}

public func isChild(of url: URL) -> Bool {
self.absoluteString.hasPrefix(url.absoluteString)
var components = URLComponents(string: url.absoluteString)
components?.query = nil

return self.absoluteString.hasPrefix(components?.url?.absoluteString ?? url.absoluteString)
}
}
1 change: 1 addition & 0 deletions DuckDuckGo/Common/Localizables/UserText.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,7 @@ struct UserText {

// "data-broker-protection.optionsMenu" - Menu item data broker protection feature
static let dataBrokerProtectionOptionsMenuItem = "Personal Information Removal"
static let dataBrokerProtectionScanOptionsMenuItem = "Personal Information Removal Scan"
// "tab.dbp.title" - Tab data broker protection title
static let tabDataBrokerProtectionTitle = "Personal Information Removal"

Expand Down
21 changes: 8 additions & 13 deletions DuckDuckGo/NavigationBar/View/MoreOptionsMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -390,24 +390,19 @@ final class MoreOptionsMenu: NSMenu {

#if SUBSCRIPTION
private func makeInactiveSubscriptionItems() -> [NSMenuItem] {
let privacyProItem = NSMenuItem(title: "",
let dataBrokerProtectionItem = NSMenuItem(title: UserText.dataBrokerProtectionScanOptionsMenuItem,
action: #selector(openSubscriptionPurchasePage(_:)),
keyEquivalent: "")
.targetting(self)
.withImage(.dbpIcon)

let privacyProItem = NSMenuItem(title: UserText.subscriptionOptionsMenuItem,
action: #selector(openSubscriptionPurchasePage(_:)),
keyEquivalent: "")
.targetting(self)
.withImage(.subscriptionIcon)

let attributedText = NSMutableAttributedString(string: UserText.subscriptionOptionsMenuItem)
attributedText.append(NSAttributedString(string: " "))

let imageAttachment = NSTextAttachment()
imageAttachment.image = .newLabel
imageAttachment.setImageHeight(height: 16, offset: .init(x: 0, y: -4))

attributedText.append(NSAttributedString(attachment: imageAttachment))

privacyProItem.attributedTitle = attributedText

return [privacyProItem]
return [dataBrokerProtectionItem, privacyProItem]
}
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1099,7 +1099,7 @@ extension NavigationBarViewController: OptionsButtonMenuDelegate {
}

func optionsButtonMenuRequestedIdentityTheftRestoration(_ menu: NSMenu) {
WindowControllersManager.shared.showTab(with: .subscription(.identityTheftRestoration))
WindowControllersManager.shared.showTab(with: .identityTheftRestoration(.identityTheftRestoration))
}
#endif

Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/Preferences/Model/PreferencesSection.swift
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ enum PreferencePaneIdentifier: String, Equatable, Hashable, Identifiable {
#endif
#if SUBSCRIPTION
case .subscription:
return "Privacy"
return "PrivacyPro"
#endif
case .autofill:
return "Autofill"
Expand Down
10 changes: 8 additions & 2 deletions DuckDuckGo/Preferences/View/PreferencesRootView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,19 @@ enum Preferences {
}
}

let openITR: () -> Void = {
DispatchQueue.main.async {
WindowControllersManager.shared.showTab(with: .identityTheftRestoration(.identityTheftRestoration))
}
}

let sheetActionHandler = SubscriptionAccessActionHandlers(restorePurchases: { SubscriptionPagesUseSubscriptionFeature.startAppStoreRestoreFlow() },
openURLHandler: openURL,
goToSyncPreferences: { self.model.selectPane(.sync) })
openURLHandler: openURL)

return PreferencesSubscriptionModel(openURLHandler: openURL,
openVPNHandler: openVPN,
openDBPHandler: openDBP,
openITRHandler: openITR,
sheetActionHandler: sheetActionHandler)
}
#endif
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -242,7 +242,7 @@ extension Tab.TabContent {
switch self {
case .url(let url, credential: let credential, source: _):
.url(url, credential: credential, source: .pendingStateRestoration)
case .newtab, .settings, .bookmarks, .onboarding, .none, .dataBrokerProtection, .subscription:
case .newtab, .settings, .bookmarks, .onboarding, .none, .dataBrokerProtection, .subscription, .identityTheftRestoration:
self
}
}
Expand All @@ -252,7 +252,7 @@ extension Tab.TabContent {
case .url(let url, credential: let credential, source: let source):
let newSource: URLSource = source == .pendingStateRestoration ? .loadedByStateRestoration : .reload
return .url(url, credential: credential, source: newSource)
case .newtab, .settings, .bookmarks, .onboarding, .none, .dataBrokerProtection, .subscription:
case .newtab, .settings, .bookmarks, .onboarding, .none, .dataBrokerProtection, .subscription, .identityTheftRestoration:
return self
}
}
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/RecentlyClosed/View/RecentlyClosedMenu.swift
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ private extension NSMenuItem {
case .bookmarks:
image = TabViewModel.Favicon.preferences
title = UserText.tabPreferencesTitle
case .url, .subscription:
case .url, .subscription, .identityTheftRestoration:
image = recentlyClosedTab.favicon
image?.size = NSSize.faviconSize
title = recentlyClosedTab.title ?? recentlyClosedTab.tabContent.url?.absoluteString ?? ""
Expand Down
5 changes: 5 additions & 0 deletions DuckDuckGo/StateRestoration/Tab+NSSecureCoding.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,7 @@ private extension Tab.TabContent {
case duckPlayer = 5
case dataBrokerProtection = 6
case subscription = 7
case identityTheftRestoration = 8
}

// swiftlint:disable:next cyclomatic_complexity
Expand All @@ -117,6 +118,9 @@ private extension Tab.TabContent {
case .subscription:
guard let url = url else { return nil }
self = .subscription(url)
case .identityTheftRestoration:
guard let url = url else { return nil }
self = .identityTheftRestoration(url)
}
}

Expand All @@ -130,6 +134,7 @@ private extension Tab.TabContent {
case .none: return .newtab
case .dataBrokerProtection: return .dataBrokerProtection
case .subscription: return .subscription
case .identityTheftRestoration: return .identityTheftRestoration
}
}

Expand Down
19 changes: 13 additions & 6 deletions DuckDuckGo/Tab/Model/Tab.swift
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ protocol NewWindowPolicyDecisionMaker {
case none
case dataBrokerProtection
case subscription(URL)
case identityTheftRestoration(URL)

enum URLSource: Equatable {
case pendingStateRestoration
Expand Down Expand Up @@ -140,8 +141,10 @@ protocol NewWindowPolicyDecisionMaker {

#if SUBSCRIPTION
if let url {
if url.isChild(of: URL.subscriptionBaseURL) || url.isChild(of: URL.identityTheftRestoration) {
if url.isChild(of: URL.subscriptionBaseURL) {
return .subscription(url)
} else if url.isChild(of: URL.identityTheftRestoration) {
return .identityTheftRestoration(url)
}
}
#endif
Expand Down Expand Up @@ -174,7 +177,7 @@ protocol NewWindowPolicyDecisionMaker {

var isDisplayable: Bool {
switch self {
case .settings, .bookmarks, .dataBrokerProtection:
case .settings, .bookmarks, .dataBrokerProtection, .subscription, .identityTheftRestoration:
return true
default:
return false
Expand All @@ -189,6 +192,10 @@ protocol NewWindowPolicyDecisionMaker {
return true
case (.dataBrokerProtection, .dataBrokerProtection):
return true
case (.subscription, .subscription):
return true
case (.identityTheftRestoration, .identityTheftRestoration):
return true
default:
return false
}
Expand All @@ -201,7 +208,7 @@ protocol NewWindowPolicyDecisionMaker {
case .bookmarks: return UserText.tabBookmarksTitle
case .onboarding: return UserText.tabOnboardingTitle
case .dataBrokerProtection: return UserText.tabDataBrokerProtectionTitle
case .subscription: return nil
case .subscription, .identityTheftRestoration: return nil
}
}

Expand Down Expand Up @@ -233,7 +240,7 @@ protocol NewWindowPolicyDecisionMaker {
return .welcome
case .dataBrokerProtection:
return .dataBrokerProtection
case .subscription(let url):
case .subscription(let url), .identityTheftRestoration(let url):
return url
case .none:
return nil
Expand All @@ -242,7 +249,7 @@ protocol NewWindowPolicyDecisionMaker {

var isUrl: Bool {
switch self {
case .url, .subscription:
case .url, .subscription, .identityTheftRestoration:
return true
default:
return false
Expand Down Expand Up @@ -992,7 +999,7 @@ protocol NewWindowPolicyDecisionMaker {
let forceReload = url.absoluteString == source.userEnteredValue ? shouldLoadInBackground : (source == .reload)
return (url, source, forceReload: forceReload)

case .subscription(let url):
case .subscription(let url), .identityTheftRestoration(let url):
return (url, .ui, forceReload: false)

case .newtab, .bookmarks, .onboarding, .dataBrokerProtection, .settings:
Expand Down
17 changes: 10 additions & 7 deletions DuckDuckGo/Tab/UserScripts/SubscriptionPagesUserScript.swift
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,7 @@ final class SubscriptionPagesUseSubscriptionFeature: Subfeature {
#endif
}

// swiftlint:disable:next function_body_length
// swiftlint:disable:next function_body_length cyclomatic_complexity
func subscriptionSelected(params: Any, original: WKScriptMessage) async throws -> Encodable? {
struct SubscriptionSelection: Decodable {
let id: String
Expand Down Expand Up @@ -230,8 +230,13 @@ final class SubscriptionPagesUseSubscriptionFeature: Subfeature {
case .success:
break
case .failure(let error):
os_log(.error, log: .subscription, "[Purchase] Error: %{public}s", String(reflecting: error))
await WindowControllersManager.shared.lastKeyMainWindowController?.showSomethingWentWrongAlert()
switch error {
case .cancelledByUser:
os_log(.error, log: .subscription, "[Purchase] Cancelled by user")
default:
os_log(.error, log: .subscription, "[Purchase] Error: %{public}s", String(reflecting: error))
await WindowControllersManager.shared.lastKeyMainWindowController?.showSomethingWentWrongAlert()
}
return nil
}

Expand Down Expand Up @@ -265,9 +270,7 @@ final class SubscriptionPagesUseSubscriptionFeature: Subfeature {
}
},
openURLHandler: { url in
WindowControllersManager.shared.show(url: url, source: .ui, newTab: true)
}, goToSyncPreferences: {
WindowControllersManager.shared.show(url: .settingsPane(.sync), source: .ui, newTab: true)
WindowControllersManager.shared.showTab(with: .subscription(url))
})

let vc = SubscriptionAccessViewController(actionHandlers: actionHandlers)
Expand Down Expand Up @@ -307,7 +310,7 @@ final class SubscriptionPagesUseSubscriptionFeature: Subfeature {
NotificationCenter.default.post(name: .openPersonalInformationRemoval, object: self, userInfo: nil)
await WindowControllersManager.shared.showTab(with: .dataBrokerProtection)
case .identityTheftRestoration:
await WindowControllersManager.shared.showTab(with: .subscription(.identityTheftRestoration))
await WindowControllersManager.shared.showTab(with: .identityTheftRestoration(.identityTheftRestoration))
}

return nil
Expand Down
6 changes: 3 additions & 3 deletions DuckDuckGo/Tab/View/BrowserTabViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ final class BrowserTabViewController: NSViewController {
.url(_, _, source: .reload):
return true

case .settings, .bookmarks, .dataBrokerProtection, .subscription, .onboarding:
case .settings, .bookmarks, .dataBrokerProtection, .subscription, .onboarding, .identityTheftRestoration:
return true

case .none:
Expand All @@ -463,7 +463,7 @@ final class BrowserTabViewController: NSViewController {
return
case .onboarding:
getView = { [weak self] in self?.transientTabContentViewController?.view }
case .url, .subscription:
case .url, .subscription, .identityTheftRestoration:
getView = { [weak self] in self?.webView }
case .settings:
getView = { [weak self] in self?.preferencesViewController?.view }
Expand Down Expand Up @@ -585,7 +585,7 @@ final class BrowserTabViewController: NSViewController {
}
showTransientTabContentController(OnboardingViewController.create(withDelegate: self))

case .url, .subscription:
case .url, .subscription, .identityTheftRestoration:
if shouldReplaceWebView(for: tabViewModel) {
removeAllTabContent(includingWebView: true)
changeWebView(tabViewModel: tabViewModel)
Expand Down
17 changes: 13 additions & 4 deletions DuckDuckGo/Tab/ViewModel/TabViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,9 @@ final class TabViewModel {
static let burnerHome = NSImage.burnerTabFavicon
static let preferences = NSImage.preferences
static let bookmarks = NSImage.bookmarks
static let dataBrokerProtection = NSImage.burnerWindowIcon2 // PLACEHOLDER: Change it once we have the final icon
static let dataBrokerProtection = NSImage.dbpIcon
static let subscription = NSImage.subscriptionIcon
static let identityTheftRestoration = NSImage.itrIcon
}

private(set) var tab: Tab
Expand Down Expand Up @@ -130,7 +132,8 @@ final class TabViewModel {
.onboarding,
.none,
.dataBrokerProtection,
.subscription:
.subscription,
.identityTheftRestoration:
// Update the address bar instantly for built-in content types or user-initiated navigations
return Just( .instant ).eraseToAnyPublisher()
}
Expand Down Expand Up @@ -296,7 +299,7 @@ final class TabViewModel {
}
case .onboarding:
title = UserText.tabOnboardingTitle
case .url, .none, .subscription:
case .url, .none, .subscription, .identityTheftRestoration:
if let tabTitle = tab.title?.trimmingWhitespace(), !tabTitle.isEmpty {
title = tabTitle
} else if let host = tab.url?.host?.droppingWwwPrefix() {
Expand Down Expand Up @@ -335,7 +338,13 @@ final class TabViewModel {
case .bookmarks:
favicon = Favicon.bookmarks
return
case .url, .onboarding, .none, .subscription: break
case .subscription:
favicon = Favicon.subscription
return
case .identityTheftRestoration:
favicon = Favicon.identityTheftRestoration
return
case .url, .onboarding, .none: break
}

if let favicon: NSImage? = tabFavicon {
Expand Down
Loading

0 comments on commit 774adaa

Please sign in to comment.