Skip to content

Commit

Permalink
Remove voiceSearchHelper from AppDependencyProvider (#3452)
Browse files Browse the repository at this point in the history
Task/Issue URL: https://app.asana.com/0/414235014887631/1208574561964832/f
Tech Design URL:
CC:

Description:

This PR removes voiceSearchHelper from AppDependencyProvider and updates the test suite to no longer mutate the dependency provider singleton. Tests that use this pattern have been prone to occasional crashes, so I'm simplifying them and working towards removing makeTestingInstance() entirely.
  • Loading branch information
samsymons authored Oct 18, 2024
1 parent 6a93586 commit 8584abe
Show file tree
Hide file tree
Showing 18 changed files with 364 additions and 369 deletions.
12 changes: 8 additions & 4 deletions DuckDuckGo/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,8 @@ import os.log
private let launchOptionsHandler = LaunchOptionsHandler()
private let onboardingPixelReporter = OnboardingPixelReporter()

private let voiceSearchHelper = VoiceSearchHelper()

private let marketplaceAdPostbackManager = MarketplaceAdPostbackManager()
override init() {
super.init()
Expand Down Expand Up @@ -320,7 +322,8 @@ import os.log
if shouldPresentInsufficientDiskSpaceAlertAndCrash {

window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = BlankSnapshotViewController(appSettings: AppDependencyProvider.shared.appSettings)
window?.rootViewController = BlankSnapshotViewController(appSettings: AppDependencyProvider.shared.appSettings,
voiceSearchHelper: voiceSearchHelper)
window?.makeKeyAndVisible()

presentInsufficientDiskSpaceAlert()
Expand All @@ -342,7 +345,8 @@ import os.log
contextualOnboardingPresenter: contextualOnboardingPresenter,
contextualOnboardingLogic: daxDialogs,
contextualOnboardingPixelReporter: onboardingPixelReporter,
subscriptionFeatureAvailability: subscriptionFeatureAvailability)
subscriptionFeatureAvailability: subscriptionFeatureAvailability,
voiceSearchHelper: voiceSearchHelper)

main.loadViewIfNeeded()
syncErrorHandler.alertPresenter = main
Expand All @@ -359,7 +363,7 @@ import os.log
}
}

AppDependencyProvider.shared.voiceSearchHelper.migrateSettingsFlagIfNecessary()
self.voiceSearchHelper.migrateSettingsFlagIfNecessary()

// Task handler registration needs to happen before the end of `didFinishLaunching`, otherwise submitting a task can throw an exception.
// Having both in `didBecomeActive` can sometimes cause the exception when running on a physical device, so registration happens here.
Expand Down Expand Up @@ -828,7 +832,7 @@ import os.log
overlayWindow = UIWindow(frame: frame)
overlayWindow?.windowLevel = UIWindow.Level.alert

let overlay = BlankSnapshotViewController(appSettings: AppDependencyProvider.shared.appSettings)
let overlay = BlankSnapshotViewController(appSettings: AppDependencyProvider.shared.appSettings, voiceSearchHelper: voiceSearchHelper)
overlay.delegate = self

overlayWindow?.rootViewController = overlay
Expand Down
2 changes: 0 additions & 2 deletions DuckDuckGo/AppDependencyProvider.swift
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,6 @@ protocol DependencyProvider {
var internalUserDecider: InternalUserDecider { get }
var featureFlagger: FeatureFlagger { get }
var storageCache: StorageCache { get }
var voiceSearchHelper: VoiceSearchHelperProtocol { get }
var downloadManager: DownloadManager { get }
var autofillLoginSession: AutofillLoginSession { get }
var autofillNeverPromptWebsitesManager: AutofillNeverPromptWebsitesManager { get }
Expand Down Expand Up @@ -64,7 +63,6 @@ final class AppDependencyProvider: DependencyProvider {
let featureFlagger: FeatureFlagger

let storageCache = StorageCache()
let voiceSearchHelper: VoiceSearchHelperProtocol = VoiceSearchHelper()
let downloadManager = DownloadManager()
let autofillLoginSession = AutofillLoginSession()
lazy var autofillNeverPromptWebsitesManager = AutofillNeverPromptWebsitesManager()
Expand Down
6 changes: 4 additions & 2 deletions DuckDuckGo/BlankSnapshotViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,13 +37,15 @@ class BlankSnapshotViewController: UIViewController {

var tabSwitcherButton: TabSwitcherButton!
let appSettings: AppSettings
let voiceSearchHelper: VoiceSearchHelperProtocol

var viewCoordinator: MainViewCoordinator!

weak var delegate: BlankSnapshotViewRecoveringDelegate?

init(appSettings: AppSettings) {
init(appSettings: AppSettings, voiceSearchHelper: VoiceSearchHelperProtocol) {
self.appSettings = appSettings
self.voiceSearchHelper = voiceSearchHelper
super.init(nibName: nil, bundle: nil)
}

Expand All @@ -56,7 +58,7 @@ class BlankSnapshotViewController: UIViewController {

tabSwitcherButton = TabSwitcherButton()

viewCoordinator = MainViewFactory.createViewHierarchy(view)
viewCoordinator = MainViewFactory.createViewHierarchy(view, voiceSearchHelper: voiceSearchHelper)
if appSettings.currentAddressBarPosition.isBottom {
viewCoordinator.moveAddressBarToPosition(.bottom)
viewCoordinator.hideToolbarSeparator()
Expand Down
98 changes: 55 additions & 43 deletions DuckDuckGo/LargeOmniBarState.swift
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,27 @@ struct LargeOmniBarState {
let showShareButton: Bool = false
let clearTextOnStart = true
let allowsTrackersAnimation = false
let showSearchLoupe = !AppDependencyProvider.shared.voiceSearchHelper.isVoiceSearchEnabled
let showPrivacyIcon = false
let showBackground = false
let showClear = false
let showRefresh = false
let showMenu = false
let showSettings = true
let showCancel: Bool = false
let showVoiceSearch = AppDependencyProvider.shared.voiceSearchHelper.isVoiceSearchEnabled
var name: String { return "Pad" + Type.name(self) }
var onEditingStoppedState: OmniBarState { return HomeNonEditingState() }
var onEditingStoppedState: OmniBarState { return HomeNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onEditingStartedState: OmniBarState { return self }
var onTextClearedState: OmniBarState { return self }
var onTextEnteredState: OmniBarState { return HomeTextEditingState() }
var onBrowsingStartedState: OmniBarState { return BrowsingNonEditingState() }
var onTextEnteredState: OmniBarState { return HomeTextEditingState(voiceSearchHelper: voiceSearchHelper) }
var onBrowsingStartedState: OmniBarState { return BrowsingNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onBrowsingStoppedState: OmniBarState { return self }
var onEnterPadState: OmniBarState { return self }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.HomeEmptyEditingState() }
var onReloadState: OmniBarState { return BrowsingNonEditingState() }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.HomeEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onReloadState: OmniBarState { return BrowsingNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var showSearchLoupe: Bool { !voiceSearchHelper.isVoiceSearchEnabled }
var showVoiceSearch: Bool { voiceSearchHelper.isVoiceSearchEnabled }

let voiceSearchHelper: VoiceSearchHelperProtocol
}

struct HomeTextEditingState: OmniBarState {
Expand All @@ -59,25 +61,27 @@ struct LargeOmniBarState {
let showShareButton: Bool = false
let clearTextOnStart = false
let allowsTrackersAnimation = false
let showSearchLoupe = !AppDependencyProvider.shared.voiceSearchHelper.isVoiceSearchEnabled
let showPrivacyIcon = false
let showBackground = false
let showClear = true
let showRefresh = false
let showMenu = false
let showSettings = true
let showCancel: Bool = false
let showVoiceSearch = AppDependencyProvider.shared.voiceSearchHelper.isVoiceSearchEnabled
var name: String { return "Pad" + Type.name(self) }
var onEditingStoppedState: OmniBarState { return HomeNonEditingState() }
var onEditingStoppedState: OmniBarState { return HomeNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onEditingStartedState: OmniBarState { return self }
var onTextClearedState: OmniBarState { return HomeEmptyEditingState() }
var onTextClearedState: OmniBarState { return HomeEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onTextEnteredState: OmniBarState { return self }
var onBrowsingStartedState: OmniBarState { return BrowsingNonEditingState() }
var onBrowsingStoppedState: OmniBarState { return HomeEmptyEditingState() }
var onBrowsingStartedState: OmniBarState { return BrowsingNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onBrowsingStoppedState: OmniBarState { return HomeEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onEnterPadState: OmniBarState { return self }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.HomeTextEditingState() }
var onReloadState: OmniBarState { return HomeTextEditingState() }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.HomeTextEditingState(voiceSearchHelper: voiceSearchHelper) }
var onReloadState: OmniBarState { return HomeTextEditingState(voiceSearchHelper: voiceSearchHelper) }
var showSearchLoupe: Bool { !voiceSearchHelper.isVoiceSearchEnabled }
var showVoiceSearch: Bool { voiceSearchHelper.isVoiceSearchEnabled }

let voiceSearchHelper: VoiceSearchHelperProtocol
}

struct HomeNonEditingState: OmniBarState {
Expand All @@ -96,17 +100,19 @@ struct LargeOmniBarState {
let showMenu = false
let showSettings = true
let showCancel: Bool = false
let showVoiceSearch = AppDependencyProvider.shared.voiceSearchHelper.isVoiceSearchEnabled
var name: String { return "Pad" + Type.name(self) }
var onEditingStoppedState: OmniBarState { return self }
var onEditingStartedState: OmniBarState { return HomeEmptyEditingState() }
var onTextClearedState: OmniBarState { return HomeEmptyEditingState() }
var onTextEnteredState: OmniBarState { return HomeTextEditingState() }
var onBrowsingStartedState: OmniBarState { return BrowsingNonEditingState() }
var onBrowsingStoppedState: OmniBarState { return HomeNonEditingState() }
var onEditingStartedState: OmniBarState { return HomeEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onTextClearedState: OmniBarState { return HomeEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onTextEnteredState: OmniBarState { return HomeTextEditingState(voiceSearchHelper: voiceSearchHelper) }
var onBrowsingStartedState: OmniBarState { return BrowsingNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onBrowsingStoppedState: OmniBarState { return HomeNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onEnterPadState: OmniBarState { return self }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.HomeNonEditingState() }
var onReloadState: OmniBarState { return HomeNonEditingState() }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.HomeNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onReloadState: OmniBarState { return HomeNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var showVoiceSearch: Bool { voiceSearchHelper.isVoiceSearchEnabled }

let voiceSearchHelper: VoiceSearchHelperProtocol
}

struct BrowsingEmptyEditingState: OmniBarState {
Expand All @@ -117,25 +123,27 @@ struct LargeOmniBarState {
let showShareButton: Bool = true
let clearTextOnStart = true
let allowsTrackersAnimation = false
let showSearchLoupe = !AppDependencyProvider.shared.voiceSearchHelper.isVoiceSearchEnabled
let showPrivacyIcon = false
let showBackground = false
let showClear = false
let showRefresh = false
let showMenu = true
let showSettings = false
let showCancel: Bool = false
let showVoiceSearch = AppDependencyProvider.shared.voiceSearchHelper.isVoiceSearchEnabled
var name: String { return "Pad" + Type.name(self) }
var onEditingStoppedState: OmniBarState { return BrowsingNonEditingState() }
var onEditingStoppedState: OmniBarState { return BrowsingNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onEditingStartedState: OmniBarState { return self }
var onTextClearedState: OmniBarState { return self }
var onTextEnteredState: OmniBarState { return BrowsingTextEditingState() }
var onTextEnteredState: OmniBarState { return BrowsingTextEditingState(voiceSearchHelper: voiceSearchHelper) }
var onBrowsingStartedState: OmniBarState { return self }
var onBrowsingStoppedState: OmniBarState { return HomeEmptyEditingState() }
var onBrowsingStoppedState: OmniBarState { return HomeEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onEnterPadState: OmniBarState { return self }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.BrowsingEmptyEditingState() }
var onReloadState: OmniBarState { return BrowsingEmptyEditingState() }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.BrowsingEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onReloadState: OmniBarState { return BrowsingEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var showSearchLoupe: Bool { !voiceSearchHelper.isVoiceSearchEnabled }
var showVoiceSearch: Bool { voiceSearchHelper.isVoiceSearchEnabled }

let voiceSearchHelper: VoiceSearchHelperProtocol
}

struct BrowsingTextEditingState: OmniBarState {
Expand All @@ -146,25 +154,27 @@ struct LargeOmniBarState {
let showShareButton: Bool = true
let clearTextOnStart = false
let allowsTrackersAnimation = false
let showSearchLoupe = !AppDependencyProvider.shared.voiceSearchHelper.isVoiceSearchEnabled
let showPrivacyIcon = false
let showBackground = false
let showClear = true
let showRefresh = false
let showMenu = true
let showSettings = false
let showCancel: Bool = false
let showVoiceSearch = AppDependencyProvider.shared.voiceSearchHelper.isVoiceSearchEnabled
var name: String { return "Pad" + Type.name(self) }
var onEditingStoppedState: OmniBarState { return BrowsingNonEditingState() }
var onEditingStoppedState: OmniBarState { return BrowsingNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onEditingStartedState: OmniBarState { return self }
var onTextClearedState: OmniBarState { return BrowsingEmptyEditingState() }
var onTextClearedState: OmniBarState { return BrowsingEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onTextEnteredState: OmniBarState { return self }
var onBrowsingStartedState: OmniBarState { return self }
var onBrowsingStoppedState: OmniBarState { return HomeEmptyEditingState() }
var onBrowsingStoppedState: OmniBarState { return HomeEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onEnterPadState: OmniBarState { return self }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.BrowsingTextEditingState() }
var onReloadState: OmniBarState { return BrowsingTextEditingState() }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.BrowsingTextEditingState(voiceSearchHelper: voiceSearchHelper) }
var onReloadState: OmniBarState { return BrowsingTextEditingState(voiceSearchHelper: voiceSearchHelper) }
var showSearchLoupe: Bool { !voiceSearchHelper.isVoiceSearchEnabled }
var showVoiceSearch: Bool { voiceSearchHelper.isVoiceSearchEnabled }

let voiceSearchHelper: VoiceSearchHelperProtocol
}

struct BrowsingNonEditingState: OmniBarState {
Expand All @@ -186,14 +196,16 @@ struct LargeOmniBarState {
let showVoiceSearch = false
var name: String { return "Pad" + Type.name(self) }
var onEditingStoppedState: OmniBarState { return self }
var onEditingStartedState: OmniBarState { return BrowsingTextEditingState() }
var onTextClearedState: OmniBarState { return BrowsingEmptyEditingState() }
var onTextEnteredState: OmniBarState { return BrowsingTextEditingState() }
var onEditingStartedState: OmniBarState { return BrowsingTextEditingState(voiceSearchHelper: voiceSearchHelper) }
var onTextClearedState: OmniBarState { return BrowsingEmptyEditingState(voiceSearchHelper: voiceSearchHelper) }
var onTextEnteredState: OmniBarState { return BrowsingTextEditingState(voiceSearchHelper: voiceSearchHelper) }
var onBrowsingStartedState: OmniBarState { return self }
var onBrowsingStoppedState: OmniBarState { return HomeNonEditingState() }
var onBrowsingStoppedState: OmniBarState { return HomeNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onEnterPadState: OmniBarState { return self }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.BrowsingNonEditingState() }
var onReloadState: OmniBarState { return BrowsingNonEditingState() }
var onEnterPhoneState: OmniBarState { return SmallOmniBarState.BrowsingNonEditingState(voiceSearchHelper: voiceSearchHelper) }
var onReloadState: OmniBarState { return BrowsingNonEditingState(voiceSearchHelper: voiceSearchHelper) }

let voiceSearchHelper: VoiceSearchHelperProtocol
}

}
10 changes: 6 additions & 4 deletions DuckDuckGo/MainView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,17 +22,19 @@ import UIKit
class MainViewFactory {

private let coordinator: MainViewCoordinator
private let voiceSearchHelper: VoiceSearchHelperProtocol

var superview: UIView {
coordinator.superview
}

private init(_ superview: UIView) {
private init(superview: UIView, voiceSearchHelper: VoiceSearchHelperProtocol) {
coordinator = MainViewCoordinator(superview: superview)
self.voiceSearchHelper = voiceSearchHelper
}

static func createViewHierarchy(_ superview: UIView) -> MainViewCoordinator {
let factory = MainViewFactory(superview)
static func createViewHierarchy(_ superview: UIView, voiceSearchHelper: VoiceSearchHelperProtocol) -> MainViewCoordinator {
let factory = MainViewFactory(superview: superview, voiceSearchHelper: voiceSearchHelper)
factory.createViews()
factory.disableAutoresizingOnImmediateSubviews(superview)
factory.constrainViews()
Expand Down Expand Up @@ -70,7 +72,7 @@ extension MainViewFactory {
}

private func createOmniBar() {
coordinator.omniBar = OmniBar.loadFromXib()
coordinator.omniBar = OmniBar.loadFromXib(voiceSearchHelper: voiceSearchHelper)
coordinator.omniBar.translatesAutoresizingMaskIntoConstraints = false
}

Expand Down
1 change: 1 addition & 0 deletions DuckDuckGo/MainViewController+Segues.swift
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,7 @@ extension MainViewController {
let settingsViewModel = SettingsViewModel(legacyViewProvider: legacyViewProvider,
subscriptionManager: AppDependencyProvider.shared.subscriptionManager,
subscriptionFeatureAvailability: subscriptionFeatureAvailability,
voiceSearchHelper: voiceSearchHelper,
deepLink: deepLinkTarget,
historyManager: historyManager,
syncPausedStateManager: syncPausedStateManager,
Expand Down
Loading

0 comments on commit 8584abe

Please sign in to comment.