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

Share tracker stats #859

Merged
merged 15 commits into from
Feb 16, 2018
61 changes: 61 additions & 0 deletions Blockzilla/BrowserViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,9 @@ class BrowserViewController: UIViewController {

private var shouldEnsureBrowsingMode = false
private var initialUrl: URL?

private let userDefaultsTrackersBlockedKey = "lifetimeTrackersBlocked"
private let userDefaultsShareTrackerStatsKey = "shareTrackerStats"

convenience init() {
self.init(nibName: nil, bundle: nil)
Expand Down Expand Up @@ -244,6 +247,13 @@ class BrowserViewController: UIViewController {
homeView.removeFromSuperview()
}
self.homeView = homeView

if shouldShowTrackerStatsShareButton() {
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is run after a user taps "Erase" so there is a chance they would not see it on launch but then see it after they erased a browsing session. Is that ok?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A chance they wouldn't see it on launch? And then they would see it every time they 'Erase'?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ahh i miss understood! I thought the 10% rule was just to not show it all the time and annoy users. I will change it to bucket users into groups.

let numberOfTrackersBlocked = getNumberOfLifetimeTrackersBlocked()
homeView.showTrackerStatsShareButton(text: String(format: UIConstants.strings.shareTrackerStatsLabel, String(numberOfTrackersBlocked)))
} else {
homeView.hideTrackerStatsShareButton()
}
}

private func createURLBar() {
Expand Down Expand Up @@ -470,6 +480,40 @@ class BrowserViewController: UIViewController {
UIKeyCommand(input: "]", modifierFlags: .command, action: #selector(BrowserViewController.goForward), discoverabilityTitle: UIConstants.strings.browserForward),
]
}

private func shouldShowTrackerStatsShareButton() -> Bool {
let shouldShowTrackerStatsToUser = UserDefaults.standard.object(forKey: userDefaultsShareTrackerStatsKey) as! Bool?

if shouldShowTrackerStatsToUser == nil {
// User has not been put into a bucket for determining if it should be shown
// 10% chance they get put into the group that sees the share button
// arc4random_uniform(10) returns an integer 0 through 9 (inclusive)
if arc4random_uniform(10) == 0 {
UserDefaults.standard.set(true, forKey: userDefaultsShareTrackerStatsKey)
Telemetry.default.recordEvent(category: TelemetryEventCategory.action, method: TelemetryEventMethod.shareStatsCoinFlip, object: TelemetryEventObject.showStatsShareButton)

} else {
UserDefaults.standard.set(false, forKey: userDefaultsShareTrackerStatsKey)
return false
}
}

if shouldShowTrackerStatsToUser == false ||
getNumberOfLifetimeTrackersBlocked() < 100 ||
NSLocale.current.identifier != "en_US" {
return false
}

return true
}

private func getNumberOfLifetimeTrackersBlocked() -> Int {
return UserDefaults.standard.integer(forKey: userDefaultsTrackersBlockedKey)
}

private func setNumberOfLifetimeTrackersBlocked(numberOfTrackers: Int) {
UserDefaults.standard.set(numberOfTrackers, forKey: userDefaultsTrackersBlockedKey)
}
}

extension BrowserViewController: URLBarDelegate {
Expand Down Expand Up @@ -588,6 +632,16 @@ extension BrowserViewController: HomeViewDelegate {
func homeViewDidPressSettings(homeView: HomeView) {
showSettings()
}

func shareTrackerStatsButtonTapped() {
Telemetry.default.recordEvent(category: TelemetryEventCategory.action, method: TelemetryEventMethod.share, object: TelemetryEventObject.trackerStatsShareButton)

let numberOfTrackersBlocked = getNumberOfLifetimeTrackersBlocked()
let appStoreUrl = String(format: "https://itunes.apple.com/app/id%@", AppInfo.isKlar ? "1073435754" : "1055677337")
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There has got to be a better way to do this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We will get you adjust links to track this install channel. Stay tuned.

let text = String(format: UIConstants.strings.shareTrackerStatsText, AppInfo.productName, String(numberOfTrackersBlocked), appStoreUrl)
let shareController = UIActivityViewController(activityItems: [text], applicationActivities: nil)
present(shareController, animated: true)
}
}

extension BrowserViewController: OverlayViewDelegate {
Expand Down Expand Up @@ -747,6 +801,13 @@ extension BrowserViewController: WebControllerDelegate {
func webController(_ controller: WebController, stateDidChange state: BrowserState) {}

func webController(_ controller: WebController, didUpdateTrackingProtectionStatus trackingStatus: TrackingProtectionStatus) {
// Calculate the number of trackers blocked and add that to lifetime total
if case .on(let info) = trackingStatus,
case .on(let oldInfo) = trackingProtectionStatus {
let differenceSinceLastUpdate = max(0, info.total - oldInfo.total)
let numberOfTrackersBlocked = getNumberOfLifetimeTrackersBlocked()
setNumberOfLifetimeTrackersBlocked(numberOfTrackers: numberOfTrackersBlocked + differenceSinceLastUpdate)
}
trackingProtectionStatus = trackingStatus
}

Expand Down
76 changes: 73 additions & 3 deletions Blockzilla/HomeView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -6,28 +6,31 @@ import Foundation

protocol HomeViewDelegate: class {
func homeViewDidPressSettings(homeView: HomeView)
func shareTrackerStatsButtonTapped()
}

class HomeView: UIView {
weak var delegate: HomeViewDelegate?
private(set) var settingsButton: UIButton! = nil

private let description1 = UILabel()
private let description2 = UILabel()
private let trackerStatsView = UIView()
private let trackerStatsLabel = UILabel()

init() {
super.init(frame: CGRect.zero)

let wordmark = AppInfo.config.wordmark
let textLogo = UIImageView(image: wordmark)
addSubview(textLogo)

let description1 = UILabel()
description1.textColor = .white
description1.font = UIConstants.fonts.homeLabel
description1.textAlignment = .center
description1.text = UIConstants.strings.homeLabel1
description1.numberOfLines = 0
addSubview(description1)

let description2 = UILabel()
description2.textColor = .white
description2.font = UIConstants.fonts.homeLabel
description2.textAlignment = .center
Expand All @@ -42,6 +45,30 @@ class HomeView: UIView {
settingsButton.accessibilityIdentifier = "HomeView.settingsButton"
addSubview(settingsButton)
self.settingsButton = settingsButton

addSubview(trackerStatsView)
trackerStatsView.isHidden = true

let shieldLogo = UIImageView(image: #imageLiteral(resourceName: "tracking_protection"))
shieldLogo.tintColor = UIColor.white
trackerStatsView.addSubview(shieldLogo)

trackerStatsLabel.font = UIConstants.fonts.shareTrackerStatsLabel
trackerStatsLabel.textColor = UIConstants.colors.defaultFont
trackerStatsLabel.numberOfLines = 0
trackerStatsView.addSubview(trackerStatsLabel)

let trackerStatsShareButton = UIButton()
trackerStatsShareButton.setTitleColor(UIConstants.colors.defaultFont, for: .normal)
trackerStatsShareButton.titleLabel?.font = UIConstants.fonts.shareTrackerStatsLabel
trackerStatsShareButton.titleLabel?.textAlignment = .center
trackerStatsShareButton.setTitle(UIConstants.strings.share, for: .normal)
trackerStatsShareButton.addTarget(self, action: #selector(shareTapped), for: .touchUpInside)
trackerStatsShareButton.titleLabel?.numberOfLines = 0
trackerStatsShareButton.layer.borderColor = UIConstants.colors.defaultFont.cgColor
trackerStatsShareButton.layer.borderWidth = 1.0;
trackerStatsShareButton.layer.cornerRadius = 4
trackerStatsView.addSubview(trackerStatsShareButton)

textLogo.snp.makeConstraints { make in
make.centerX.equalTo(self)
Expand All @@ -63,6 +90,32 @@ class HomeView: UIView {
make.trailing.equalTo(safeAreaLayoutGuide).inset(16)
make.height.width.equalTo(24)
}

trackerStatsView.snp.makeConstraints { make in
make.bottom.equalTo(self).offset(-24)
make.height.equalTo(20)
make.centerX.equalToSuperview()
make.width.equalTo(300)
}

trackerStatsLabel.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.equalTo(shieldLogo.snp.right).offset(8)
make.right.equalTo(trackerStatsShareButton.snp.left).offset(13)
make.height.equalToSuperview()
}

shieldLogo.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.left.equalToSuperview()
}

trackerStatsShareButton.snp.makeConstraints { make in
make.centerY.equalToSuperview()
make.right.equalToSuperview()
make.width.equalTo(80)
make.height.equalTo(36)
}
}

required init?(coder aDecoder: NSCoder) {
Expand All @@ -73,6 +126,23 @@ class HomeView: UIView {
delegate?.homeViewDidPressSettings(homeView: self)
}

func showTrackerStatsShareButton(text: String) {
trackerStatsLabel.text = text
trackerStatsView.isHidden = false
description1.isHidden = true
description2.isHidden = true
}

func hideTrackerStatsShareButton() {
trackerStatsView.isHidden = true
description1.isHidden = false
description2.isHidden = false
}

@objc private func shareTapped() {
delegate?.shareTrackerStatsButtonTapped()
}

func setHighlightWhatsNew(shouldHighlight: Bool) {
if shouldHighlight {
settingsButton.setImage(UIImage(named: "preferences_updated"), for: .normal)
Expand Down
3 changes: 3 additions & 0 deletions Blockzilla/TelemetryIntegration.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ class TelemetryEventMethod {
public static let share = "share"
public static let customDomainRemoved = "removed"
public static let customDomainReordered = "reordered"
public static let shareStatsCoinFlip = "share_stats_coin_flip"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this can be removed now, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

good catch. will fix these

}

class TelemetryEventObject {
Expand All @@ -48,4 +49,6 @@ class TelemetryEventObject {
public static let trackingProtectionToggle = "tracking_protection_toggle"
public static let websiteLink = "website_link"
public static let autofill = "autofill"
public static let showStatsShareButton = "show_share_share_button"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and this too?

public static let trackerStatsShareButton = "tracker_stats_share_button"
}
4 changes: 4 additions & 0 deletions Blockzilla/UIConstants.swift
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,7 @@ struct UIConstants {
static let truncatedUrlText = UIFont.systemFont(ofSize: 12)
static let settingsInputLabel = UIFont.systemFont(ofSize: 18)
static let settingsDescriptionText = UIFont.systemFont(ofSize: 12)
static let shareTrackerStatsLabel = UIFont.systemFont(ofSize: 14, weight: UIFont.Weight.light)
}

struct layout {
Expand Down Expand Up @@ -195,6 +196,7 @@ struct UIConstants {
static let saveImage = NSLocalizedString("contextMenu.saveImageTitle", value: "Save Image", comment: "Text for the context menu when a user wants to save an image after long pressing it.")
static let copyImage = NSLocalizedString("contextMenu.copyImageTitle", value: "Copy Image", comment: "Text for the context menu when a user wants to copy an image after long pressing it.")
static let shareLink = NSLocalizedString("contextMenu.shareLinkTitle", value: "Share Link", comment: "Text for the context menu when a user wants to share a link after long pressing it.")
static let share = NSLocalizedString("share", value: "Share", comment: "Text for a share button")
static let copyLink = NSLocalizedString("contextMenu.copyLink", value: "Copy Link", comment: "Text for the context menu when a user wants to copy a link after long pressing it.")
static let trackersBlocked = NSLocalizedString("URL.trackersBlockedLabel", value: "Trackers blocked", comment: "Text for the URL bar showing the number of trackers blocked on a webpage.")
static let externalAppLink = NSLocalizedString("ExternalAppLink.messageTitle", value: "%@ wants to open another App", comment: "Dialog title used for opening an external app from Focus. The placeholder string is the app name of either Focus or Klar.")
Expand Down Expand Up @@ -264,5 +266,7 @@ struct UIConstants {
static let autocompleteAddCustomUrlExample = NSLocalizedString("Autocomplete.addCustomUrlExample", value: "Example: example.com", comment: "A label displaying an example URL")
static let autocompleteEmptyState = NSLocalizedString("Autocomplete.emptyState", value: "No Custom URLs to display", comment: "Label for button to add a custom URL")
static let autocompleteCustomURLAdded = NSLocalizedString("Autocomplete.customUrlAdded", value: "New Custom URL added.", comment: "Label for toast alerting a custom URL has been added")
static let shareTrackerStatsLabel = NSLocalizedString("share.trackerStatsLabel", value: "%@ trackers blocked so far", comment: "Text used when the user shares their trackers blocked stats")
static let shareTrackerStatsText = NSLocalizedString("share.trackerStatsText", value: "By using %@, I've blocked %@ trackers! No more ads following me around the internet! Download it here: %@", comment: "The text shared to users after the user chooses to share there tracker stats")
}
}