Skip to content

Commit

Permalink
Fix #3298: Add support for Xcode 16 (#3299)
Browse files Browse the repository at this point in the history
Task/Issue URL: #3298 & https://app.asana.com/0/414709148257752/1208200157992058/f
Tech Design URL:
CC:

Description:

Resolves #3298

This PR allows this repo to be compiled with Xcode 16.
Two changes had to be made:

In iOS 18 Apple added a new field to UIViewController named tab.
It causes ambiguity and has to be renamed.
Source https://developer.apple.com/documentation/uikit/uiviewcontroller/4434584-tab
I renamed it to _tab, I am open to any other rename suggestion

The URLOpener protocol and Apple's UIApplication shared the same
signature for url opening function. This resulted in ambiguous compile
time error.
Code is now simplified and still allows to be used in mocks.

Changes I made should be backwards compatible and work in Xcode 15 as well
  • Loading branch information
iccub authored Sep 4, 2024
1 parent c334197 commit 76b9d1d
Show file tree
Hide file tree
Showing 12 changed files with 22 additions and 38 deletions.
8 changes: 3 additions & 5 deletions Core/URLOpener.swift
Original file line number Diff line number Diff line change
Expand Up @@ -21,13 +21,11 @@ import UIKit

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

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

extension UIApplication: URLOpener {}
4 changes: 2 additions & 2 deletions DuckDuckGo/CriticalAlerts.swift
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ struct CriticalAlerts {

let openSettingsButton = UIAlertAction(title: UserText.insufficientDiskSpaceAction, style: .default) { _ in
let url = URL(string: UIApplication.openSettingsURLString)!
UIApplication.shared.open(url, options: [:]) { _ in
UIApplication.shared.open(url) { _ in
fatalError("App is in unrecoverable state")
}
}
Expand All @@ -59,7 +59,7 @@ struct CriticalAlerts {

let closeButton = UIAlertAction(title: UserText.keyCommandClose, style: .cancel)
let signInButton = UIAlertAction(title: UserText.emailProtectionSignInAction, style: .default) { _ in
UIApplication.shared.open(URL.emailProtectionQuickLink, options: [:], completionHandler: nil)
UIApplication.shared.open(URL.emailProtectionQuickLink)
}

alertController.addAction(closeButton)
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/MainViewController+Email.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ extension MainViewController {

func newEmailAddress() {
guard emailManager.isSignedIn else {
UIApplication.shared.open(URL.emailProtectionQuickLink, options: [:], completionHandler: nil)
UIApplication.shared.open(URL.emailProtectionQuickLink)
return
}

Expand Down
6 changes: 3 additions & 3 deletions DuckDuckGo/NewTabPageViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ final class NewTabPageViewController: UIHostingController<NewTabPageView<Favorit
private let shortcutsModel: ShortcutsModel
private let shortcutsSettingsModel: NewTabPageShortcutsSettingsModel
private let sectionsSettingsModel: NewTabPageSectionsSettingsModel
private let tab: Tab
private let associatedTab: Tab

private var hostingController: UIHostingController<AnyView>?

Expand All @@ -53,7 +53,7 @@ final class NewTabPageViewController: UIHostingController<NewTabPageView<Favorit
newTabDialogFactory: any NewTabDaxDialogProvider,
newTabDialogTypeProvider: NewTabDialogSpecProvider) {

self.tab = tab
self.associatedTab = tab
self.syncService = syncService
self.syncBookmarksAdapter = syncBookmarksAdapter
self.variantManager = variantManager
Expand Down Expand Up @@ -82,7 +82,7 @@ final class NewTabPageViewController: UIHostingController<NewTabPageView<Favorit
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)

tab.viewed = true
associatedTab.viewed = true

presentNextDaxDialog()

Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/NoMicPermissionAlert.swift
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ struct NoMicPermissionAlert {

let openSettingsButton = UIAlertAction(title: UserText.noVoicePermissionActionSettings, style: .default) { _ in
let url = URL(string: UIApplication.openSettingsURLString)!
UIApplication.shared.open(url, options: [:], completionHandler: nil)
UIApplication.shared.open(url)
}
let cancelAction = UIAlertAction(title: UserText.actionCancel, style: .cancel, handler: nil)

Expand Down
24 changes: 6 additions & 18 deletions DuckDuckGo/SettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -524,33 +524,23 @@ extension SettingsViewModel {
}

func openEmailProtection() {
UIApplication.shared.open(URL.emailProtectionQuickLink,
options: [:],
completionHandler: nil)
UIApplication.shared.open(URL.emailProtectionQuickLink)
}

func openEmailAccountManagement() {
UIApplication.shared.open(URL.emailProtectionAccountLink,
options: [:],
completionHandler: nil)
UIApplication.shared.open(URL.emailProtectionAccountLink)
}

func openEmailSupport() {
UIApplication.shared.open(URL.emailProtectionSupportLink,
options: [:],
completionHandler: nil)
UIApplication.shared.open(URL.emailProtectionSupportLink)
}

func openOtherPlatforms() {
UIApplication.shared.open(URL.apps,
options: [:],
completionHandler: nil)
UIApplication.shared.open(URL.apps)
}

func openMoreSearchSettings() {
UIApplication.shared.open(URL.searchSettings,
options: [:],
completionHandler: nil)
UIApplication.shared.open(URL.searchSettings)
}

var shouldDisplayDuckPlayerContingencyMessage: Bool {
Expand All @@ -560,9 +550,7 @@ extension SettingsViewModel {
func openDuckPlayerContingencyMessageSite() {
guard let url = duckPlayerContingencyHandler.learnMoreURL else { return }
Pixel.fire(pixel: .duckPlayerContingencyLearnMoreClicked)
UIApplication.shared.open(url,
options: [:],
completionHandler: nil)
UIApplication.shared.open(url)
}

@MainActor func openCookiePopupManagement() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ extension HeadlessWebViewCoordinator: WKNavigationDelegate {

// Handle custom schemes (e.g., tel:, facetime:, etc.)
if Constants.externalSchemes.contains(scheme), UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
UIApplication.shared.open(url)
decisionHandler(.cancel)
return
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,7 @@ final class SubscriptionSettingsViewModel: ObservableObject {
@MainActor
private func openURL(_ url: URL) {
if UIApplication.shared.canOpenURL(url) {
UIApplication.shared.open(url, options: [:], completionHandler: nil)
UIApplication.shared.open(url)
}
}

Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/SyncSettingsViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -407,7 +407,7 @@ extension SyncSettingsViewController: ScanOrPasteCodeViewModelDelegate {

func gotoSettings() {
if let appSettings = URL(string: UIApplication.openSettingsURLString) {
UIApplication.shared.open(appSettings, options: [:], completionHandler: nil)
UIApplication.shared.open(appSettings)
}
}

Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGo/TabViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -1042,7 +1042,7 @@ class TabViewController: UIViewController {
private func openExternally(url: URL) {
self.url = webView.url
delegate?.tabLoadingStateDidChange(tab: self)
UIApplication.shared.open(url, options: [:]) { opened in
UIApplication.shared.open(url) { opened in
if !opened {
let addressBarBottom = self.appSettings.currentAddressBarPosition.isBottom
ActionMessageView.present(message: UserText.failedToOpenExternally,
Expand Down
2 changes: 1 addition & 1 deletion DuckDuckGoTests/MockURLOpener.swift
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ final class MockURLOpener: URLOpener {
return canOpenURL
}

func open(_ url: URL, options: [UIApplication.OpenExternalURLOptionsKey: Any], completionHandler completion: ((Bool) -> Void)?) {
func open(_ url: URL) {
didCallOpenURL = true
capturedURL = url
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,9 +99,7 @@ public struct SyncSettingsView: View {
title: Text("Secure Your Device to Use Sync & Backup"),
message: Text("A device password is required to use Sync & Backup."),
dismissButton: .default(Text("Go to Settings"), action: {
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!,
options: [:],
completionHandler: nil)
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
model.shouldShowPasscodeRequiredAlert = false
})
)
Expand Down

0 comments on commit 76b9d1d

Please sign in to comment.