Skip to content
This repository has been archived by the owner on May 10, 2024. It is now read-only.

Commit

Permalink
Fix #2832: Update onboarding flow. (#2837)
Browse files Browse the repository at this point in the history
  • Loading branch information
iccub authored Aug 31, 2020
1 parent 29300dd commit 6aedffb
Show file tree
Hide file tree
Showing 7 changed files with 217 additions and 38 deletions.
5 changes: 5 additions & 0 deletions BraveShared/BraveStrings.swift
Original file line number Diff line number Diff line change
Expand Up @@ -629,6 +629,11 @@ extension Strings {
public static let OBErrorTitle = NSLocalizedString("OBErrorTitle", bundle: Bundle.braveShared, value: "Sorry", comment: "A generic error title for onboarding")
public static let OBErrorDetails = NSLocalizedString("OBErrorDetails", bundle: Bundle.braveShared, value: "Something went wrong while creating your wallet. Please try again", comment: "A generic error body for onboarding")
public static let OBErrorOkay = NSLocalizedString("OBErrorOkay", bundle: Bundle.braveShared, value: "Okay", comment: "")
public static let OBPrivacyConsentTitle = NSLocalizedString("OBPrivacyConsentTitle", bundle: .braveShared, value: "Anonymous referral code check", comment: "")
public static let OBPrivacyConsentDetail = NSLocalizedString("OBPrivacyConsentDetail", bundle: .braveShared, value: "You may have downloaded Brave in support of your referrer. To detect your referrer, Brave performs a one-time check of your clipboard for the matching referral code. This check is limited to the code only and no other personal data will be transmitted. If you opt out, your referrer won’t receive rewards from Brave.", comment: "")
public static let OBPrivacyConsentClipboardPermission = NSLocalizedString("OBPrivacyConsentClipboardPermission", bundle: .braveShared, value: "Allow Brave to check my clipboard for a matching referral code", comment: "")
public static let OBPrivacyConsentYesButton = NSLocalizedString("OBPrivacyConsentYesButton", bundle: .braveShared, value: "Allow one-time clipboard check", comment: "")
public static let OBPrivacyConsentNoButton = NSLocalizedString("OBPrivacyConsentNoButton", bundle: .braveShared, value: "Do not allow this check", comment: "")
}

// MARK: - Ads Notifications
Expand Down
8 changes: 8 additions & 0 deletions Client.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,8 @@
0ADCD45B231973650078CC67 /* UserAgentBuilderTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0ADCD45A231973650078CC67 /* UserAgentBuilderTests.swift */; };
0ADCD45F2319799F0078CC67 /* RollingFileLoggerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E61453BD1B750A1700C3F9D7 /* RollingFileLoggerTests.swift */; };
0AE5C09922CAA01E00DFF3EE /* RewardsButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE5C09822CAA01E00DFF3EE /* RewardsButton.swift */; };
0AE5C69124F0059D004CBC9B /* OnboardingPrivacyConsentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE5C69024F0059D004CBC9B /* OnboardingPrivacyConsentViewController.swift */; };
0AE5C69424F005F9004CBC9B /* OnboardingPrivacyConsentView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AE5C69324F005F9004CBC9B /* OnboardingPrivacyConsentView.swift */; };
0AEF16C723CDE4B800158AD9 /* BottomSheetViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AEF16C523CDE4B800158AD9 /* BottomSheetViewController.swift */; };
0AEF99A922E22C5E00294C76 /* DownloadsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AEF99A822E22C5E00294C76 /* DownloadsViewController.swift */; };
0AEF99B222E22D2200294C76 /* DateGroupedTableData.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0AEF99B122E22D2200294C76 /* DateGroupedTableData.swift */; };
Expand Down Expand Up @@ -1515,6 +1517,8 @@
0ADCD4512319640F0078CC67 /* UserAgentBuilder.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilder.swift; sourceTree = "<group>"; };
0ADCD45A231973650078CC67 /* UserAgentBuilderTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = UserAgentBuilderTests.swift; sourceTree = "<group>"; };
0AE5C09822CAA01E00DFF3EE /* RewardsButton.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RewardsButton.swift; sourceTree = "<group>"; };
0AE5C69024F0059D004CBC9B /* OnboardingPrivacyConsentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingPrivacyConsentViewController.swift; sourceTree = "<group>"; };
0AE5C69324F005F9004CBC9B /* OnboardingPrivacyConsentView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = OnboardingPrivacyConsentView.swift; sourceTree = "<group>"; };
0AE885BC23571EE1006951A8 /* fr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = fr; path = fr.lproj/Storage.strings; sourceTree = "<group>"; };
0AEF16C523CDE4B800158AD9 /* BottomSheetViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = BottomSheetViewController.swift; sourceTree = "<group>"; };
0AEF99A822E22C5E00294C76 /* DownloadsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DownloadsViewController.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -2933,6 +2937,8 @@
children = (
0A6112BC230B4306001BBC45 /* OnboardingViewController.swift */,
0A6112AB230B00E7001BBC45 /* OnboardingNavigationController.swift */,
0AE5C69024F0059D004CBC9B /* OnboardingPrivacyConsentViewController.swift */,
0AE5C69324F005F9004CBC9B /* OnboardingPrivacyConsentView.swift */,
0A3C789C23055C4A0022F6D8 /* OnboardingSearchEnginesViewController.swift */,
0A3C789E23056C910022F6D8 /* OnboardingSearchEnginesView.swift */,
0A3C78A0230597DA0022F6D8 /* OnboardingShieldsViewController.swift */,
Expand Down Expand Up @@ -6719,6 +6725,7 @@
27FD2CAD2146C31C00A5A779 /* AddToFavoritesActivity.swift in Sources */,
4422D4E121BFFB7600BF1855 /* filter_block.cc in Sources */,
0A8C69BE225E350300988715 /* IndentedImageTableViewCell.swift in Sources */,
0AE5C69124F0059D004CBC9B /* OnboardingPrivacyConsentViewController.swift in Sources */,
0A1E843D2190A57F0042F782 /* SyncSettingsTableViewController.swift in Sources */,
4422D56C21BFFB7F00BF1855 /* bitstate.cc in Sources */,
E68E7ADE1CAC208A00FDCA76 /* RemovePasscodeViewController.swift in Sources */,
Expand Down Expand Up @@ -6772,6 +6779,7 @@
C4EFEECF1CEBB6F2009762A4 /* BackForwardTableViewCell.swift in Sources */,
2C49854E206173C800893DAE /* photon-colors.swift in Sources */,
E689C7301E0C7617008BAADB /* NSAttributedStringExtensions.swift in Sources */,
0AE5C69424F005F9004CBC9B /* OnboardingPrivacyConsentView.swift in Sources */,
0A16E2D723D4E1FB00B0BF94 /* ClaimRewardsNTPNotificationViewController.swift in Sources */,
D0C95E0E200FD3B200E4E51C /* PrintHelper.swift in Sources */,
4422D55821BFFB7F00BF1855 /* unicode_casefold.cc in Sources */,
Expand Down
85 changes: 48 additions & 37 deletions Client/Application/Delegates/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -295,54 +295,65 @@ class AppDelegate: UIResponder, UIApplicationDelegate, UIViewControllerRestorati
Preferences.URP.referralLookupOutstanding.value = isFirstLaunch
}

if Preferences.URP.referralLookupOutstanding.value == true {
var refCode: String?

let savedRefCode: String? = ProcessInfo().operatingSystemVersion.majorVersion > 13
? nil : UIPasteboard.general.string

if Preferences.URP.referralCode.value == nil {
UrpLog.log("No ref code exists on launch, attempting clipboard retrieval")
refCode = UserReferralProgram.sanitize(input: savedRefCode)
}
handleReferralLookup(urp, checkClipboard: false)
} else {
log.error("Failed to initialize user referral program")
UrpLog.log("Failed to initialize user referral program")
}

AdblockResourceDownloader.shared.startLoading()

return shouldPerformAdditionalDelegateHandling
}

func handleReferralLookup(_ urp: UserReferralProgram, checkClipboard: Bool) {
let initialOnboarding =
Preferences.General.basicOnboardingProgress.value == OnboardingProgress.none.rawValue

// FIXME: Update to iOS14 clipboard api once ready (#2838)
if initialOnboarding && UIPasteboard.general.hasStrings {
log.debug("Skipping URP call at app launch, this is handled in privacy consent onboarding screen")
return
}

if Preferences.URP.referralLookupOutstanding.value == true {
var refCode: String?

if Preferences.URP.referralCode.value == nil {
UrpLog.log("No ref code exists on launch, attempting clipboard retrieval")
let savedRefCode = checkClipboard ? UIPasteboard.general.string : nil
refCode = UserReferralProgram.sanitize(input: savedRefCode)

if refCode != nil {
UrpLog.log("Clipboard ref code found: " + (savedRefCode ?? "!Clipboard Empty!"))
UrpLog.log("Clearing clipboard.")
UIPasteboard.general.clearPasteboard()
}

urp.referralLookup(refCode: refCode) { referralCode, offerUrl in
// Attempting to send ping after first urp lookup.
// This way we can grab the referral code if it exists, see issue #2586.
self.dau.sendPingToServer()
if let code = referralCode {
let retryTime = AppConstants.buildChannel.isPublic ? 1.days : 10.minutes
let retryDeadline = Date() + retryTime

Preferences.NewTabPage.superReferrerThemeRetryDeadline.value = retryDeadline

self.browserViewController.backgroundDataSource
.fetchSpecificResource(.superReferral(code: code))
} else {
self.browserViewController.backgroundDataSource.startFetching()
}
}

urp.referralLookup(refCode: refCode) { referralCode, offerUrl in
// Attempting to send ping after first urp lookup.
// This way we can grab the referral code if it exists, see issue #2586.
self.dau.sendPingToServer()
if let code = referralCode {
let retryTime = AppConstants.buildChannel.isPublic ? 1.days : 10.minutes
let retryDeadline = Date() + retryTime

guard let url = offerUrl?.asURL else { return }
self.browserViewController.openReferralLink(url: url)
Preferences.NewTabPage.superReferrerThemeRetryDeadline.value = retryDeadline

self.browserViewController.backgroundDataSource
.fetchSpecificResource(.superReferral(code: code))
} else {
self.browserViewController.backgroundDataSource.startFetching()
}
} else {
urp.pingIfEnoughTimePassed()
browserViewController.backgroundDataSource.startFetching()
guard let url = offerUrl?.asURL else { return }
self.browserViewController.openReferralLink(url: url)
}
} else {
log.error("Failed to initialize user referral program")
UrpLog.log("Failed to initialize user referral program")
urp.pingIfEnoughTimePassed()
browserViewController.backgroundDataSource.startFetching()
}

AdblockResourceDownloader.shared.startLoading()

return shouldPerformAdditionalDelegateHandling
}

func application(_ application: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey: Any] = [:]) -> Bool {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import UIKit
import Shared
import BraveShared
import pop
import Lottie
import BraveRewards
Expand Down Expand Up @@ -55,7 +56,19 @@ class OnboardingNavigationController: UINavigationController {
if progress == .rewards || progress == .ads {
return BraveAds.isCurrentLocaleSupported() ? [.adsCountdown] : [.rewardsAgreement]
}
return BraveAds.isCurrentLocaleSupported() ? [.searchEnginePicker, .shieldsInfo, .rewardsAgreement, .adsCountdown] : [.searchEnginePicker, .shieldsInfo, .rewardsAgreement]

var newUserScreens: [Screens] = [.searchEnginePicker, .shieldsInfo, .rewardsAgreement]

if BraveAds.isCurrentLocaleSupported() {
newUserScreens.append(.adsCountdown)
}

// FIXME: Update to iOS14 clipboard api once ready (#2838)
if Preferences.URP.referralCode.value == nil && UIPasteboard.general.hasStrings {
newUserScreens.insert(.privacyConsent, at: 0)
}

return newUserScreens
case .existingUserRewardsOff(let progress):
//The user already made it to rewards and agreed so they should only see ads countdown
if progress == .rewards || progress == .ads {
Expand All @@ -79,6 +92,7 @@ class OnboardingNavigationController: UINavigationController {
}

fileprivate enum Screens {
case privacyConsent
case searchEnginePicker
case shieldsInfo
case existingRewardsTurnOnAds
Expand All @@ -88,6 +102,7 @@ class OnboardingNavigationController: UINavigationController {
/// Returns new ViewController associated with the screen type
func viewController(with profile: Profile, rewards: BraveRewards?, theme: Theme) -> OnboardingViewController {
switch self {
case .privacyConsent: return OnboardingPrivacyConsentViewController(profile: profile, rewards: rewards, theme: theme)
case .searchEnginePicker:
return OnboardingSearchEnginesViewController(profile: profile, rewards: rewards, theme: theme)
case .shieldsInfo:
Expand All @@ -103,6 +118,7 @@ class OnboardingNavigationController: UINavigationController {

var type: OnboardingViewController.Type {
switch self {
case .privacyConsent: return OnboardingPrivacyConsentViewController.self
case .searchEnginePicker: return OnboardingSearchEnginesViewController.self
case .shieldsInfo: return OnboardingShieldsViewController.self
case .existingRewardsTurnOnAds: return OnboardingAdsAvailableController.self
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import Foundation
import Shared
import BraveShared
import pop
import SnapKit

extension OnboardingPrivacyConsentViewController {

class View: UIView {

let yesConsentButton = CommonViews.primaryButton(text: Strings.OBPrivacyConsentYesButton).then {
$0.accessibilityIdentifier = "OnboardingPrivacyConsentViewController.YesButton"
$0.titleLabel?.adjustsFontSizeToFitWidth = true
}

let noConsentButton = CommonViews.secondaryButton(text: Strings.OBPrivacyConsentNoButton).then {
$0.accessibilityIdentifier = "OnboardingPrivacyConsentViewController.NoButton"
$0.titleLabel?.adjustsFontSizeToFitWidth = true
}

private let mainStackView = UIStackView().then {
$0.axis = .vertical
$0.distribution = .equalSpacing
}

private let braveLogo = UIImageView(image: #imageLiteral(resourceName: "browser_lock_popup")).then {
$0.contentMode = .scaleAspectFit
}

private let titleLabel = CommonViews.primaryText(Strings.OBPrivacyConsentTitle).then {
$0.font = .systemFont(ofSize: 20, weight: .semibold)
$0.numberOfLines = 0
}

private let refProgramLabel = UILabel().then {
$0.text = Strings.OBPrivacyConsentDetail
$0.font = .systemFont(ofSize: 16, weight: .regular)
$0.numberOfLines = 0
$0.textAlignment = .left
$0.minimumScaleFactor = 0.7
}

init(theme: Theme) {
super.init(frame: .zero)

mainStackView.tag = OnboardingViewAnimationID.detailsContent.rawValue
braveLogo.tag = OnboardingViewAnimationID.background.rawValue

applyTheme(theme)

mainStackView.addStackViewItems(
.view(.spacer(.vertical, amount: 1)),
.view(braveLogo),
.view(
UIStackView(arrangedSubviews: [titleLabel, refProgramLabel]).then {
$0.axis = .vertical
$0.spacing = 24
}),
.view(UIStackView(arrangedSubviews: [yesConsentButton, noConsentButton]).then {
$0.axis = .vertical
$0.spacing = 8
})
)

addSubview(mainStackView)

mainStackView.snp.makeConstraints {
$0.top.equalTo(safeArea.top).inset(24)
$0.bottom.equalTo(safeArea.bottom).inset(16)
$0.leading.trailing.equalToSuperview().inset(25)
}
}

@available(*, unavailable)
required init(coder: NSCoder) { fatalError() }

func applyTheme(_ theme: Theme) {
backgroundColor = OnboardingViewController.colorForTheme(theme)
titleLabel.appearanceTextColor = theme.colors.tints.home
refProgramLabel.appearanceTextColor = theme.colors.tints.home
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at http://mozilla.org/MPL/2.0/.

import UIKit
import BraveShared
import Shared

private let log = Logger.browserLogger

class OnboardingPrivacyConsentViewController: OnboardingViewController {

private var contentView: View {
return view as! View // swiftlint:disable:this force_cast
}

override func loadView() {
view = View(theme: theme)
}

override func viewDidLoad() {
super.viewDidLoad()

contentView.yesConsentButton.addTarget(self, action: #selector(yesConsentTapped), for: .touchUpInside)
contentView.noConsentButton.addTarget(self, action: #selector(noConsentTaapped), for: .touchUpInside)
}

@objc func yesConsentTapped() {
presentNextScreen(withPrivacyConsent: true)
}

@objc func noConsentTaapped() {
presentNextScreen(withPrivacyConsent: false)
}

private func presentNextScreen(withPrivacyConsent: Bool) {
Preferences.General.basicOnboardingProgress.value = OnboardingProgress.privacyConsent.rawValue
if let urp = UserReferralProgram.shared {
(UIApplication.shared.delegate as? AppDelegate)?
.handleReferralLookup(urp, checkClipboard: withPrivacyConsent)
}

delegate?.presentNextScreen(current: self)
}

override func applyTheme(_ theme: Theme) {
styleChildren(theme: theme)
contentView.applyTheme(theme)
}
}
2 changes: 2 additions & 0 deletions Client/Frontend/Browser/Onboarding/OnboardingState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ enum OnboardingState: Int {
enum OnboardingProgress: Int {
/// The user has never started any onboarding.
case none
/// The user has completed the privacy consent
case privacyConsent
/// The user has completed the search engine onboarding.
case searchEngine
/// The user has completed the rewards onboarding.
Expand Down

0 comments on commit 6aedffb

Please # to comment.