Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Subscriptions: 19. Error handling and minor updates #2567

Merged
merged 21 commits into from
Mar 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 8 additions & 6 deletions DuckDuckGo/SettingsSubscriptionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -138,25 +138,27 @@ struct SettingsSubscriptionView: View {
SettingsCellView(label: UserText.settingsPProDBPTitle,
subtitle: UserText.settingsPProDBPSubTitle,
action: { isShowingDBP.toggle() }, isButton: true)
.sheet(isPresented: $isShowingDBP) {
SubscriptionPIRView()
}

}

if viewModel.shouldShowITP {
SettingsCellView(label: UserText.settingsPProITRTitle,
subtitle: UserText.settingsPProITRSubTitle,
action: { isShowingITP.toggle() }, isButton: true)
.sheet(isPresented: $isShowingITP) {
SubscriptionITPView()
}

}

NavigationLink(destination: SubscriptionSettingsView()) {
SettingsCustomCell(content: { manageSubscriptionView })
}

}
.sheet(isPresented: $isShowingDBP) {
SubscriptionPIRView()
}
.sheet(isPresented: $isShowingITP) {
SubscriptionITPView()
}
}

var body: some View {
Expand Down
18 changes: 9 additions & 9 deletions DuckDuckGo/SettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ import Common
import Combine
import SyncUI


#if SUBSCRIPTION
import Subscription
#endif
Expand All @@ -47,12 +48,20 @@ final class SettingsViewModel: ObservableObject {
private var legacyViewProvider: SettingsLegacyViewProvider
private lazy var versionProvider: AppVersion = AppVersion.shared
private let voiceSearchHelper: VoiceSearchHelperProtocol

#if SUBSCRIPTION
private var accountManager: AccountManager
private var signOutObserver: Any?

// Sheet Presentation & Navigation
@Published var isRestoringSubscription: Bool = false
@Published var shouldDisplayRestoreSubscriptionError: Bool = false
@Published var shouldShowNetP = false
@Published var shouldShowDBP = false
@Published var shouldShowITP = false
#endif
@UserDefaultsWrapper(key: .subscriptionIsActive, defaultValue: false)
static private var cachedHasActiveSubscription: Bool


#if NETWORK_PROTECTION
Expand All @@ -63,10 +72,6 @@ final class SettingsViewModel: ObservableObject {
private lazy var isPad = UIDevice.current.userInterfaceIdiom == .pad
private var cancellables = Set<AnyCancellable>()

// Defaults
@UserDefaultsWrapper(key: .subscriptionIsActive, defaultValue: false)
static private var cachedHasActiveSubscription: Bool

// Closures to interact with legacy view controllers through the container
var onRequestPushLegacyView: ((UIViewController) -> Void)?
var onRequestPresentLegacyView: ((UIViewController, _ modal: Bool) -> Void)?
Expand All @@ -78,10 +83,6 @@ final class SettingsViewModel: ObservableObject {
@Published var shouldNavigateToDBP = false
@Published var shouldNavigateToITP = false
@Published var shouldNavigateToSubscriptionFlow = false

@Published var shouldShowNetP = false
@Published var shouldShowDBP = false
@Published var shouldShowITP = false

// Our View State
@Published private(set) var state: SettingsState
Expand Down Expand Up @@ -372,7 +373,6 @@ extension SettingsViewModel {
}
}
}

default:
// Account is active but there's not a valid subscription / entitlements
signOutUser()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ struct AsyncHeadlessWebView: View {
onContentType: { value in
viewModel.contentType = value
},
onNavigationError: { value in
viewModel.navigationError = value
},
navigationCoordinator: viewModel.navigationCoordinator
)
.frame(width: geometry.size.width, height: geometry.size.height)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ final class AsyncHeadlessWebViewViewModel: ObservableObject {
@Published var canGoBack: Bool = false
@Published var canGoForward: Bool = false
@Published var contentType: String = ""
@Published var navigationError: Error?
@Published var allowedDomains: [String]?

var navigationCoordinator = HeadlessWebViewNavCoordinator(webView: nil)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ struct HeadlessWebView: UIViewRepresentable {
var onCanGoBack: ((Bool) -> Void)?
var onCanGoForward: ((Bool) -> Void)?
var onContentType: ((String) -> Void)?
var onNavigationError: ((Error?) -> Void)?
var navigationCoordinator: HeadlessWebViewNavCoordinator

func makeUIView(context: Context) -> WKWebView {
Expand Down Expand Up @@ -73,6 +74,7 @@ struct HeadlessWebView: UIViewRepresentable {
onCanGoBack: onCanGoBack,
onCanGoForward: onCanGoForward,
onContentType: onContentType,
onNavigationError: onNavigationError,
settings: settings
)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ final class HeadlessWebViewCoordinator: NSObject {
var onCanGoBack: ((Bool) -> Void)?
var onCanGoForward: ((Bool) -> Void)?
var onContentType: ((String) -> Void)?
var onNavigationError: ((Error?) -> Void)?
var settings: AsyncHeadlessWebViewSettings

var size: CGSize = .zero
Expand All @@ -52,6 +53,7 @@ final class HeadlessWebViewCoordinator: NSObject {
onCanGoBack: ((Bool) -> Void)?,
onCanGoForward: ((Bool) -> Void)?,
onContentType: ((String) -> Void)?,
onNavigationError: ((Error?) -> Void)?,
allowedDomains: [String]? = nil,
settings: AsyncHeadlessWebViewSettings = AsyncHeadlessWebViewSettings()) {
self.parent = parent
Expand All @@ -60,6 +62,7 @@ final class HeadlessWebViewCoordinator: NSObject {
self.onURLChange = onURLChange
self.onCanGoBack = onCanGoBack
self.onCanGoForward = onCanGoForward
self.onNavigationError = onNavigationError
self.onContentType = onContentType
self.settings = settings
}
Expand Down Expand Up @@ -106,6 +109,7 @@ final class HeadlessWebViewCoordinator: NSObject {
onCanGoBack = nil
onCanGoForward = nil
onContentType = nil
onNavigationError = nil
}

}
Expand All @@ -128,6 +132,7 @@ extension HeadlessWebViewCoordinator: WKNavigationDelegate {
}

func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
onNavigationError?(nil)
if let url = webView.url, url != lastURL {
onURLChange?(url)
lastURL = url
Expand Down Expand Up @@ -182,8 +187,12 @@ extension HeadlessWebViewCoordinator: WKNavigationDelegate {
decisionHandler(.allow)
}

func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: any Error) {
onNavigationError?(error)
}

func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
// NOOP
onNavigationError?(error)
}

// Javascript Confirm dialogs Delegate
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,13 @@ final class IdentityTheftRestorationPagesFeature: Subfeature, ObservableObject {
return nil
}
}

func getAccessToken(params: Any, original: WKScriptMessage) async throws -> Encodable? {
let authToken = AccountManager().authToken ?? ""
return [Constants.token: authToken]
if let accessToken = AccountManager().accessToken {
return [Constants.token: accessToken]
} else {
return [String: String]()
}
}

deinit {
Expand Down
12 changes: 12 additions & 0 deletions DuckDuckGo/Subscription/ViewModel/SubscriptionEmailViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ final class SubscriptionEmailViewModel: ObservableObject {
@Published var activateSubscription = false
@Published var managingSubscriptionEmail = false
@Published var transactionError: SubscriptionRestoreError?
@Published var navigationError: Bool = false
@Published var shouldDisplayInactiveError: Bool = false
var webViewModel: AsyncHeadlessWebViewViewModel

Expand Down Expand Up @@ -101,6 +102,17 @@ final class SubscriptionEmailViewModel: ObservableObject {
}
}
.store(in: &cancellables)

webViewModel.$navigationError
.receive(on: DispatchQueue.main)
.sink { [weak self] error in
guard let strongSelf = self else { return }
DispatchQueue.main.async {
strongSelf.navigationError = error != nil ? true : false
}

}
.store(in: &cancellables)
}

private func handleTransactionError(error: SubscriptionPagesUseSubscriptionFeature.UseSubscriptionError) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,10 +224,24 @@ final class SubscriptionFlowViewModel: ObservableObject {
}
.store(in: &cancellables)

webViewModel.$navigationError
.receive(on: DispatchQueue.main)
.sink { [weak self] error in
guard let strongSelf = self else { return }
DispatchQueue.main.async {
strongSelf.transactionError = error != nil ? .generalError : nil
}

}
.store(in: &cancellables)

canGoBackCancellable = webViewModel.$canGoBack
.receive(on: DispatchQueue.main)
.sink { [weak self] value in
self?.canNavigateBack = value
guard let strongSelf = self else { return }

let shouldNavigateBack = value && (strongSelf.webViewModel.url?.lastPathComponent != URL.subscriptionBaseURL.lastPathComponent)
strongSelf.canNavigateBack = shouldNavigateBack
}
}

Expand All @@ -242,6 +256,12 @@ final class SubscriptionFlowViewModel: ObservableObject {
canNavigateBack = false
}

private func urlRemovingQueryParams(_ url: URL) -> URL? {
var urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: false)
urlComponents?.query = nil // Remove the query string
return urlComponents?.url
}

func initializeViewData() async {
await self.setupTransactionObserver()
await self .setupWebViewObservers()
Expand All @@ -257,6 +277,7 @@ final class SubscriptionFlowViewModel: ObservableObject {
userTappedRestoreButton = false
shouldShowNavigationBar = false
selectedFeature = nil
transactionError = nil
canNavigateBack = false
shouldDismissView = true
subFeature.cleanup()
Expand Down
15 changes: 14 additions & 1 deletion DuckDuckGo/Subscription/ViewModel/SubscriptionITPViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ final class SubscriptionITPViewModel: ObservableObject {
@Published var isDownloadableContent: Bool = false
@Published var activityItems: [Any] = []
@Published var attachmentURL: URL?
@Published var navigationError: Bool = false
var webViewModel: AsyncHeadlessWebViewViewModel

@Published var shouldNavigateToExternalURL: URL?
Expand Down Expand Up @@ -81,9 +82,20 @@ final class SubscriptionITPViewModel: ObservableObject {
settings: webViewSettings)
}

// Observe transaction status
// swiftlint:disable function_body_length
private func setupSubscribers() async {

webViewModel.$navigationError
.receive(on: DispatchQueue.main)
.sink { [weak self] error in
guard let strongSelf = self else { return }
DispatchQueue.main.async {
strongSelf.navigationError = error != nil ? true : false
}

}
.store(in: &cancellables)

webViewModel.$scrollPosition
.receive(on: DispatchQueue.main)
.throttle(for: .milliseconds(100), scheduler: DispatchQueue.main, latest: true)
Expand Down Expand Up @@ -134,6 +146,7 @@ final class SubscriptionITPViewModel: ObservableObject {
self?.canNavigateBack = value
}
}
// swiftlint:enable function_body_length

func initializeView() {
webViewModel.navigationCoordinator.navigateTo(url: manageITPURL )
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ final class SubscriptionRestoreViewModel: ObservableObject {
private func handleRestoreError(error: SubscriptionPagesUseSubscriptionFeature.UseSubscriptionError) {
switch error {
case .failedToRestorePastPurchase:
activationResult = .notFound
activationResult = .error
case .subscriptionExpired:
activationResult = .expired
case .subscriptionNotFound:
Expand Down
9 changes: 9 additions & 0 deletions DuckDuckGo/Subscription/Views/SubscriptionEmailView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,15 @@ struct SubscriptionEmailView: View {
)
}

.alert(isPresented: $viewModel.navigationError) {
Alert(
title: Text(UserText.subscriptionBackendErrorTitle),
message: Text(UserText.subscriptionBackendErrorMessage),
dismissButton: .cancel(Text(UserText.subscriptionBackendErrorButton)) {
dismiss()
})
}

.onAppear {
viewModel.loadURL()
}
Expand Down
Loading
Loading