From 3e09d3cc9cb1dc8f84da0269c8cad7984e6e2781 Mon Sep 17 00:00:00 2001 From: Sam Symons Date: Thu, 25 Jul 2024 17:00:15 -0700 Subject: [PATCH] iOS 14 deprecation cleanup (#3098) Task/Issue URL: https://app.asana.com/0/414709148257752/1207384568093644/f Tech Design URL: CC: Description: This PR removes iOS 14 support code now that 15 is our minimum deployment target. --- Core/DefaultVariantManager.swift | 7 - Core/PixelEvent.swift | 4 - DuckDuckGo.xcodeproj/project.pbxproj | 4 - DuckDuckGo/ActionMessageView.swift | 2 +- .../AdAttribution/AdAttributionFetcher.swift | 10 +- DuckDuckGo/AnimatableTypingText.swift | 13 +- DuckDuckGo/AppDelegate.swift | 8 +- DuckDuckGo/AppDependencyProvider.swift | 16 +- DuckDuckGo/AutofillLoginDetailsView.swift | 32 ++-- .../AutofillLoginDetailsViewController.swift | 12 +- .../AutofillLoginPromptViewController.swift | 9 +- ...ofillLoginSettingsListViewController.swift | 28 ++-- DuckDuckGo/CompleteDownloadRow.swift | 1 - DuckDuckGo/DownloadsList.swift | 24 +-- .../DownloadsListHostingController.swift | 2 +- .../DuckPlayerNavigationHandler.swift | 18 +-- .../Modal/DuckPlayerModalPresenter.swift | 14 +- DuckDuckGo/Favicons.swift | 8 +- DuckDuckGo/Feedback/VPNFeedbackFormView.swift | 2 - DuckDuckGo/FireButtonAnimator.swift | 2 +- DuckDuckGo/HomeMessageView.swift | 2 +- DuckDuckGo/ImportPasswordsView.swift | 3 +- DuckDuckGo/ImportPasswordsViewModel.swift | 2 - DuckDuckGo/InlineWKDownloadDelegate.swift | 1 - DuckDuckGo/MainViewController+Email.swift | 32 ++-- .../MainViewController+KeyCommands.swift | 6 +- DuckDuckGo/MainViewController.swift | 17 +-- .../NetworkProtectionDNSSettingsView.swift | 2 - ...NetworkProtectionDebugViewController.swift | 2 +- DuckDuckGo/NetworkProtectionRootView.swift | 1 - .../NetworkProtectionRootViewController.swift | 2 - DuckDuckGo/NetworkProtectionStatusView.swift | 2 - .../NetworkProtectionVPNLocationView.swift | 4 - .../NetworkProtectionVPNSettingsView.swift | 1 - DuckDuckGo/OngoingDownloadRow.swift | 2 +- DuckDuckGo/PasswordGenerationPromptView.swift | 6 +- DuckDuckGo/PreserveLoginsWorker.swift | 2 +- DuckDuckGo/SettingsLegacyViewProvider.swift | 2 - DuckDuckGo/SettingsRootView.swift | 42 ++---- DuckDuckGo/SettingsSubscriptionView.swift | 1 - DuckDuckGo/SettingsViewModel.swift | 17 +-- DuckDuckGo/SpeechRecognizer.swift | 9 +- DuckDuckGo/SpeechRecognizerProtocol.swift | 1 - .../HeadlessWebView.swift | 2 +- .../SubscriptionManageriOS14.swift | 51 ------- ...IdentityTheftRestorationPagesFeature.swift | 1 - ...scriptionPagesUseSubscriptionFeature.swift | 1 - .../SubscriptionContainerViewModel.swift | 1 - .../SubscriptionEmailViewModel.swift | 1 - .../ViewModel/SubscriptionFlowViewModel.swift | 1 - .../ViewModel/SubscriptionITPViewModel.swift | 1 - .../ViewModel/SubscriptionPIRViewModel.swift | 1 - .../SubscriptionRestoreViewModel.swift | 1 - .../SubscriptionSettingsViewModel.swift | 1 - .../Views/SubscriptionContainerView.swift | 1 - .../SubscriptionContainerViewFactory.swift | 1 - .../Views/SubscriptionEmailView.swift | 2 - .../Views/SubscriptionExternalLinkView.swift | 1 - .../Views/SubscriptionFlowView.swift | 2 - .../Views/SubscriptionGoogleView.swift | 4 - .../Views/SubscriptionITPView.swift | 2 - .../Views/SubscriptionPIRView.swift | 2 - .../Views/SubscriptionRestoreView.swift | 1 - .../Views/SubscriptionSettingsView.swift | 2 - .../SubscriptionDebugViewController.swift | 2 +- DuckDuckGo/SyncSettingsViewController.swift | 12 +- DuckDuckGo/TabSwitcherViewController.swift | 6 +- DuckDuckGo/TabViewController.swift | 140 ++++-------------- .../TextSizeSettingsViewController.swift | 63 ++++---- DuckDuckGo/Themable.swift | 20 +-- DuckDuckGo/UIApplicationExtension.swift | 12 +- DuckDuckGo/UIScrollViewExtension.swift | 2 +- DuckDuckGo/URLRequestExtension.swift | 12 +- DuckDuckGo/ViewExtension.swift | 7 - DuckDuckGo/VoiceSearchFeedbackView.swift | 11 +- DuckDuckGo/VoiceSearchFeedbackViewModel.swift | 1 - DuckDuckGo/VoiceSearchHelper.swift | 3 - DuckDuckGo/WKDownloadSession.swift | 2 - DuckDuckGo/global.swift | 2 +- .../AnimatableTypingTextModelTests.swift | 8 - DuckDuckGoTests/MockDependencyProvider.swift | 26 ++-- .../SubscriptionContainerViewModelTests.swift | 1 - .../SubscriptionFlowViewModelTests.swift | 1 - ...tionPagesUseSubscriptionFeatureTests.swift | 1 - LocalPackages/DuckUI/Package.swift | 2 +- LocalPackages/SyncUI/Package.swift | 2 +- .../Views/Internal/ViewExtensions.swift | 18 +-- .../Sources/SyncUI/Views/PasteCodeView.swift | 20 +-- .../SyncUI/Views/ScanOrPasteCodeView.swift | 7 +- .../Views/SyncSettingsViewExtension.swift | 18 +-- LocalPackages/Waitlist/Package.swift | 2 +- OpenAction/ActionViewController.swift | 9 +- ...orkProtectionUNNotificationPresenter.swift | 7 +- 93 files changed, 247 insertions(+), 625 deletions(-) delete mode 100644 DuckDuckGo/Subscription/SubscriptionManageriOS14.swift diff --git a/Core/DefaultVariantManager.swift b/Core/DefaultVariantManager.swift index c2f73b4dc8..d7f4b63855 100644 --- a/Core/DefaultVariantManager.swift +++ b/Core/DefaultVariantManager.swift @@ -40,13 +40,6 @@ public struct VariantIOS: Variant { .contains(where: { Locale.current.regionCode == $0 }) } static let inEnglish = { return Locale.current.languageCode == "en" } - - static let iOS15 = { () -> Bool in - if #available(iOS 15, *) { - return true - } - return false - } } /// This variant is used for returning users to separate them from really new users. diff --git a/Core/PixelEvent.swift b/Core/PixelEvent.swift index f16f3a6e02..d808341c51 100644 --- a/Core/PixelEvent.swift +++ b/Core/PixelEvent.swift @@ -201,8 +201,6 @@ extension Pixel { case downloadsSharingPredownloadedLocalFile - case downloadAttemptToOpenBLOBviaJS - case jsAlertShown case featureFlaggingInternalUserAuthenticated @@ -920,8 +918,6 @@ extension Pixel.Event { case .downloadsSharingPredownloadedLocalFile: return "m_downloads_sharing_predownloaded_local_file" - case .downloadAttemptToOpenBLOBviaJS: return "m_download_attempt_to_open_blob_js" - case .jsAlertShown: return "m_js_alert_shown" case .featureFlaggingInternalUserAuthenticated: return "m_internal-user_authenticated" diff --git a/DuckDuckGo.xcodeproj/project.pbxproj b/DuckDuckGo.xcodeproj/project.pbxproj index c4f2307fc0..60e97d8ef4 100644 --- a/DuckDuckGo.xcodeproj/project.pbxproj +++ b/DuckDuckGo.xcodeproj/project.pbxproj @@ -951,7 +951,6 @@ F15531962BF215F60029ED04 /* SubscriptionTestingUtilities in Frameworks */ = {isa = PBXBuildFile; productRef = F15531952BF215F60029ED04 /* SubscriptionTestingUtilities */; }; F1564F032B7B915F00D454A6 /* AppDelegate+SKAD4.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1564F022B7B915F00D454A6 /* AppDelegate+SKAD4.swift */; }; F15D43201E706CC500BF2CDC /* AutocompleteViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15D431F1E706CC500BF2CDC /* AutocompleteViewController.swift */; }; - F15E9F3E2BEE128200DEFDDE /* SubscriptionManageriOS14.swift in Sources */ = {isa = PBXBuildFile; fileRef = F15E9F3D2BEE128200DEFDDE /* SubscriptionManageriOS14.swift */; }; F1617C131E572E0300DEDCAF /* TabSwitcherViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1617C121E572E0300DEDCAF /* TabSwitcherViewController.swift */; }; F1617C151E57336D00DEDCAF /* TabManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1617C141E57336D00DEDCAF /* TabManager.swift */; }; F1617C191E573EA800DEDCAF /* TabSwitcherDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = F1617C181E573EA800DEDCAF /* TabSwitcherDelegate.swift */; }; @@ -2667,7 +2666,6 @@ F1564F022B7B915F00D454A6 /* AppDelegate+SKAD4.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "AppDelegate+SKAD4.swift"; sourceTree = ""; }; F159BDA31F0BDB5A00B4A01D /* TabViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabViewController.swift; sourceTree = ""; }; F15D431F1E706CC500BF2CDC /* AutocompleteViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutocompleteViewController.swift; sourceTree = ""; }; - F15E9F3D2BEE128200DEFDDE /* SubscriptionManageriOS14.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionManageriOS14.swift; sourceTree = ""; }; F1617C121E572E0300DEDCAF /* TabSwitcherViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabSwitcherViewController.swift; sourceTree = ""; }; F1617C141E57336D00DEDCAF /* TabManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabManager.swift; sourceTree = ""; }; F1617C181E573EA800DEDCAF /* TabSwitcherDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TabSwitcherDelegate.swift; sourceTree = ""; }; @@ -4749,7 +4747,6 @@ children = ( F1FDC92F2BF4E0B3006B1435 /* SubscriptionEnvironment+Default.swift */, D60170BB2BA32DD6001911B5 /* Subscription.swift */, - F15E9F3D2BEE128200DEFDDE /* SubscriptionManageriOS14.swift */, D6D95CE42B6DA3F200960317 /* AsyncHeadlessWebview */, D664C7952B289AA000CBFA76 /* Subscription.storekit */, D664C7932B289AA000CBFA76 /* ViewModel */, @@ -6699,7 +6696,6 @@ 3132FA2627A0784600DD7A12 /* FilePreviewHelper.swift in Sources */, 9820FF502244FECC008D4782 /* UIScrollViewExtension.swift in Sources */, 8540BD5423D8D5080057FDD2 /* PreserveLoginsAlert.swift in Sources */, - F15E9F3E2BEE128200DEFDDE /* SubscriptionManageriOS14.swift in Sources */, 1E87615928A1517200C7C5CE /* PrivacyDashboardViewController.swift in Sources */, 6F03CAFE2C32DD08004179A8 /* HomePageMessagesConfiguration.swift in Sources */, EE9D68D12AE00CF300B55EF4 /* NetworkProtectionVPNSettingsView.swift in Sources */, diff --git a/DuckDuckGo/ActionMessageView.swift b/DuckDuckGo/ActionMessageView.swift index 57ff705e6e..f0a3ef3f63 100644 --- a/DuckDuckGo/ActionMessageView.swift +++ b/DuckDuckGo/ActionMessageView.swift @@ -124,7 +124,7 @@ class ActionMessageView: UIView { presentationLocation: PresentationLocation = .withBottomBar(andAddressBarBottom: false), onAction: @escaping () -> Void = {}, onDidDismiss: @escaping () -> Void = {}) { - guard let window = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first else { return } + guard let window = UIApplication.shared.firstKeyWindow else { return } dismissAllMessages() diff --git a/DuckDuckGo/AdAttribution/AdAttributionFetcher.swift b/DuckDuckGo/AdAttribution/AdAttributionFetcher.swift index a9d3d31a80..b052a0c127 100644 --- a/DuckDuckGo/AdAttribution/AdAttributionFetcher.swift +++ b/DuckDuckGo/AdAttribution/AdAttributionFetcher.swift @@ -46,10 +46,6 @@ struct DefaultAdAttributionFetcher: AdAttributionFetcher { } func fetch() async -> AdServicesAttributionResponse? { - guard #available(iOS 14.3, *) else { - return nil - } - var lastToken: String? for _ in 0.. String { - if #available(iOS 14.3, *) { - return try AAAttribution.attributionToken() - } else { - throw AdAttributionFetcherError.attributionUnsupported - } + return try AAAttribution.attributionToken() } } diff --git a/DuckDuckGo/AnimatableTypingText.swift b/DuckDuckGo/AnimatableTypingText.swift index 7e323f99af..b391d447f0 100644 --- a/DuckDuckGo/AnimatableTypingText.swift +++ b/DuckDuckGo/AnimatableTypingText.swift @@ -47,13 +47,8 @@ struct AnimatableTypingText: View { .frame(maxWidth: .infinity, alignment: .leading) .visibility(.invisible) - if #available(iOS 15, *) { - Text(AttributedString(model.typedAttributedText)) - .frame(maxWidth: .infinity, alignment: .leading) - } else { - Text(model.typedAttributedText.string) - .frame(maxWidth: .infinity, alignment: .leading) - } + Text(AttributedString(model.typedAttributedText)) + .frame(maxWidth: .infinity, alignment: .leading) } .onChange(of: startAnimating.wrappedValue, perform: { shouldAnimate in if shouldAnimate { @@ -128,10 +123,6 @@ final class AnimatableTypingTextModel: ObservableObject { private func showCharacter() { func attributedTypedString(forTypedChars typedChars: [String.Element]) -> NSAttributedString { - guard #available(iOS 15, *) else { - return NSAttributedString(string: String(typedChars)) - } - let chars = Array(text) let untypedChars = chars[typedChars.count ..< chars.count] let combined = NSMutableAttributedString(string: String(typedChars)) diff --git a/DuckDuckGo/AppDelegate.swift b/DuckDuckGo/AppDelegate.swift index 6557443cb4..fb86aaeac1 100644 --- a/DuckDuckGo/AppDelegate.swift +++ b/DuckDuckGo/AppDelegate.swift @@ -802,7 +802,7 @@ import WebKit } private func tryToObtainOverlayWindow() { - for window in UIApplication.shared.windows where window.rootViewController is BlankSnapshotViewController { + for window in UIApplication.shared.foregroundSceneWindows where window.rootViewController is BlankSnapshotViewController { overlayWindow = window return } @@ -1007,10 +1007,8 @@ extension AppDelegate: UNUserNotificationCenterDelegate { Task { if case .success(let hasEntitlements) = await accountManager.hasEntitlement(forProductName: .networkProtection), hasEntitlements { - if #available(iOS 15, *) { - let networkProtectionRoot = NetworkProtectionRootViewController() - presentSettings(with: networkProtectionRoot) - } + let networkProtectionRoot = NetworkProtectionRootViewController() + presentSettings(with: networkProtectionRoot) } else { (window?.rootViewController as? MainViewController)?.segueToPrivacyPro() } diff --git a/DuckDuckGo/AppDependencyProvider.swift b/DuckDuckGo/AppDependencyProvider.swift index fea06bf74e..9fb8e62f7c 100644 --- a/DuckDuckGo/AppDependencyProvider.swift +++ b/DuckDuckGo/AppDependencyProvider.swift @@ -111,16 +111,12 @@ class AppDependencyProvider: DependencyProvider { entitlementsCache: entitlementsCache, subscriptionEndpointService: subscriptionService, authEndpointService: authService) - if #available(iOS 15.0, *) { - subscriptionManager = DefaultSubscriptionManager(storePurchaseManager: DefaultStorePurchaseManager(), - accountManager: accountManager, - subscriptionEndpointService: subscriptionService, - authEndpointService: authService, - subscriptionEnvironment: subscriptionEnvironment) - } else { - // This is used just for iOS <15, it's a sort of mocked environment that will not be used. - subscriptionManager = SubscriptionManageriOS14(accountManager: accountManager) - } + + subscriptionManager = DefaultSubscriptionManager(storePurchaseManager: DefaultStorePurchaseManager(), + accountManager: accountManager, + subscriptionEndpointService: subscriptionService, + authEndpointService: authService, + subscriptionEnvironment: subscriptionEnvironment) let subscriptionFeatureAvailability: SubscriptionFeatureAvailability = DefaultSubscriptionFeatureAvailability( privacyConfigurationManager: ContentBlocking.shared.privacyConfigurationManager, diff --git a/DuckDuckGo/AutofillLoginDetailsView.swift b/DuckDuckGo/AutofillLoginDetailsView.swift index d645e9b346..934f380071 100644 --- a/DuckDuckGo/AutofillLoginDetailsView.swift +++ b/DuckDuckGo/AutofillLoginDetailsView.swift @@ -74,7 +74,7 @@ struct AutofillLoginDetailsView: View { viewModel.selectedCell = nil })) .listStyle(.insetGrouped) - .animation(.easeInOut) + .animation(.easeInOut, value: viewModel.viewMode) } private var editingContentView: some View { @@ -191,27 +191,19 @@ struct AutofillLoginDetailsView: View { usernameCell() } footer: { if !viewModel.isSignedIn { - if #available(iOS 15, *) { - var attributedString: AttributedString { - let text = String(format: UserText.autofillSignInToManageEmail, UserText.autofillEnableEmailProtection) - var attributedString = AttributedString(text) - if let range = attributedString.range(of: UserText.autofillEnableEmailProtection) { - attributedString[range].foregroundColor = Color(ThemeManager.shared.currentTheme.buttonTintColor) - } - return attributedString + var attributedString: AttributedString { + let text = String(format: UserText.autofillSignInToManageEmail, UserText.autofillEnableEmailProtection) + var attributedString = AttributedString(text) + if let range = attributedString.range(of: UserText.autofillEnableEmailProtection) { + attributedString[range].foregroundColor = Color(ThemeManager.shared.currentTheme.buttonTintColor) } - Text(attributedString) - .font(.footnote) - .lineLimit(nil) - .multilineTextAlignment(.leading) - .fixedSize(horizontal: false, vertical: true) - } else { - Text(String(format: UserText.autofillSignInToManageEmail, UserText.autofillEnableEmailProtection)) - .font(.footnote) - .lineLimit(nil) - .multilineTextAlignment(.leading) - .fixedSize(horizontal: false, vertical: true) + return attributedString } + Text(attributedString) + .font(.footnote) + .lineLimit(nil) + .multilineTextAlignment(.leading) + .fixedSize(horizontal: false, vertical: true) } } .onTapGesture { diff --git a/DuckDuckGo/AutofillLoginDetailsViewController.swift b/DuckDuckGo/AutofillLoginDetailsViewController.swift index 2fde29ee32..1a08045aa1 100644 --- a/DuckDuckGo/AutofillLoginDetailsViewController.swift +++ b/DuckDuckGo/AutofillLoginDetailsViewController.swift @@ -343,13 +343,11 @@ extension AutofillLoginDetailsViewController { navigationController?.navigationBar.barTintColor = theme.barBackgroundColor navigationController?.navigationBar.tintColor = theme.navigationBarTintColor - if #available(iOS 15.0, *) { - let appearance = UINavigationBarAppearance() - appearance.shadowColor = .clear - appearance.backgroundColor = theme.backgroundColor + let appearance = UINavigationBarAppearance() + appearance.shadowColor = .clear + appearance.backgroundColor = theme.backgroundColor - navigationController?.navigationBar.standardAppearance = appearance - navigationController?.navigationBar.scrollEdgeAppearance = appearance - } + navigationController?.navigationBar.standardAppearance = appearance + navigationController?.navigationBar.scrollEdgeAppearance = appearance } } diff --git a/DuckDuckGo/AutofillLoginPromptViewController.swift b/DuckDuckGo/AutofillLoginPromptViewController.swift index 701ef51c0e..5841f4c36c 100644 --- a/DuckDuckGo/AutofillLoginPromptViewController.swift +++ b/DuckDuckGo/AutofillLoginPromptViewController.swift @@ -82,8 +82,7 @@ class AutofillLoginPromptViewController: UIViewController { if #available(iOS 16.0, *) { return true } - if #available(iOS 15.0, *), - let presentationController = presentationController as? UISheetPresentationController { + if let presentationController = presentationController as? UISheetPresentationController { if presentationController.selectedDetentIdentifier == nil && presentationController.detents.contains(.medium()) { return false @@ -178,10 +177,8 @@ extension AutofillLoginPromptViewController: AutofillLoginPromptViewModelDelegat } func autofillLoginPromptViewModelDidRequestExpansion(_ viewModel: AutofillLoginPromptViewModel) { - if #available(iOS 15.0, *) { - dismiss(animated: true) { - self.completion?(nil, true) - } + dismiss(animated: true) { + self.completion?(nil, true) } } diff --git a/DuckDuckGo/AutofillLoginSettingsListViewController.swift b/DuckDuckGo/AutofillLoginSettingsListViewController.swift index fba8246fca..921330d649 100644 --- a/DuckDuckGo/AutofillLoginSettingsListViewController.swift +++ b/DuckDuckGo/AutofillLoginSettingsListViewController.swift @@ -466,15 +466,13 @@ final class AutofillLoginSettingsListViewController: UIViewController { } ) - if #available(iOS 15.0, *) { - if let presentationController = authConfirmationPromptViewController.presentationController as? UISheetPresentationController { - if #available(iOS 16.0, *) { - presentationController.detents = [.custom(resolver: { _ in - AutofillViews.deleteAllPromptMinHeight - })] - } else { - presentationController.detents = [.medium()] - } + if let presentationController = authConfirmationPromptViewController.presentationController as? UISheetPresentationController { + if #available(iOS 16.0, *) { + presentationController.detents = [.custom(resolver: { _ in + AutofillViews.deleteAllPromptMinHeight + })] + } else { + presentationController.detents = [.medium()] } } @@ -961,14 +959,12 @@ extension AutofillLoginSettingsListViewController { navigationController?.navigationBar.barTintColor = theme.barBackgroundColor navigationController?.navigationBar.tintColor = theme.navigationBarTintColor - if #available(iOS 15.0, *) { - let appearance = UINavigationBarAppearance() - appearance.shadowColor = .clear - appearance.backgroundColor = theme.backgroundColor + let appearance = UINavigationBarAppearance() + appearance.shadowColor = .clear + appearance.backgroundColor = theme.backgroundColor - navigationController?.navigationBar.standardAppearance = appearance - navigationController?.navigationBar.scrollEdgeAppearance = appearance - } + navigationController?.navigationBar.standardAppearance = appearance + navigationController?.navigationBar.scrollEdgeAppearance = appearance tableView.reloadData() } diff --git a/DuckDuckGo/CompleteDownloadRow.swift b/DuckDuckGo/CompleteDownloadRow.swift index dbd7f3e9a4..4cb5f1694f 100644 --- a/DuckDuckGo/CompleteDownloadRow.swift +++ b/DuckDuckGo/CompleteDownloadRow.swift @@ -71,7 +71,6 @@ struct CompleteDownloadRow: View { } .accessibilityLabel(UserText.actionShare) .buttonStyle(.plain) - .animation(nil) .background( GeometryReader { geometryProxy in Color.clear diff --git a/DuckDuckGo/DownloadsList.swift b/DuckDuckGo/DownloadsList.swift index afebd5f884..d2bd6fb844 100644 --- a/DuckDuckGo/DownloadsList.swift +++ b/DuckDuckGo/DownloadsList.swift @@ -40,17 +40,7 @@ struct DownloadsList: View { private var doneButton: some View { Button(action: { - if #available(iOS 15.0, *) { - presentationMode.wrappedValue.dismiss() - } else { - // Because: presentationMode.wrappedValue.dismiss() for view wrapped in NavigationView() does not work in iOS 14 and lower - if var topController = UIApplication.shared.windows.first!.rootViewController { - while let presentedViewController = topController.presentedViewController { - topController = presentedViewController - } - topController.dismiss(animated: true) - } - } + presentationMode.wrappedValue.dismiss() }, label: { Text(UserText.navigationTitleDone).foregroundColor(.barButton).bold() }) .opacity(editMode == .inactive ? 1.0 : 0.0) @@ -81,15 +71,9 @@ struct DownloadsList: View { @ViewBuilder private var listWithBottomToolbar: some View { - if #available(iOS 15.0, *) { - listWithBackground.toolbar { - ToolbarItemGroup(placement: .bottomBar) { - toolbarButtons - } - } - } else { - listWithBackground.toolbar { - toolbarContent + listWithBackground.toolbar { + ToolbarItemGroup(placement: .bottomBar) { + toolbarButtons } } } diff --git a/DuckDuckGo/DownloadsListHostingController.swift b/DuckDuckGo/DownloadsListHostingController.swift index 84738042a6..ac700bb75b 100644 --- a/DuckDuckGo/DownloadsListHostingController.swift +++ b/DuckDuckGo/DownloadsListHostingController.swift @@ -51,7 +51,7 @@ class DownloadsListHostingController: UIHostingController { let activityViewController = UIActivityViewController(activityItems: [url], applicationActivities: nil) if UIDevice.current.userInterfaceIdiom == .pad { - activityViewController.popoverPresentationController?.sourceView = UIApplication.shared.windows.first + activityViewController.popoverPresentationController?.sourceView = UIApplication.shared.firstKeyWindow activityViewController.popoverPresentationController?.permittedArrowDirections = .right activityViewController.popoverPresentationController?.sourceRect = rect } diff --git a/DuckDuckGo/DuckPlayer/DuckPlayerNavigationHandler.swift b/DuckDuckGo/DuckPlayer/DuckPlayerNavigationHandler.swift index 7f50c6ad11..09f059eea9 100644 --- a/DuckDuckGo/DuckPlayer/DuckPlayerNavigationHandler.swift +++ b/DuckDuckGo/DuckPlayer/DuckPlayerNavigationHandler.swift @@ -83,10 +83,7 @@ final class DuckPlayerNavigationHandler { } private func performNavigation(_ request: URLRequest, responseHTML: String, webView: WKWebView) { - // iOS 14 will be soon dropped out (and it does not support simulatedRequests) - if #available(iOS 15.0, *) { - webView.loadSimulatedRequest(request, responseHTML: responseHTML) - } + webView.loadSimulatedRequest(request, responseHTML: responseHTML) } private func performRequest(request: URLRequest, webView: WKWebView) { @@ -181,14 +178,13 @@ extension DuckPlayerNavigationHandler: DuckNavigationHandling { duckPlayer.settings.mode == .enabled || duckPlayer.settings.mode == .alwaysAsk, !url.hasWatchInYoutubeQueryParameter { let newRequest = Self.makeDuckPlayerRequest(from: URLRequest(url: url)) - if #available(iOS 15.0, *) { - os_log("DP: Loading Simulated Request for %s", log: .duckPlayerLog, type: .debug, navigationAction.request.url?.absoluteString ?? "") - - DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { - self.performRequest(request: newRequest, webView: webView) - } - return + + os_log("DP: Loading Simulated Request for %s", log: .duckPlayerLog, type: .debug, navigationAction.request.url?.absoluteString ?? "") + + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { + self.performRequest(request: newRequest, webView: webView) } + return } } diff --git a/DuckDuckGo/DuckPlayer/Modal/DuckPlayerModalPresenter.swift b/DuckDuckGo/DuckPlayer/Modal/DuckPlayerModalPresenter.swift index 503e6af4e5..f5ecb51636 100644 --- a/DuckDuckGo/DuckPlayer/Modal/DuckPlayerModalPresenter.swift +++ b/DuckDuckGo/DuckPlayer/Modal/DuckPlayerModalPresenter.swift @@ -42,16 +42,14 @@ struct DuckPlayerModalPresenter { } private func configurePresentationStyle(for hostingController: UIHostingController, on viewController: UIViewController) { - if #available(iOS 15.0, *) { - if let sheet = hostingController.presentationController as? UISheetPresentationController { + if let sheet = hostingController.presentationController as? UISheetPresentationController { - if #available(iOS 16.0, *) { - let targetSize = getTargetSizeForPresentationView(on: viewController) - sheet.detents = [.custom { _ in targetSize.height }] - } else { - sheet.detents = [.large()] + if #available(iOS 16.0, *) { + let targetSize = getTargetSizeForPresentationView(on: viewController) + sheet.detents = [.custom { _ in targetSize.height }] + } else { + sheet.detents = [.large()] - } } } } diff --git a/DuckDuckGo/Favicons.swift b/DuckDuckGo/Favicons.swift index e38acc128c..567a617e5b 100644 --- a/DuckDuckGo/Favicons.swift +++ b/DuckDuckGo/Favicons.swift @@ -395,12 +395,8 @@ public class Favicons { } } - if #available(iOS 15.0, *) { - let request = URLRequest.userInitiated(url) - metadataFetcher.startFetchingMetadata(for: request, completionHandler: completion) - } else { - metadataFetcher.startFetchingMetadata(for: url, completionHandler: completion) - } + let request = URLRequest.userInitiated(url) + metadataFetcher.startFetchingMetadata(for: request, completionHandler: completion) } private func retrieveBestImage(from urls: [URL], completion: @escaping (UIImage?) -> Void) { diff --git a/DuckDuckGo/Feedback/VPNFeedbackFormView.swift b/DuckDuckGo/Feedback/VPNFeedbackFormView.swift index b74eca8b17..e2dd5ea5e3 100644 --- a/DuckDuckGo/Feedback/VPNFeedbackFormView.swift +++ b/DuckDuckGo/Feedback/VPNFeedbackFormView.swift @@ -22,7 +22,6 @@ import SwiftUI import NetworkProtection -@available(iOS 15.0, *) struct VPNFeedbackFormCategoryView: View { @Environment(\.dismiss) private var dismiss let collector = DefaultVPNMetadataCollector(statusObserver: AppDependencyProvider.shared.connectionObserver) @@ -78,7 +77,6 @@ struct VPNFeedbackFormCategoryView: View { } } -@available(iOS 15.0, *) struct VPNFeedbackFormView: View { @StateObject var viewModel: VPNFeedbackFormViewModel @Environment(\.dismiss) private var dismiss diff --git a/DuckDuckGo/FireButtonAnimator.swift b/DuckDuckGo/FireButtonAnimator.swift index b5aca8dc41..84b9f82a39 100644 --- a/DuckDuckGo/FireButtonAnimator.swift +++ b/DuckDuckGo/FireButtonAnimator.swift @@ -112,7 +112,7 @@ class FireButtonAnimator { func animate(onAnimationStart: @escaping () async -> Void, onTransitionCompleted: @escaping () async -> Void, completion: @escaping () async -> Void) { - guard let window = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first, + guard let window = UIApplication.shared.firstKeyWindow, let snapshot = window.snapshotView(afterScreenUpdates: false) else { Task { @MainActor in await onAnimationStart() diff --git a/DuckDuckGo/HomeMessageView.swift b/DuckDuckGo/HomeMessageView.swift index 871b79ec55..a4067808fa 100644 --- a/DuckDuckGo/HomeMessageView.swift +++ b/DuckDuckGo/HomeMessageView.swift @@ -131,7 +131,7 @@ struct HomeMessageView: View { @ViewBuilder private var subtitle: some View { - if #available(iOS 15, *), let attributed = try? AttributedString(markdown: viewModel.subtitle) { + if let attributed = try? AttributedString(markdown: viewModel.subtitle) { Text(attributed) .daxBodyRegular() } else { diff --git a/DuckDuckGo/ImportPasswordsView.swift b/DuckDuckGo/ImportPasswordsView.swift index fcb69b232a..c4964edb57 100644 --- a/DuckDuckGo/ImportPasswordsView.swift +++ b/DuckDuckGo/ImportPasswordsView.swift @@ -110,7 +110,7 @@ struct ImportPasswordsView: View { ForEach(ImportPasswordsViewModel.InstructionStep.allCases, id: \.self) { step in - if #available(iOS 15.0, *), step == .step2 || step == .step3 { + if step == .step2 || step == .step3 { Instruction(step: step.rawValue, instructionText: attributedText(viewModel.attributedInstructionsForStep(step))) } else { Instruction(step: step.rawValue, instructionText: Text(viewModel.instructionsForStep(step))) @@ -120,7 +120,6 @@ struct ImportPasswordsView: View { } - @available(iOS 15.0, *) func attributedText(_ string: AttributedString) -> Text { return Text(string) } diff --git a/DuckDuckGo/ImportPasswordsViewModel.swift b/DuckDuckGo/ImportPasswordsViewModel.swift index e70f5baab1..480eb27ef4 100644 --- a/DuckDuckGo/ImportPasswordsViewModel.swift +++ b/DuckDuckGo/ImportPasswordsViewModel.swift @@ -102,7 +102,6 @@ final class ImportPasswordsViewModel { return step.instructions() } - @available(iOS 15.0, *) func attributedInstructionsForStep(_ step: InstructionStep) -> AttributedString { let semiboldFont = Font.system(.body).weight(.semibold) var attributedString = AttributedString(step.instructions()) @@ -141,7 +140,6 @@ private extension String { } -@available(iOS 15, *) private extension AttributedString { mutating func applyFontStyle(forSubstring substring: String, withFont font: Font) { diff --git a/DuckDuckGo/InlineWKDownloadDelegate.swift b/DuckDuckGo/InlineWKDownloadDelegate.swift index b0e803133a..2eb4f5f880 100644 --- a/DuckDuckGo/InlineWKDownloadDelegate.swift +++ b/DuckDuckGo/InlineWKDownloadDelegate.swift @@ -20,7 +20,6 @@ import Foundation import WebKit -@available(iOS 14.5, *) final class InlineWKDownloadDelegate: NSObject, WKDownloadDelegate { var decideDestinationCallback: ((WKDownload, URLResponse, String, @escaping (URL?) -> Void) -> Void)? diff --git a/DuckDuckGo/MainViewController+Email.swift b/DuckDuckGo/MainViewController+Email.swift index 4209cf50dc..8b4bb3421b 100644 --- a/DuckDuckGo/MainViewController+Email.swift +++ b/DuckDuckGo/MainViewController+Email.swift @@ -85,15 +85,13 @@ extension MainViewController: EmailManagerAliasPermissionDelegate { didRequestPermissionToProvideAliasWithCompletion(addressType, autosave) } - if #available(iOS 15.0, *) { - if let presentationController = emailAddressPromptViewController.presentationController as? UISheetPresentationController { - if #available(iOS 16.0, *) { - presentationController.detents = [.custom(resolver: { _ in - AutofillViews.emailSignupPromptMinHeight - })] - } else { - presentationController.detents = [.medium()] - } + if let presentationController = emailAddressPromptViewController.presentationController as? UISheetPresentationController { + if #available(iOS 16.0, *) { + presentationController.detents = [.custom(resolver: { _ in + AutofillViews.emailSignupPromptMinHeight + })] + } else { + presentationController.detents = [.medium()] } } self.present(emailAddressPromptViewController, animated: true) @@ -115,15 +113,13 @@ extension MainViewController: EmailManagerAliasPermissionDelegate { } } - if #available(iOS 15.0, *) { - if let presentationController = emailSignupPromptViewController.presentationController as? UISheetPresentationController { - if #available(iOS 16.0, *) { - presentationController.detents = [.custom(resolver: { _ in - AutofillViews.emailSignupPromptMinHeight - })] - } else { - presentationController.detents = [.medium()] - } + if let presentationController = emailSignupPromptViewController.presentationController as? UISheetPresentationController { + if #available(iOS 16.0, *) { + presentationController.detents = [.custom(resolver: { _ in + AutofillViews.emailSignupPromptMinHeight + })] + } else { + presentationController.detents = [.medium()] } } diff --git a/DuckDuckGo/MainViewController+KeyCommands.swift b/DuckDuckGo/MainViewController+KeyCommands.swift index 695be22846..45f499a9b6 100644 --- a/DuckDuckGo/MainViewController+KeyCommands.swift +++ b/DuckDuckGo/MainViewController+KeyCommands.swift @@ -111,10 +111,8 @@ extension MainViewController { ] let commands = [alwaysAvailable, browsingCommands, findInPageCommands, arrowKeys, other].flatMap { $0 } - if #available(iOS 15, *) { - commands.forEach { - $0.wantsPriorityOverSystemBehavior = true - } + commands.forEach { + $0.wantsPriorityOverSystemBehavior = true } return commands } diff --git a/DuckDuckGo/MainViewController.swift b/DuckDuckGo/MainViewController.swift index fe17899cfb..22154cccc5 100644 --- a/DuckDuckGo/MainViewController.swift +++ b/DuckDuckGo/MainViewController.swift @@ -151,7 +151,7 @@ class MainViewController: UIViewController { } var searchBarRect: CGRect { - let view = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first?.rootViewController?.view + let view = UIApplication.shared.firstKeyWindow?.rootViewController?.view return viewCoordinator.omniBar.searchContainer.convert(viewCoordinator.omniBar.searchContainer.bounds, to: view) } @@ -2674,17 +2674,10 @@ extension MainViewController { private func historyMenuButton(with menuHistoryItemList: [BackForwardMenuHistoryItem]) -> [UIAction] { let menuItems: [UIAction] = menuHistoryItemList.compactMap { historyItem in - if #available(iOS 15.0, *) { - return UIAction(title: historyItem.title, - subtitle: historyItem.sanitizedURLForDisplay, - discoverabilityTitle: historyItem.sanitizedURLForDisplay) { [weak self] _ in - self?.loadBackForwardItem(historyItem.backForwardItem) - } - } else { - return UIAction(title: historyItem.title, - discoverabilityTitle: historyItem.sanitizedURLForDisplay) { [weak self] _ in - self?.loadBackForwardItem(historyItem.backForwardItem) - } + return UIAction(title: historyItem.title, + subtitle: historyItem.sanitizedURLForDisplay, + discoverabilityTitle: historyItem.sanitizedURLForDisplay) { [weak self] _ in + self?.loadBackForwardItem(historyItem.backForwardItem) } } diff --git a/DuckDuckGo/NetworkProtectionDNSSettingsView.swift b/DuckDuckGo/NetworkProtectionDNSSettingsView.swift index 415226eeba..dae30832d9 100644 --- a/DuckDuckGo/NetworkProtectionDNSSettingsView.swift +++ b/DuckDuckGo/NetworkProtectionDNSSettingsView.swift @@ -22,7 +22,6 @@ import SwiftUI import NetworkProtection -@available(iOS 15.0, *) struct NetworkProtectionDNSSettingsView: View { @StateObject var viewModel = NetworkProtectionDNSSettingsViewModel(settings: VPNSettings(defaults: .networkProtectionGroupDefaults)) @Environment(\.dismiss) private var dismiss @@ -110,7 +109,6 @@ struct NetworkProtectionDNSSettingsView: View { } } -@available(iOS 15, *) private struct ChecklistItem: View where Content: View { let isSelected: Bool let action: () -> Void diff --git a/DuckDuckGo/NetworkProtectionDebugViewController.swift b/DuckDuckGo/NetworkProtectionDebugViewController.swift index b625dea250..8ad874f3c0 100644 --- a/DuckDuckGo/NetworkProtectionDebugViewController.swift +++ b/DuckDuckGo/NetworkProtectionDebugViewController.swift @@ -425,7 +425,7 @@ final class NetworkProtectionDebugViewController: UITableViewController { Supports IPv6: \(path.supportsIPv6) """ - if #available(iOS 14.2, *), path.status == .unsatisfied { + if path.status == .unsatisfied { pathDescription.append("\nUnsatisfied Reason: \(path.unsatisfiedReason)") } diff --git a/DuckDuckGo/NetworkProtectionRootView.swift b/DuckDuckGo/NetworkProtectionRootView.swift index 1d23f301a9..e3be48390f 100644 --- a/DuckDuckGo/NetworkProtectionRootView.swift +++ b/DuckDuckGo/NetworkProtectionRootView.swift @@ -23,7 +23,6 @@ import SwiftUI import NetworkProtection import Subscription -@available(iOS 15, *) struct NetworkProtectionRootView: View { let statusViewModel: NetworkProtectionStatusViewModel diff --git a/DuckDuckGo/NetworkProtectionRootViewController.swift b/DuckDuckGo/NetworkProtectionRootViewController.swift index 013f6132bc..3dd569fccc 100644 --- a/DuckDuckGo/NetworkProtectionRootViewController.swift +++ b/DuckDuckGo/NetworkProtectionRootViewController.swift @@ -21,7 +21,6 @@ import SwiftUI -@available(iOS 15, *) final class NetworkProtectionRootViewController: UIHostingController { init() { @@ -40,7 +39,6 @@ final class NetworkProtectionRootViewController: UIHostingController Void @@ -145,7 +143,6 @@ private struct CountryItem: View { } } -@available(iOS 15, *) private struct ChecklistItem: View where Content: View { let isSelected: Bool let action: () -> Void @@ -170,7 +167,6 @@ private struct ChecklistItem: View where Content: View { } } -@available(iOS 15, *) private struct MenuItem: View { let isSelected: Bool let title: String diff --git a/DuckDuckGo/NetworkProtectionVPNSettingsView.swift b/DuckDuckGo/NetworkProtectionVPNSettingsView.swift index 06a265e736..dad117cf16 100644 --- a/DuckDuckGo/NetworkProtectionVPNSettingsView.swift +++ b/DuckDuckGo/NetworkProtectionVPNSettingsView.swift @@ -22,7 +22,6 @@ import SwiftUI import DesignResourcesKit -@available(iOS 15, *) struct NetworkProtectionVPNSettingsView: View { @StateObject var viewModel = NetworkProtectionVPNSettingsViewModel() diff --git a/DuckDuckGo/OngoingDownloadRow.swift b/DuckDuckGo/OngoingDownloadRow.swift index 435a5fab4f..a0ace4aa57 100644 --- a/DuckDuckGo/OngoingDownloadRow.swift +++ b/DuckDuckGo/OngoingDownloadRow.swift @@ -83,7 +83,7 @@ struct ProgressCircle: View { .stroke(style: StrokeStyle(lineWidth: Const.Size.progressStrokeWidth, lineCap: .butt, lineJoin: .miter)) .foregroundColor(.progressFill) .rotationEffect(Angle(degrees: 270.0)) - .animation(.linear) + .animation(.linear, value: self.progress) } } } diff --git a/DuckDuckGo/PasswordGenerationPromptView.swift b/DuckDuckGo/PasswordGenerationPromptView.swift index 8c01fdabf6..6743d47f12 100644 --- a/DuckDuckGo/PasswordGenerationPromptView.swift +++ b/DuckDuckGo/PasswordGenerationPromptView.swift @@ -169,11 +169,7 @@ private extension View { @ViewBuilder func textSelectionEnabled() -> some View { - if #available(iOS 15.0, *) { - self.textSelection(.enabled) - } else { - self - } + self.textSelection(.enabled) } } diff --git a/DuckDuckGo/PreserveLoginsWorker.swift b/DuckDuckGo/PreserveLoginsWorker.swift index 998ca9147f..54e98f8f58 100644 --- a/DuckDuckGo/PreserveLoginsWorker.swift +++ b/DuckDuckGo/PreserveLoginsWorker.swift @@ -35,7 +35,7 @@ struct PreserveLoginsWorker { if isAutofillEnabled && autofillShouldBlockPrompt(saveLoginPromptLastDismissed, saveLoginPromptIsPresenting: saveLoginPromptIsPresenting) { return false } - if let window = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first, window.subviews.contains(where: { $0 is ActionMessageView }) { + if let window = UIApplication.shared.firstKeyWindow, window.subviews.contains(where: { $0 is ActionMessageView }) { // if an ActionMessageView is currently displayed wait before prompting to fireproof DispatchQueue.main.asyncAfter(deadline: .now() + 3.0) { self.promptToFireproof(domain) diff --git a/DuckDuckGo/SettingsLegacyViewProvider.swift b/DuckDuckGo/SettingsLegacyViewProvider.swift index 8fefd7ea99..9ebab1a8f3 100644 --- a/DuckDuckGo/SettingsLegacyViewProvider.swift +++ b/DuckDuckGo/SettingsLegacyViewProvider.swift @@ -81,8 +81,6 @@ class SettingsLegacyViewProvider: ObservableObject { var autoclearData: UIViewController { instantiate("AutoClearSettingsViewController", fromStoryboard: "Settings") } var keyboard: UIViewController { instantiate("Keyboard", fromStoryboard: "Settings") } var feedback: UIViewController { instantiate("Feedback", fromStoryboard: "Feedback") } - - @available(iOS 15, *) var netP: UIViewController { NetworkProtectionRootViewController() } @MainActor diff --git a/DuckDuckGo/SettingsRootView.swift b/DuckDuckGo/SettingsRootView.swift index 4893193bac..765d1a66f3 100644 --- a/DuckDuckGo/SettingsRootView.swift +++ b/DuckDuckGo/SettingsRootView.swift @@ -34,21 +34,16 @@ struct SettingsRootView: View { var body: some View { // Hidden navigationLink for programatic navigation - if #available(iOS 15.0, *) { - - if let target = deepLinkTarget { - NavigationLink(destination: deepLinkDestinationView(for: target), - isActive: $shouldDisplayDeepLinkPush) { - EmptyView() - } + if let target = deepLinkTarget { + NavigationLink(destination: deepLinkDestinationView(for: target), + isActive: $shouldDisplayDeepLinkPush) { + EmptyView() } } List { SettingsPrivacyProtectionsView() - if #available(iOS 15, *) { - SettingsSubscriptionView().environmentObject(subscriptionNavigationCoordinator) - } + SettingsSubscriptionView().environmentObject(subscriptionNavigationCoordinator) SettingsMainSettingsView() SettingsNextStepsView() SettingsOthersView() @@ -67,18 +62,14 @@ struct SettingsRootView: View { // MARK: Deeplink Modifiers - .sheet(isPresented: $shouldDisplayDeepLinkSheet, - onDismiss: { - viewModel.onAppear() - shouldDisplayDeepLinkSheet = false - }, - content: { - if #available(iOS 15.0, *) { - if let target = deepLinkTarget { - deepLinkDestinationView(for: target) - } - } - }) + .sheet(isPresented: $shouldDisplayDeepLinkSheet, onDismiss: { + viewModel.onAppear() + shouldDisplayDeepLinkSheet = false + }, content: { + if let target = deepLinkTarget { + deepLinkDestinationView(for: target) + } + }) .onReceive(viewModel.$deepLinkTarget.removeDuplicates(), perform: { link in guard let link else { @@ -112,7 +103,6 @@ struct SettingsRootView: View { } // MARK: DeepLink Views - @available(iOS 15.0, *) @ViewBuilder func deepLinkDestinationView(for target: SettingsViewModel.SettingsDeepLinkSection) -> some View { switch target { @@ -148,11 +138,7 @@ struct SettingsRootView: View { struct InsetGroupedListStyleModifier: ViewModifier { func body(content: Content) -> some View { - if #available(iOS 15, *) { - return AnyView(content.applyInsetGroupedListStyle()) - } else { - return AnyView(content) - } + return AnyView(content.applyInsetGroupedListStyle()) } } diff --git a/DuckDuckGo/SettingsSubscriptionView.swift b/DuckDuckGo/SettingsSubscriptionView.swift index afe2fd7085..d5b871d8f0 100644 --- a/DuckDuckGo/SettingsSubscriptionView.swift +++ b/DuckDuckGo/SettingsSubscriptionView.swift @@ -22,7 +22,6 @@ import Subscription import SwiftUI import UIKit -@available(iOS 15.0, *) struct SettingsSubscriptionView: View { @EnvironmentObject var viewModel: SettingsViewModel diff --git a/DuckDuckGo/SettingsViewModel.swift b/DuckDuckGo/SettingsViewModel.swift index 6b4edda900..9ecdbebc4d 100644 --- a/DuckDuckGo/SettingsViewModel.swift +++ b/DuckDuckGo/SettingsViewModel.swift @@ -600,10 +600,8 @@ extension SettingsViewModel { #if NETWORK_PROTECTION case .netP: - if #available(iOS 15, *) { - firePixel(.privacyProVPNSettings) - pushViewController(legacyViewProvider.netP) - } + firePixel(.privacyProVPNSettings) + pushViewController(legacyViewProvider.netP) #endif } } @@ -753,12 +751,10 @@ extension SettingsViewModel { subscriptionSignOutObserver = NotificationCenter.default.addObserver(forName: .accountDidSignOut, object: nil, queue: .main) { [weak self] _ in - if #available(iOS 15.0, *) { - guard let strongSelf = self else { return } - Task { - strongSelf.subscriptionStateCache.reset() - await strongSelf.setupSubscriptionEnvironment() - } + guard let strongSelf = self else { return } + Task { + strongSelf.subscriptionStateCache.reset() + await strongSelf.setupSubscriptionEnvironment() } } @@ -772,7 +768,6 @@ extension SettingsViewModel { } - @available(iOS 15.0, *) func restoreAccountPurchase() async { DispatchQueue.main.async { self.state.subscription.isRestoring = true } let appStoreRestoreFlow = DefaultAppStoreRestoreFlow(accountManager: subscriptionManager.accountManager, diff --git a/DuckDuckGo/SpeechRecognizer.swift b/DuckDuckGo/SpeechRecognizer.swift index 0e52738319..67e58d9377 100644 --- a/DuckDuckGo/SpeechRecognizer.swift +++ b/DuckDuckGo/SpeechRecognizer.swift @@ -57,12 +57,7 @@ final class SpeechRecognizer: NSObject, SpeechRecognizerProtocol { operationQueue.addOperation { [weak self] in guard let self = self else { return } - // https://app.asana.com/0/1201011656765697/1201271104639596 - if #available(iOS 15.0, *) { - self.isAvailable = self.supportsOnDeviceRecognition && (self.speechRecognizer?.isAvailable ?? false) - } else { - self.isAvailable = false - } + self.isAvailable = self.supportsOnDeviceRecognition && (self.speechRecognizer?.isAvailable ?? false) } } @@ -103,8 +98,6 @@ final class SpeechRecognizer: NSObject, SpeechRecognizerProtocol { return normalized } - // https://app.asana.com/0/1201011656765697/1201271104639596 - @available(iOS 15, *) func startRecording(resultHandler: @escaping (_ text: String?, _ error: Error?, _ speechDidFinish: Bool) -> Void, diff --git a/DuckDuckGo/SpeechRecognizerProtocol.swift b/DuckDuckGo/SpeechRecognizerProtocol.swift index 7506c1fad3..369d3ccede 100644 --- a/DuckDuckGo/SpeechRecognizerProtocol.swift +++ b/DuckDuckGo/SpeechRecognizerProtocol.swift @@ -25,7 +25,6 @@ protocol SpeechRecognizerProtocol { func getVolumeLevel(from channelData: UnsafeMutablePointer) -> Float func stopRecording() - @available(iOS 15, *) func startRecording(resultHandler: @escaping (_ text: String?, _ error: Error?, _ speechDidFinish: Bool) -> Void, diff --git a/DuckDuckGo/Subscription/AsyncHeadlessWebview/HeadlessWebView.swift b/DuckDuckGo/Subscription/AsyncHeadlessWebview/HeadlessWebView.swift index 3452302d90..5af147b4a5 100644 --- a/DuckDuckGo/Subscription/AsyncHeadlessWebview/HeadlessWebView.swift +++ b/DuckDuckGo/Subscription/AsyncHeadlessWebview/HeadlessWebView.swift @@ -118,7 +118,7 @@ struct HeadlessWebView: UIViewRepresentable { } extension UIViewController { - static func getCurrentViewController(base: UIViewController? = UIApplication.shared.windows.first { $0.isKeyWindow }?.rootViewController) -> UIViewController? { + static func getCurrentViewController(base: UIViewController? = UIApplication.shared.firstKeyWindow?.rootViewController) -> UIViewController? { if let nav = base as? UINavigationController { return getCurrentViewController(base: nav.visibleViewController) } else if let tab = base as? UITabBarController, let selected = tab.selectedViewController { diff --git a/DuckDuckGo/Subscription/SubscriptionManageriOS14.swift b/DuckDuckGo/Subscription/SubscriptionManageriOS14.swift deleted file mode 100644 index 6172f1bb66..0000000000 --- a/DuckDuckGo/Subscription/SubscriptionManageriOS14.swift +++ /dev/null @@ -1,51 +0,0 @@ -// -// SubscriptionManageriOS14.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 -import Subscription - -class SubscriptionManageriOS14: SubscriptionManager { - var accountManager: AccountManager - var subscriptionEndpointService: SubscriptionEndpointService = DefaultSubscriptionEndpointService(currentServiceEnvironment: .production) - var authEndpointService: AuthEndpointService = DefaultAuthEndpointService(currentServiceEnvironment: .production) - - @available(iOS 15, *) - func storePurchaseManager() -> StorePurchaseManager { - DefaultStorePurchaseManager() - } - - static func loadEnvironmentFrom(userDefaults: UserDefaults) -> SubscriptionEnvironment? { - return nil - } - - static func save(subscriptionEnvironment: SubscriptionEnvironment, userDefaults: UserDefaults) {} - - var currentEnvironment: SubscriptionEnvironment = SubscriptionEnvironment.default - var canPurchase: Bool = false - func loadInitialData() {} - func refreshCachedSubscriptionAndEntitlements(completion: @escaping (Bool) -> Void) {} - - func url(for type: SubscriptionURL) -> URL { - URL(string: "https://duckduckgo.com")! - } - - init(accountManager: AccountManager) { - self.accountManager = accountManager - } -} diff --git a/DuckDuckGo/Subscription/UserScripts/IdentityTheftRestorationPagesFeature.swift b/DuckDuckGo/Subscription/UserScripts/IdentityTheftRestorationPagesFeature.swift index 218494a94f..aef3903dbb 100644 --- a/DuckDuckGo/Subscription/UserScripts/IdentityTheftRestorationPagesFeature.swift +++ b/DuckDuckGo/Subscription/UserScripts/IdentityTheftRestorationPagesFeature.swift @@ -25,7 +25,6 @@ import UserScript import Combine import Subscription -@available(iOS 15.0, *) final class IdentityTheftRestorationPagesFeature: Subfeature, ObservableObject { struct Constants { diff --git a/DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift b/DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift index c266490059..779f7193da 100644 --- a/DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift +++ b/DuckDuckGo/Subscription/UserScripts/SubscriptionPagesUseSubscriptionFeature.swift @@ -30,7 +30,6 @@ enum SubscriptionTransactionStatus { case idle, purchasing, restoring, polling } -@available(iOS 15.0, *) final class SubscriptionPagesUseSubscriptionFeature: Subfeature, ObservableObject { struct Constants { diff --git a/DuckDuckGo/Subscription/ViewModel/SubscriptionContainerViewModel.swift b/DuckDuckGo/Subscription/ViewModel/SubscriptionContainerViewModel.swift index 17274f5c48..4d18327bd2 100644 --- a/DuckDuckGo/Subscription/ViewModel/SubscriptionContainerViewModel.swift +++ b/DuckDuckGo/Subscription/ViewModel/SubscriptionContainerViewModel.swift @@ -21,7 +21,6 @@ import Foundation import Subscription import Combine -@available(iOS 15.0, *) final class SubscriptionContainerViewModel: ObservableObject { let userScript: SubscriptionPagesUserScript diff --git a/DuckDuckGo/Subscription/ViewModel/SubscriptionEmailViewModel.swift b/DuckDuckGo/Subscription/ViewModel/SubscriptionEmailViewModel.swift index b185c9d512..aba3be0689 100644 --- a/DuckDuckGo/Subscription/ViewModel/SubscriptionEmailViewModel.swift +++ b/DuckDuckGo/Subscription/ViewModel/SubscriptionEmailViewModel.swift @@ -23,7 +23,6 @@ import Combine import Core import Subscription -@available(iOS 15.0, *) final class SubscriptionEmailViewModel: ObservableObject { private let subscriptionManager: SubscriptionManager diff --git a/DuckDuckGo/Subscription/ViewModel/SubscriptionFlowViewModel.swift b/DuckDuckGo/Subscription/ViewModel/SubscriptionFlowViewModel.swift index 95d0a9f5c3..af64bda56c 100644 --- a/DuckDuckGo/Subscription/ViewModel/SubscriptionFlowViewModel.swift +++ b/DuckDuckGo/Subscription/ViewModel/SubscriptionFlowViewModel.swift @@ -23,7 +23,6 @@ import Combine import Core import Subscription -@available(iOS 15.0, *) final class SubscriptionFlowViewModel: ObservableObject { let userScript: SubscriptionPagesUserScript diff --git a/DuckDuckGo/Subscription/ViewModel/SubscriptionITPViewModel.swift b/DuckDuckGo/Subscription/ViewModel/SubscriptionITPViewModel.swift index 6be2122be0..3e9692f30b 100644 --- a/DuckDuckGo/Subscription/ViewModel/SubscriptionITPViewModel.swift +++ b/DuckDuckGo/Subscription/ViewModel/SubscriptionITPViewModel.swift @@ -23,7 +23,6 @@ import Combine import Core import Subscription -@available(iOS 15.0, *) final class SubscriptionITPViewModel: ObservableObject { var userScript: IdentityTheftRestorationPagesUserScript? diff --git a/DuckDuckGo/Subscription/ViewModel/SubscriptionPIRViewModel.swift b/DuckDuckGo/Subscription/ViewModel/SubscriptionPIRViewModel.swift index 4f6cddffa4..49afa010be 100644 --- a/DuckDuckGo/Subscription/ViewModel/SubscriptionPIRViewModel.swift +++ b/DuckDuckGo/Subscription/ViewModel/SubscriptionPIRViewModel.swift @@ -20,7 +20,6 @@ import Foundation import Core -@available(iOS 15.0, *) final class SubscriptionPIRViewModel: ObservableObject { var viewTitle = UserText.settingsPProDBPTitle diff --git a/DuckDuckGo/Subscription/ViewModel/SubscriptionRestoreViewModel.swift b/DuckDuckGo/Subscription/ViewModel/SubscriptionRestoreViewModel.swift index 0c178c8257..2940149fe3 100644 --- a/DuckDuckGo/Subscription/ViewModel/SubscriptionRestoreViewModel.swift +++ b/DuckDuckGo/Subscription/ViewModel/SubscriptionRestoreViewModel.swift @@ -23,7 +23,6 @@ import Combine import Core import Subscription -@available(iOS 15.0, *) final class SubscriptionRestoreViewModel: ObservableObject { let userScript: SubscriptionPagesUserScript diff --git a/DuckDuckGo/Subscription/ViewModel/SubscriptionSettingsViewModel.swift b/DuckDuckGo/Subscription/ViewModel/SubscriptionSettingsViewModel.swift index 61afacec98..8019e9cd29 100644 --- a/DuckDuckGo/Subscription/ViewModel/SubscriptionSettingsViewModel.swift +++ b/DuckDuckGo/Subscription/ViewModel/SubscriptionSettingsViewModel.swift @@ -23,7 +23,6 @@ import StoreKit import Subscription import Core -@available(iOS 15.0, *) final class SubscriptionSettingsViewModel: ObservableObject { private let subscriptionManager: SubscriptionManager diff --git a/DuckDuckGo/Subscription/Views/SubscriptionContainerView.swift b/DuckDuckGo/Subscription/Views/SubscriptionContainerView.swift index 61b38b3292..1723e38a89 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionContainerView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionContainerView.swift @@ -20,7 +20,6 @@ import Foundation import SwiftUI -@available(iOS 15.0, *) struct SubscriptionContainerView: View { enum CurrentView { diff --git a/DuckDuckGo/Subscription/Views/SubscriptionContainerViewFactory.swift b/DuckDuckGo/Subscription/Views/SubscriptionContainerViewFactory.swift index 05d06609f9..3ee28dfa22 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionContainerViewFactory.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionContainerViewFactory.swift @@ -20,7 +20,6 @@ import SwiftUI import Subscription -@available(iOS 15.0, *) enum SubscriptionContainerViewFactory { static func makeSubscribeFlow(origin: String?, navigationCoordinator: SubscriptionNavigationCoordinator, subscriptionManager: SubscriptionManager, privacyProDataReporter: PrivacyProDataReporting?) -> some View { diff --git a/DuckDuckGo/Subscription/Views/SubscriptionEmailView.swift b/DuckDuckGo/Subscription/Views/SubscriptionEmailView.swift index 1e10c205f2..0b43465f61 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionEmailView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionEmailView.swift @@ -22,7 +22,6 @@ import Foundation import Core import Combine -@available(iOS 15.0, *) struct SubscriptionEmailView: View { @StateObject var viewModel: SubscriptionEmailViewModel @@ -183,7 +182,6 @@ struct SubscriptionEmailView: View { } // Commented out because CI fails if a SwiftUI preview is enabled https://app.asana.com/0/414709148257752/1206774081310425/f -// @available(iOS 15.0, *) // struct SubscriptionEmailView_Previews: PreviewProvider { // static var previews: some View { // SubscriptionEmailView() diff --git a/DuckDuckGo/Subscription/Views/SubscriptionExternalLinkView.swift b/DuckDuckGo/Subscription/Views/SubscriptionExternalLinkView.swift index 9884d9bcc3..a71582671e 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionExternalLinkView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionExternalLinkView.swift @@ -21,7 +21,6 @@ import SwiftUI import Foundation import DesignResourcesKit -@available(iOS 15.0, *) struct SubscriptionExternalLinkView: View { @Environment(\.dismiss) var dismiss diff --git a/DuckDuckGo/Subscription/Views/SubscriptionFlowView.swift b/DuckDuckGo/Subscription/Views/SubscriptionFlowView.swift index e891ce3348..8cbedebb2a 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionFlowView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionFlowView.swift @@ -22,7 +22,6 @@ import Foundation import DesignResourcesKit import Core -@available(iOS 15.0, *) struct SubscriptionFlowView: View { @Environment(\.dismiss) var dismiss @@ -247,7 +246,6 @@ struct SubscriptionFlowView: View { } // Commented out because CI fails if a SwiftUI preview is enabled https://app.asana.com/0/414709148257752/1206774081310425/f -// @available(iOS 15.0, *) // struct SubscriptionFlowView_Previews: PreviewProvider { // static var previews: some View { // SubscriptionFlowView() diff --git a/DuckDuckGo/Subscription/Views/SubscriptionGoogleView.swift b/DuckDuckGo/Subscription/Views/SubscriptionGoogleView.swift index c790e29ae4..06f81ecda7 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionGoogleView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionGoogleView.swift @@ -20,8 +20,6 @@ import Foundation import SwiftUI - -@available(iOS 15.0, *) struct SubscriptionGoogleView: View { enum Constants { @@ -53,8 +51,6 @@ struct SubscriptionGoogleView: View { #if DEBUG -@available(iOS 15.0, *) - struct SubscriptionGoogleView_Previews: PreviewProvider { static var previews: some View { NavigationView { diff --git a/DuckDuckGo/Subscription/Views/SubscriptionITPView.swift b/DuckDuckGo/Subscription/Views/SubscriptionITPView.swift index 76ed85d96d..29ff072a6c 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionITPView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionITPView.swift @@ -32,7 +32,6 @@ struct SubscriptionActivityViewController: UIViewControllerRepresentable { func updateUIViewController(_ uiViewController: UIActivityViewController, context: Context) {} } -@available(iOS 15.0, *) struct SubscriptionITPView: View { @Environment(\.dismiss) var dismiss @@ -142,7 +141,6 @@ struct SubscriptionITPView: View { } // Commented out because CI fails if a SwiftUI preview is enabled https://app.asana.com/0/414709148257752/1206774081310425/f -// @available(iOS 15.0, *) // struct SubscriptionITPView_Previews: PreviewProvider { // static var previews: some View { // SubscriptionITPView() diff --git a/DuckDuckGo/Subscription/Views/SubscriptionPIRView.swift b/DuckDuckGo/Subscription/Views/SubscriptionPIRView.swift index 74a7fcf1a0..7947d697e1 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionPIRView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionPIRView.swift @@ -22,7 +22,6 @@ import Foundation import DesignResourcesKit import DuckUI -@available(iOS 15.0, *) struct SubscriptionPIRView: View { @Environment(\.dismiss) var dismiss @@ -181,7 +180,6 @@ struct SubscriptionPIRView: View { } // Commented out because CI fails if a SwiftUI preview is enabled https://app.asana.com/0/414709148257752/1206774081310425/f -// @available(iOS 15.0, *) // struct SubscriptionPIRView_Previews: PreviewProvider { // static var previews: some View { // SubscriptionPIRView() diff --git a/DuckDuckGo/Subscription/Views/SubscriptionRestoreView.swift b/DuckDuckGo/Subscription/Views/SubscriptionRestoreView.swift index 3368a036b0..1063398adc 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionRestoreView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionRestoreView.swift @@ -22,7 +22,6 @@ import SwiftUI import DesignResourcesKit import Core -@available(iOS 15.0, *) struct SubscriptionRestoreView: View { @Environment(\.dismiss) var dismiss diff --git a/DuckDuckGo/Subscription/Views/SubscriptionSettingsView.swift b/DuckDuckGo/Subscription/Views/SubscriptionSettingsView.swift index 76dcf7f7d7..6462f25c3f 100644 --- a/DuckDuckGo/Subscription/Views/SubscriptionSettingsView.swift +++ b/DuckDuckGo/Subscription/Views/SubscriptionSettingsView.swift @@ -22,7 +22,6 @@ import SwiftUI import DesignResourcesKit import Core -@available(iOS 15.0, *) struct SubscriptionSettingsView: View { @Environment(\.dismiss) var dismiss @@ -319,7 +318,6 @@ struct SubscriptionSettingsView: View { } // Commented out because CI fails if a SwiftUI preview is enabled https://app.asana.com/0/414709148257752/1206774081310425/f -// @available(iOS 15.0, *) // struct SubscriptionSettingsView_Previews: PreviewProvider { // static var previews: some View { // SubscriptionSettingsView() diff --git a/DuckDuckGo/SubscriptionDebugViewController.swift b/DuckDuckGo/SubscriptionDebugViewController.swift index b57c1b3e69..019a12abfa 100644 --- a/DuckDuckGo/SubscriptionDebugViewController.swift +++ b/DuckDuckGo/SubscriptionDebugViewController.swift @@ -26,7 +26,7 @@ import Core import NetworkProtection #endif -@available(iOS 15.0, *) final class SubscriptionDebugViewController: UITableViewController { +final class SubscriptionDebugViewController: UITableViewController { let subscriptionAppGroup = Bundle.main.appGroup(bundle: .subs) private var subscriptionManager: SubscriptionManager { diff --git a/DuckDuckGo/SyncSettingsViewController.swift b/DuckDuckGo/SyncSettingsViewController.swift index b1dc787e10..25ff94a2ed 100644 --- a/DuckDuckGo/SyncSettingsViewController.swift +++ b/DuckDuckGo/SyncSettingsViewController.swift @@ -416,14 +416,12 @@ extension SyncSettingsViewController { navigationController?.navigationBar.barTintColor = theme.barBackgroundColor navigationController?.navigationBar.tintColor = theme.navigationBarTintColor - if #available(iOS 15.0, *) { - let appearance = UINavigationBarAppearance() - appearance.shadowColor = .clear - appearance.backgroundColor = theme.backgroundColor + let appearance = UINavigationBarAppearance() + appearance.shadowColor = .clear + appearance.backgroundColor = theme.backgroundColor - navigationController?.navigationBar.standardAppearance = appearance - navigationController?.navigationBar.scrollEdgeAppearance = appearance - } + navigationController?.navigationBar.standardAppearance = appearance + navigationController?.navigationBar.scrollEdgeAppearance = appearance } diff --git a/DuckDuckGo/TabSwitcherViewController.swift b/DuckDuckGo/TabSwitcherViewController.swift index 545698b9d0..fca5edc4c3 100644 --- a/DuckDuckGo/TabSwitcherViewController.swift +++ b/DuckDuckGo/TabSwitcherViewController.swift @@ -513,11 +513,7 @@ extension TabSwitcherViewController: TabObserver { } if let index = tabsModel.indexOf(tab: tab), index < collectionView.numberOfItems(inSection: 0) { - if #available(iOS 15.0, *) { - collectionView.reconfigureItems(at: [IndexPath(row: index, section: 0)]) - } else { - collectionView.reloadItems(at: [IndexPath(row: index, section: 0)]) - } + collectionView.reconfigureItems(at: [IndexPath(row: index, section: 0)]) } } } diff --git a/DuckDuckGo/TabViewController.swift b/DuckDuckGo/TabViewController.swift index 6d40815662..40ba5c2e40 100644 --- a/DuckDuckGo/TabViewController.swift +++ b/DuckDuckGo/TabViewController.swift @@ -648,9 +648,7 @@ class TabViewController: UIViewController { requeryLogic.onNewNavigation(url: url) } - if #available(iOS 15.0, *) { - assert(urlRequest.attribution == .user, "WebView requests should be user attributed") - } + assert(urlRequest.attribution == .user, "WebView requests should be user attributed") refreshCountSinceLoad = 0 @@ -1250,8 +1248,7 @@ extension TabViewController: WKNavigationDelegate { mostRecentAutoPreviewDownloadID = download?.id Pixel.fire(pixel: .downloadStarted, withAdditionalParameters: [PixelParameters.canAutoPreviewMIMEType: "1"]) - } else if #available(iOS 14.5, *), - let url = navigationResponse.response.url, + } else if let url = navigationResponse.response.url, case .blob = SchemeHandler.schemeType(for: url) { decisionHandler(.download) @@ -1509,9 +1506,7 @@ extension TabViewController: WKNavigationDelegate { return nil } - if #available(iOS 15.0, *) { - request.attribution = .user - } + request.attribution = .user return request } @@ -1880,14 +1875,6 @@ extension TabViewController { private func performBlobNavigation(_ navigationAction: WKNavigationAction, completion: @escaping (WKNavigationActionPolicy) -> Void) { - guard #available(iOS 14.5, *) else { - Pixel.fire(pixel: .downloadAttemptToOpenBLOBviaJS) - self.legacySetupBlobDownload(for: navigationAction) { - completion(.allow) - } - return - } - self.blobDownloadTargetFrame = navigationAction.targetFrame completion(.allow) } @@ -1900,23 +1887,9 @@ extension TabViewController { let url = navigationResponse.response.url! if case .blob = SchemeHandler.schemeType(for: url) { - if #available(iOS 14.5, *) { - decisionHandler(.download) - - return nil - - // [iOS<14.5 legacy] reuse temporary download for blob: initiated by WKNavigationAction - } else if let download = self.temporaryDownloadForPreviewedFile, - download.temporary, - download.url == navigationResponse.response.url { - self.temporaryDownloadForPreviewedFile = nil - download.temporary = FilePreviewHelper.canAutoPreviewMIMEType(download.mimeType) - downloadManager.startDownload(download) - - decisionHandler(.cancel) + decisionHandler(.download) - return download - } + return nil } else if let download = downloadManager.makeDownload(navigationResponse: navigationResponse, cookieStore: cookieStore) { downloadManager.startDownload(download) decisionHandler(.cancel) @@ -1948,9 +1921,7 @@ extension TabViewController { guard SchemeHandler.schemeType(for: url) != .blob else { // suggestedFilename is empty for blob: downloads unless handled via completion(.download) // WKNavigationResponse._downloadAttribute private API could be used instead of it :( - if #available(iOS 14.5, *), - // if temporary download not setup yet, preview otherwise - self.temporaryDownloadForPreviewedFile?.url != url { + if self.temporaryDownloadForPreviewedFile?.url != url { // if temporary download not setup yet, preview otherwise // calls webView:navigationAction:didBecomeDownload: return .download } else { @@ -1966,7 +1937,6 @@ extension TabViewController { return .allow } - @available(iOS 14.5, *) func webView(_ webView: WKWebView, navigationResponse: WKNavigationResponse, didBecome download: WKDownload) { let delegate = InlineWKDownloadDelegate() // temporary delegate held strongly in callbacks @@ -2024,7 +1994,6 @@ extension TabViewController { download.delegate = delegate } - @available(iOS 14.5, *) private func transfer(_ download: WKDownload, to downloadManager: DownloadManager, with response: URLResponse, @@ -2068,49 +2037,6 @@ extension TabViewController { } } - private func legacySetupBlobDownload(for navigationAction: WKNavigationAction, completion: @escaping () -> Void) { - let url = navigationAction.request.url! - let legacyBlobDownloadScript = """ - let blob = await fetch(url).then(r => r.blob()) - let data = await new Promise((resolve, reject) => { - const fileReader = new FileReader(); - fileReader.onerror = (e) => reject(fileReader.error); - fileReader.onloadend = (e) => { - resolve(e.target.result.split(",")[1]) - }; - fileReader.readAsDataURL(blob); - }) - return { - mimeType: blob.type, - size: blob.size, - data: data - } - """ - webView.callAsyncJavaScript(legacyBlobDownloadScript, - arguments: ["url": url.absoluteString], - in: navigationAction.sourceFrame, - in: .page) { [weak self] result in - guard let self = self, - let dict = try? result.get() as? [String: Any], - let mimeType = dict["mimeType"] as? String, - let size = dict["size"] as? Int, - let data = dict["data"] as? String - else { - completion() - return - } - - let downloadManager = AppDependencyProvider.shared.downloadManager - let downloadSession = Base64DownloadSession(base64: data) - let response = URLResponse(url: url, mimeType: mimeType, expectedContentLength: size, textEncodingName: nil) - self.temporaryDownloadForPreviewedFile = downloadManager.makeDownload(response: response, - downloadSession: downloadSession, - cookieStore: nil, - temporary: true) - completion() - } - } - private func registerForDownloadsNotifications() { NotificationCenter.default.addObserver(self, selector: #selector(downloadDidStart), @@ -2554,18 +2480,18 @@ extension TabViewController: SecureVaultManagerDelegate { domainLastShownOn: self.domainSaveLoginPromptLastShownOn) self.domainSaveLoginPromptLastShownOn = self.url?.host saveLoginController.delegate = self - if #available(iOS 15.0, *) { - if let presentationController = saveLoginController.presentationController as? UISheetPresentationController { - if #available(iOS 16.0, *) { - presentationController.detents = [.custom(resolver: { _ in - saveLoginController.viewModel?.minHeight - })] - } else { - presentationController.detents = [.medium()] - } - presentationController.prefersScrollingExpandsWhenScrolledToEdge = false + + if let presentationController = saveLoginController.presentationController as? UISheetPresentationController { + if #available(iOS 16.0, *) { + presentationController.detents = [.custom(resolver: { _ in + saveLoginController.viewModel?.minHeight + })] + } else { + presentationController.detents = [.medium()] } + presentationController.prefersScrollingExpandsWhenScrolledToEdge = false } + self.present(saveLoginController, animated: true, completion: nil) } } @@ -2663,17 +2589,16 @@ extension TabViewController: SecureVaultManagerDelegate { completionHandler(useGeneratedPassword) } - if #available(iOS 15.0, *) { - if let presentationController = passwordGenerationPromptViewController.presentationController as? UISheetPresentationController { - if #available(iOS 16.0, *) { - presentationController.detents = [.custom(resolver: { _ in - AutofillViews.passwordGenerationMinHeight - })] - } else { - presentationController.detents = [.medium()] - } + if let presentationController = passwordGenerationPromptViewController.presentationController as? UISheetPresentationController { + if #available(iOS 16.0, *) { + presentationController.detents = [.custom(resolver: { _ in + AutofillViews.passwordGenerationMinHeight + })] + } else { + presentationController.detents = [.medium()] } } + self.present(passwordGenerationPromptViewController, animated: true) } @@ -2706,17 +2631,16 @@ extension TabViewController: SecureVaultManagerDelegate { } }) - if #available(iOS 15.0, *) { - if let presentationController = autofillPromptViewController.presentationController as? UISheetPresentationController { - if #available(iOS 16.0, *) { - presentationController.detents = [.custom(resolver: { _ in - AutofillViews.loginPromptMinHeight - })] - } else { - presentationController.detents = useLargeDetent ? [.large()] : [.medium()] - } + if let presentationController = autofillPromptViewController.presentationController as? UISheetPresentationController { + if #available(iOS 16.0, *) { + presentationController.detents = [.custom(resolver: { _ in + AutofillViews.loginPromptMinHeight + })] + } else { + presentationController.detents = useLargeDetent ? [.large()] : [.medium()] } } + self.present(autofillPromptViewController, animated: true, completion: nil) } diff --git a/DuckDuckGo/TextSizeSettingsViewController.swift b/DuckDuckGo/TextSizeSettingsViewController.swift index ad76cf0821..ca843ae2eb 100644 --- a/DuckDuckGo/TextSizeSettingsViewController.swift +++ b/DuckDuckGo/TextSizeSettingsViewController.swift @@ -58,21 +58,19 @@ class TextSizeSettingsViewController: UITableViewController { } private func adjustDetentOnPresentation() { - if #available(iOS 15.0, *) { - if !hasAdjustedDetent, let sheetController = navigationController?.presentationController as? UISheetPresentationController { - sheetController.detents = [.medium(), .large()] - sheetController.delegate = self - sheetController.largestUndimmedDetentIdentifier = .medium - sheetController.preferredCornerRadius = 16 - - sheetController.animateChanges { - sheetController.selectedDetentIdentifier = .medium - } - - navigationItem.leftBarButtonItem = customBackBarButtonItem - - hasAdjustedDetent = true + if !hasAdjustedDetent, let sheetController = navigationController?.presentationController as? UISheetPresentationController { + sheetController.detents = [.medium(), .large()] + sheetController.delegate = self + sheetController.largestUndimmedDetentIdentifier = .medium + sheetController.preferredCornerRadius = 16 + + sheetController.animateChanges { + sheetController.selectedDetentIdentifier = .medium } + + navigationItem.leftBarButtonItem = customBackBarButtonItem + + hasAdjustedDetent = true } } @@ -135,28 +133,26 @@ class TextSizeSettingsViewController: UITableViewController { @IBAction func customBackButtonTapped(_ sender: AnyObject) { var shouldPopViewController: Bool = true - if #available(iOS 15.0, *) { - if let sheetController = navigationController?.presentationController as? UISheetPresentationController { - sheetController.detents = [.large()] - - // We recreate two-step detent animation, like on push but in reverse - if sheetController.selectedDetentIdentifier != .large { - shouldPopViewController = false - - // First step is to animate detent to large - sheetController.animateChanges { - sheetController.selectedDetentIdentifier = .large - } - - // Second step is to actually pop the view controller - DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { - self.navigationItem.leftBarButtonItem = nil - self.navigationController?.popViewController(animated: true) - } + if let sheetController = navigationController?.presentationController as? UISheetPresentationController { + sheetController.detents = [.large()] + + // We recreate two-step detent animation, like on push but in reverse + if sheetController.selectedDetentIdentifier != .large { + shouldPopViewController = false + + // First step is to animate detent to large + sheetController.animateChanges { + sheetController.selectedDetentIdentifier = .large + } + + // Second step is to actually pop the view controller + DispatchQueue.main.asyncAfter(deadline: .now() + 0.35) { + self.navigationItem.leftBarButtonItem = nil + self.navigationController?.popViewController(animated: true) } } } - + if shouldPopViewController { navigationItem.leftBarButtonItem = nil navigationController?.popViewController(animated: true) @@ -195,7 +191,6 @@ class TextSizeSettingsViewController: UITableViewController { } } -@available(iOS 15.0, *) extension TextSizeSettingsViewController: UISheetPresentationControllerDelegate { func sheetPresentationControllerDidChangeSelectedDetentIdentifier(_ sheetPresentationController: UISheetPresentationController) { diff --git a/DuckDuckGo/Themable.swift b/DuckDuckGo/Themable.swift index fa9c1cf470..6b42bde066 100644 --- a/DuckDuckGo/Themable.swift +++ b/DuckDuckGo/Themable.swift @@ -28,15 +28,13 @@ extension UIViewController { titleAttrs[NSAttributedString.Key.foregroundColor] = theme.navigationBarTitleColor navigationController?.navigationBar.titleTextAttributes = titleAttrs - if #available(iOS 15.0, *) { - let appearance = UINavigationBarAppearance() - appearance.shadowColor = .clear - appearance.backgroundColor = theme.backgroundColor - appearance.titleTextAttributes = titleAttrs + let appearance = UINavigationBarAppearance() + appearance.shadowColor = .clear + appearance.backgroundColor = theme.backgroundColor + appearance.titleTextAttributes = titleAttrs - navigationController?.navigationBar.standardAppearance = appearance - navigationController?.navigationBar.scrollEdgeAppearance = appearance - } + navigationController?.navigationBar.standardAppearance = appearance + navigationController?.navigationBar.scrollEdgeAppearance = appearance } func decorateToolbar(with theme: Theme = ThemeManager.shared.currentTheme) { @@ -44,9 +42,7 @@ extension UIViewController { navigationController?.toolbar.backgroundColor = theme.barBackgroundColor navigationController?.toolbar.tintColor = theme.barTintColor - if #available(iOS 15.0, *) { - let appearance = navigationController?.toolbar.standardAppearance - navigationController?.toolbar.scrollEdgeAppearance = appearance - } + let appearance = navigationController?.toolbar.standardAppearance + navigationController?.toolbar.scrollEdgeAppearance = appearance } } diff --git a/DuckDuckGo/UIApplicationExtension.swift b/DuckDuckGo/UIApplicationExtension.swift index 9f87c640fc..601a93abde 100644 --- a/DuckDuckGo/UIApplicationExtension.swift +++ b/DuckDuckGo/UIApplicationExtension.swift @@ -41,7 +41,17 @@ extension UIApplication { } extension UIApplication { + var foregroundSceneWindows: [UIWindow] { + guard let scene = UIApplication.shared.connectedScenes.first(where: { + $0.activationState == .foregroundActive + }) as? UIWindowScene else { + return [] + } + + return scene.windows + } + var firstKeyWindow: UIWindow? { - return UIApplication.shared.windows.first(where: \.isKeyWindow) + return foregroundSceneWindows.first(where: \.isKeyWindow) } } diff --git a/DuckDuckGo/UIScrollViewExtension.swift b/DuckDuckGo/UIScrollViewExtension.swift index c1dd40cdcb..f58e224fc6 100644 --- a/DuckDuckGo/UIScrollViewExtension.swift +++ b/DuckDuckGo/UIScrollViewExtension.swift @@ -28,7 +28,7 @@ extension UIScrollView { /// Calculates rect to scroll to based on what is most useful area for a user and size/position of the keyboard. func desiredVisibleRect(forInteractionArea interactionArea: CGRect, coveredBy keyboardRect: CGRect) -> CGRect? { - guard let window = UIApplication.shared.windows.filter({ $0.isKeyWindow }).first else { return nil } + guard let window = UIApplication.shared.firstKeyWindow else { return nil } let viewInWindow = convert(bounds, to: window) let obscuredScrollViewArea = viewInWindow.intersection(keyboardRect) diff --git a/DuckDuckGo/URLRequestExtension.swift b/DuckDuckGo/URLRequestExtension.swift index 1940448267..1f35d77f99 100644 --- a/DuckDuckGo/URLRequestExtension.swift +++ b/DuckDuckGo/URLRequestExtension.swift @@ -23,21 +23,13 @@ extension URLRequest { public static func developerInitiated(_ url: URL) -> URLRequest { var request = URLRequest(url: url) - - if #available(iOS 15.0, *) { - request.attribution = .developer - } - + request.attribution = .developer return request } public static func userInitiated(_ url: URL) -> URLRequest { var request = URLRequest(url: url) - - if #available(iOS 15.0, *) { - request.attribution = .user - } - + request.attribution = .user return request } diff --git a/DuckDuckGo/ViewExtension.swift b/DuckDuckGo/ViewExtension.swift index 24dab516d9..287be0c110 100644 --- a/DuckDuckGo/ViewExtension.swift +++ b/DuckDuckGo/ViewExtension.swift @@ -34,13 +34,6 @@ extension View { } } -/* - These exensions are needed to provide the UI styling specs for Network Protection - However, at time of writing, they are not supported in iOS <=14. As Network Protection - is not supporting iOS <=14, these are being kept separate. - */ - -@available(iOS 15, *) extension View { @ViewBuilder func applyInsetGroupedListStyle() -> some View { diff --git a/DuckDuckGo/VoiceSearchFeedbackView.swift b/DuckDuckGo/VoiceSearchFeedbackView.swift index 1a8ac63333..3e90eeda66 100644 --- a/DuckDuckGo/VoiceSearchFeedbackView.swift +++ b/DuckDuckGo/VoiceSearchFeedbackView.swift @@ -29,9 +29,7 @@ struct VoiceSearchFeedbackView: View { voiceFeedbackView } .onAppear { - if #available(iOS 15, *) { - speechModel.startSpeechRecognizer() - } + speechModel.startSpeechRecognizer() speechModel.startSilenceAnimation() }.onDisappear { speechModel.stopSpeechRecognizer() @@ -172,10 +170,9 @@ struct VoiceSearchFeedbackView_Previews: PreviewProvider { VoiceSearchFeedbackView(speechModel: VoiceSearchFeedbackViewModel(speechRecognizer: PreviewMockSpeechRecognizer())) .preferredColorScheme($0) } - if #available(iOS 15.0, *) { - VoiceSearchFeedbackView(speechModel: VoiceSearchFeedbackViewModel(speechRecognizer: PreviewMockSpeechRecognizer())) - .previewInterfaceOrientation(.landscapeRight) - } + + VoiceSearchFeedbackView(speechModel: VoiceSearchFeedbackViewModel(speechRecognizer: PreviewMockSpeechRecognizer())) + .previewInterfaceOrientation(.landscapeRight) } } } diff --git a/DuckDuckGo/VoiceSearchFeedbackViewModel.swift b/DuckDuckGo/VoiceSearchFeedbackViewModel.swift index 0b1499103d..f83b6c69f7 100644 --- a/DuckDuckGo/VoiceSearchFeedbackViewModel.swift +++ b/DuckDuckGo/VoiceSearchFeedbackViewModel.swift @@ -57,7 +57,6 @@ class VoiceSearchFeedbackViewModel: ObservableObject { self.speechRecognizer = speechRecognizer } - @available(iOS 15, *) func startSpeechRecognizer() { speechRecognizer.startRecording { [weak self] text, error, speechDidFinish in DispatchQueue.main.async { diff --git a/DuckDuckGo/VoiceSearchHelper.swift b/DuckDuckGo/VoiceSearchHelper.swift index 766ba64efe..ce8ad736a7 100644 --- a/DuckDuckGo/VoiceSearchHelper.swift +++ b/DuckDuckGo/VoiceSearchHelper.swift @@ -42,15 +42,12 @@ class VoiceSearchHelper: VoiceSearchHelperProtocol { } init() { - // https://app.asana.com/0/1201011656765697/1201271104639596 - if #available(iOS 15.0, *) { #if targetEnvironment(simulator) isSpeechRecognizerAvailable = true #else speechRecognizer.delegate = self isSpeechRecognizerAvailable = speechRecognizer.isAvailable #endif - } } func migrateSettingsFlagIfNecessary() { diff --git a/DuckDuckGo/WKDownloadSession.swift b/DuckDuckGo/WKDownloadSession.swift index 6dbef718aa..c784deba5f 100644 --- a/DuckDuckGo/WKDownloadSession.swift +++ b/DuckDuckGo/WKDownloadSession.swift @@ -20,7 +20,6 @@ import Foundation import WebKit -@available(iOS 14.5, *) final class WKDownloadSession: NSObject, DownloadSession { weak var download: WKDownload? weak var delegate: DownloadSessionDelegate? @@ -70,7 +69,6 @@ final class WKDownloadSession: NSObject, DownloadSession { } -@available(iOS 14.5, *) extension WKDownloadSession: WKDownloadDelegate { func download(_ download: WKDownload, diff --git a/DuckDuckGo/global.swift b/DuckDuckGo/global.swift index 39a18de03e..2e745e3905 100644 --- a/DuckDuckGo/global.swift +++ b/DuckDuckGo/global.swift @@ -23,5 +23,5 @@ import UIKit /// /// Device orientation contains multiple states including unknown and flat, where as this approach is binary. var isPortrait: Bool { - return UIApplication.shared.windows.filter({ $0.isKeyWindow }).first?.windowScene?.interfaceOrientation.isPortrait ?? false + return UIApplication.shared.firstKeyWindow?.windowScene?.interfaceOrientation.isPortrait ?? false } diff --git a/DuckDuckGoTests/AnimatableTypingTextModelTests.swift b/DuckDuckGoTests/AnimatableTypingTextModelTests.swift index dffcef4898..7da4544530 100644 --- a/DuckDuckGoTests/AnimatableTypingTextModelTests.swift +++ b/DuckDuckGoTests/AnimatableTypingTextModelTests.swift @@ -69,10 +69,6 @@ final class AnimatableTypingTextModelTests: XCTestCase { } func testWhenTimerFiresThenTypedTextIsPublished_iOS15() throws { - guard #available(iOS 15, *) else { - throw XCTSkip("Test available only on iOS 15*") - } - // GIVEN let text = "Hello World!!!" var typedText: NSAttributedString = .init(string: "") @@ -97,10 +93,6 @@ final class AnimatableTypingTextModelTests: XCTestCase { } func testWhenStopAnimatingIsCalledThenWholeTextIsPublished_iOS15() throws { - guard #available(iOS 15, *) else { - throw XCTSkip("Test available only on iOS 15*") - } - // GIVEN let text = "Hello World!!!" var typedText: NSAttributedString = .init(string: "") diff --git a/DuckDuckGoTests/MockDependencyProvider.swift b/DuckDuckGoTests/MockDependencyProvider.swift index 214f675820..8dad3f625a 100644 --- a/DuckDuckGoTests/MockDependencyProvider.swift +++ b/DuckDuckGoTests/MockDependencyProvider.swift @@ -65,21 +65,17 @@ class MockDependencyProvider: DependencyProvider { subscriptionFeatureAvailability = defaultProvider.subscriptionFeatureAvailability accountManager = AccountManagerMock() - if #available(iOS 15.0, *) { - let subscriptionService = DefaultSubscriptionEndpointService(currentServiceEnvironment: .production) - let authService = DefaultAuthEndpointService(currentServiceEnvironment: .production) - let storePurchaseManager = DefaultStorePurchaseManager() - subscriptionManager = SubscriptionManagerMock(accountManager: accountManager, - subscriptionEndpointService: subscriptionService, - authEndpointService: authService, - storePurchaseManager: storePurchaseManager, - currentEnvironment: SubscriptionEnvironment(serviceEnvironment: .production, - purchasePlatform: .appStore), - canPurchase: true) - } else { - // This is used just for iOS <15, it's a sort of mocked environment that will not be used. - subscriptionManager = SubscriptionManageriOS14(accountManager: accountManager) - } + + let subscriptionService = DefaultSubscriptionEndpointService(currentServiceEnvironment: .production) + let authService = DefaultAuthEndpointService(currentServiceEnvironment: .production) + let storePurchaseManager = DefaultStorePurchaseManager() + subscriptionManager = SubscriptionManagerMock(accountManager: accountManager, + subscriptionEndpointService: subscriptionService, + authEndpointService: authService, + storePurchaseManager: storePurchaseManager, + currentEnvironment: SubscriptionEnvironment(serviceEnvironment: .production, + purchasePlatform: .appStore), + canPurchase: true) let accessTokenProvider: () -> String? = { { "sometoken" } }() networkProtectionKeychainTokenStore = NetworkProtectionKeychainTokenStore(accessTokenProvider: accessTokenProvider) diff --git a/DuckDuckGoTests/Subscription/SubscriptionContainerViewModelTests.swift b/DuckDuckGoTests/Subscription/SubscriptionContainerViewModelTests.swift index 77f460da48..a46ab82b20 100644 --- a/DuckDuckGoTests/Subscription/SubscriptionContainerViewModelTests.swift +++ b/DuckDuckGoTests/Subscription/SubscriptionContainerViewModelTests.swift @@ -22,7 +22,6 @@ import XCTest @testable import Subscription import SubscriptionTestingUtilities -@available(iOS 15.0, *) final class SubscriptionContainerViewModelTests: XCTestCase { var sut: SubscriptionContainerViewModel! let subscriptionManager = MockDependencyProvider().subscriptionManager diff --git a/DuckDuckGoTests/Subscription/SubscriptionFlowViewModelTests.swift b/DuckDuckGoTests/Subscription/SubscriptionFlowViewModelTests.swift index 76646f449e..260d06d816 100644 --- a/DuckDuckGoTests/Subscription/SubscriptionFlowViewModelTests.swift +++ b/DuckDuckGoTests/Subscription/SubscriptionFlowViewModelTests.swift @@ -22,7 +22,6 @@ import XCTest @testable import Subscription import SubscriptionTestingUtilities -@available(iOS 15.0, *) final class SubscriptionFlowViewModelTests: XCTestCase { private var sut: SubscriptionFlowViewModel! diff --git a/DuckDuckGoTests/Subscription/SubscriptionPagesUseSubscriptionFeatureTests.swift b/DuckDuckGoTests/Subscription/SubscriptionPagesUseSubscriptionFeatureTests.swift index f6292a6138..0cb08f6fac 100644 --- a/DuckDuckGoTests/Subscription/SubscriptionPagesUseSubscriptionFeatureTests.swift +++ b/DuckDuckGoTests/Subscription/SubscriptionPagesUseSubscriptionFeatureTests.swift @@ -22,7 +22,6 @@ import XCTest @testable import Subscription import SubscriptionTestingUtilities -@available(iOS 15.0, *) final class SubscriptionPagesUseSubscriptionFeatureTests: XCTestCase { override func setUpWithError() throws { diff --git a/LocalPackages/DuckUI/Package.swift b/LocalPackages/DuckUI/Package.swift index 55e65316ee..881fb4f33d 100644 --- a/LocalPackages/DuckUI/Package.swift +++ b/LocalPackages/DuckUI/Package.swift @@ -22,7 +22,7 @@ import PackageDescription let package = Package( name: "DuckUI", platforms: [ - .iOS(.v14) + .iOS(.v15) ], products: [ diff --git a/LocalPackages/SyncUI/Package.swift b/LocalPackages/SyncUI/Package.swift index d1da2db921..9b9ed8ab5f 100644 --- a/LocalPackages/SyncUI/Package.swift +++ b/LocalPackages/SyncUI/Package.swift @@ -23,7 +23,7 @@ let package = Package( name: "SyncUI", defaultLocalization: "en", platforms: [ - .iOS(.v14) + .iOS(.v15) ], products: [ // Products define the executables and libraries a package produces, and make them visible to other packages. diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/ViewExtensions.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/ViewExtensions.swift index 058fb71154..32ac706bf6 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/ViewExtensions.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/Internal/ViewExtensions.swift @@ -42,29 +42,17 @@ extension View { @ViewBuilder func regularMaterialBackground() -> some View { - if #available(iOS 15.0, *) { - self.background(.regularMaterial) - } else { - self.background(Rectangle().foregroundColor(.black.opacity(0.9))) - } + self.background(.regularMaterial) } @ViewBuilder func thinMaterialBackground() -> some View { - if #available(iOS 15.0, *) { - self.background(.ultraThinMaterial) - } else { - self.background(Rectangle().foregroundColor(.black.opacity(0.9))) - } + self.background(.ultraThinMaterial) } @ViewBuilder func monospaceSystemFont(ofSize size: Double) -> some View { - if #available(iOS 15.0, *) { - font(.system(size: size).monospaced()) - } else { - font(.system(size: size)) - } + font(.system(size: size).monospaced()) } @ViewBuilder diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/PasteCodeView.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/PasteCodeView.swift index 45e9f92719..78b78167fc 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/PasteCodeView.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/PasteCodeView.swift @@ -77,20 +77,11 @@ public struct PasteCodeView: View { .padding(.horizontal) } else { - if #available(iOS 15.0, *) { - Text(instructionsString) - .lineLimit(nil) - .multilineTextAlignment(.center) - .foregroundColor(.white.opacity(0.6)) - .padding() - } else { - Text(UserText.manuallyEnterCodeInstructionAttributed(syncMenuPath: UserText.syncMenuPath, - menuItem: UserText.viewTextCodeMenuItem)) - .lineLimit(nil) - .multilineTextAlignment(.center) - .foregroundColor(.white.opacity(0.6)) - .padding() - } + Text(instructionsString) + .lineLimit(nil) + .multilineTextAlignment(.center) + .foregroundColor(.white.opacity(0.6)) + .padding() Spacer() } @@ -105,7 +96,6 @@ public struct PasteCodeView: View { .padding() } - @available(iOS 15, *) var instructionsString: AttributedString { let baseString = UserText.manuallyEnterCodeInstructionAttributed(syncMenuPath: UserText.syncMenuPath, menuItem: UserText.viewTextCodeMenuItem) var instructions = AttributedString(baseString) diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/ScanOrPasteCodeView.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/ScanOrPasteCodeView.swift index 5df2f93609..2d16003406 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/ScanOrPasteCodeView.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/ScanOrPasteCodeView.swift @@ -71,14 +71,9 @@ public struct ScanOrSeeCode: View { } func instructionsText() -> some View { - if #available(iOS 15.0, *) { - return Text(instructionsString) - } else { - return Text(UserText.scanOrSeeCodeInstruction) - } + return Text(instructionsString) } - @available(iOS 15, *) var instructionsString: AttributedString { let baseString = UserText.scanOrSeeCodeInstructionAttributed(syncMenuPath: UserText.syncMenuPath) var instructions = AttributedString(baseString) diff --git a/LocalPackages/SyncUI/Sources/SyncUI/Views/SyncSettingsViewExtension.swift b/LocalPackages/SyncUI/Sources/SyncUI/Views/SyncSettingsViewExtension.swift index 59fbfbddcd..03d2637a1e 100644 --- a/LocalPackages/SyncUI/Sources/SyncUI/Views/SyncSettingsViewExtension.swift +++ b/LocalPackages/SyncUI/Sources/SyncUI/Views/SyncSettingsViewExtension.swift @@ -358,17 +358,13 @@ extension SyncSettingsView { Button(action: { isEnvironmentSwitcherInstructionsVisible.toggle() }, label: { - if #available(iOS 15.0, *) { - Text("Dev environment") - .daxFootnoteRegular() - .padding(.horizontal, 10) - .padding(.vertical, 2) - .foregroundColor(.white) - .background(Color.red40) - .clipShape(RoundedRectangle(cornerRadius: 10)) - } else { - Text("Dev environment") - } + Text("Dev environment") + .daxFootnoteRegular() + .padding(.horizontal, 10) + .padding(.vertical, 2) + .foregroundColor(.white) + .background(Color.red40) + .clipShape(RoundedRectangle(cornerRadius: 10)) }) .alert(isPresented: $isEnvironmentSwitcherInstructionsVisible) { Alert( diff --git a/LocalPackages/Waitlist/Package.swift b/LocalPackages/Waitlist/Package.swift index 59aa29a33f..75a0994bde 100644 --- a/LocalPackages/Waitlist/Package.swift +++ b/LocalPackages/Waitlist/Package.swift @@ -6,7 +6,7 @@ import PackageDescription let package = Package( name: "Waitlist", platforms: [ - .iOS(.v14) + .iOS(.v15) ], products: [ diff --git a/OpenAction/ActionViewController.swift b/OpenAction/ActionViewController.swift index 1ec079c06d..3aaae8e55d 100644 --- a/OpenAction/ActionViewController.swift +++ b/OpenAction/ActionViewController.swift @@ -21,6 +21,7 @@ import Common import UIKit import MobileCoreServices import Core +import UniformTypeIdentifiers class ActionViewController: UIViewController { @@ -30,8 +31,8 @@ class ActionViewController: UIViewController { for item in extensionContext?.inputItems as? [NSExtensionItem] ?? [] { for provider in item.attachments ?? [] { - if provider.hasItemConformingToTypeIdentifier(kUTTypeText as String) { - provider.loadItem(forTypeIdentifier: kUTTypeText as String, options: nil) { text, _ in + if provider.hasItemConformingToTypeIdentifier(UTType.text.identifier) { + provider.loadItem(forTypeIdentifier: UTType.text.identifier, options: nil) { text, _ in guard let text = text as? String else { return } guard let url = URL.makeSearchURL(text: text) else { os_log("Couldn‘t for URL for query “%s”", log: .lifecycleLog, type: .error, text) @@ -42,8 +43,8 @@ class ActionViewController: UIViewController { break } - if provider.hasItemConformingToTypeIdentifier(kUTTypeURL as String) { - provider.loadItem(forTypeIdentifier: kUTTypeURL as String, options: nil) { url, _ in + if provider.hasItemConformingToTypeIdentifier(UTType.url.identifier) { + provider.loadItem(forTypeIdentifier: UTType.url.identifier, options: nil) { url, _ in guard let url = url as? URL else { return } self.launchBrowser(withUrl: url) } diff --git a/PacketTunnelProvider/NetworkProtection/NetworkProtectionUNNotificationPresenter.swift b/PacketTunnelProvider/NetworkProtection/NetworkProtectionUNNotificationPresenter.swift index 7e06bdbf1e..8c18f175d5 100644 --- a/PacketTunnelProvider/NetworkProtection/NetworkProtectionUNNotificationPresenter.swift +++ b/PacketTunnelProvider/NetworkProtection/NetworkProtectionUNNotificationPresenter.swift @@ -61,11 +61,8 @@ final class NetworkProtectionUNNotificationPresenter: NSObject, NetworkProtectio content.threadIdentifier = threadIdentifier content.title = UserText.networkProtectionNotificationsTitle content.body = body - - if #available(iOS 15.0, *) { - content.interruptionLevel = .timeSensitive - content.relevanceScore = 0 - } + content.interruptionLevel = .timeSensitive + content.relevanceScore = 0 return content }