Skip to content

Commit

Permalink
Onboarding Intro Experiment (#3074)
Browse files Browse the repository at this point in the history
  • Loading branch information
alessandroboron authored Jul 14, 2024
1 parent ab0bb3d commit 01ebb16
Show file tree
Hide file tree
Showing 87 changed files with 3,688 additions and 26 deletions.
4 changes: 4 additions & 0 deletions Core/DefaultVariantManager.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extension FeatureName {
// Define your feature e.g.:
// public static let experimentalFeature = FeatureName(rawValue: "experimentalFeature")

public static let newOnboardingIntro = FeatureName(rawValue: "newOnboardingIntro")
}

public struct VariantIOS: Variant {
Expand Down Expand Up @@ -61,6 +62,9 @@ public struct VariantIOS: Variant {
VariantIOS(name: "sd", weight: doNotAllocate, isIncluded: When.always, features: []),
VariantIOS(name: "se", weight: doNotAllocate, isIncluded: When.always, features: []),

VariantIOS(name: "ma", weight: 1, isIncluded: When.always, features: []),
VariantIOS(name: "mb", weight: 1, isIncluded: When.always, features: [.newOnboardingIntro]),

returningUser
]

Expand Down
8 changes: 8 additions & 0 deletions Core/PixelEvent.swift
Original file line number Diff line number Diff line change
Expand Up @@ -139,6 +139,10 @@ extension Pixel {

case brokenSiteReport

case onboardingIntroShownUnique
case onboardingIntroComparisonChartShownUnique
case onboardingIntroChooseBrowserCTAPressed

case daxDialogsSerp
case daxDialogsWithoutTrackers
case daxDialogsWithoutTrackersFollowUp
Expand Down Expand Up @@ -876,6 +880,10 @@ extension Pixel.Event {

case .brokenSiteReport: return "epbf"

case .onboardingIntroShownUnique: return "m_preonboarding_intro_shown_unique"
case .onboardingIntroComparisonChartShownUnique: return "m_preonboarding_comparison_chart_shown_unique"
case .onboardingIntroChooseBrowserCTAPressed: return "m_preonboarding_choose_browser_pressed"

case .daxDialogsSerp: return "m_dx_s"
case .daxDialogsWithoutTrackers: return "m_dx_wo"
case .daxDialogsWithoutTrackersFollowUp: return "m_dx_wof"
Expand Down
42 changes: 42 additions & 0 deletions Core/TimerInterface.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
//
// TimerInterface.swift
// DuckDuckGo
//
// Copyright © 2024 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import Foundation

public protocol TimerInterface: AnyObject {
var isValid: Bool { get }
func invalidate()
func fire()
}

extension Timer: TimerInterface {}

public protocol TimerCreating: AnyObject {
func makeTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping @Sendable (TimerInterface) -> Void) -> TimerInterface
}

public final class TimerFactory: TimerCreating {

public init() {}

public func makeTimer(withTimeInterval interval: TimeInterval, repeats: Bool, block: @escaping @Sendable (TimerInterface) -> Void) -> TimerInterface {
Timer.scheduledTimer(withTimeInterval: interval, repeats: repeats, block: block)
}

}
33 changes: 33 additions & 0 deletions Core/URLOpener.swift
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
//
// URLOpener.swift
// DuckDuckGo
//
// Copyright © 2024 DuckDuckGo. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
//

import UIKit

public protocol URLOpener: AnyObject {
func canOpenURL(_ url: URL) -> Bool
func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey: Any], completionHandler completion: ((Bool) -> Void)?)
}

public extension URLOpener {
func open(_ url: URL) {
open(url, options: [:], completionHandler: nil)
}
}

extension UIApplication: URLOpener {}
4 changes: 2 additions & 2 deletions Core/UniquePixel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -54,8 +54,8 @@ public final class UniquePixel {
withAdditionalParameters params: [String: String] = [:],
includedParameters: [Pixel.QueryParameters] = [.appVersion],
onComplete: @escaping (Swift.Error?) -> Void = { _ in }) {
guard pixel.name.hasSuffix("_u") else {
assertionFailure("Unique pixel: must end with _u")
guard pixel.name.hasSuffix("_u") || pixel.name.hasSuffix("_unique") else {
assertionFailure("Unique pixel: must end with _u or _unique")
return
}

Expand Down
Loading

0 comments on commit 01ebb16

Please sign in to comment.