Skip to content

Commit

Permalink
Bug fixes for refreshing and updating subscription state (#2473)
Browse files Browse the repository at this point in the history
Task/Issue URL:
https://app.asana.com/0/1199230911884351/1206896697354395/f

**Description**:
- when closing DBP tab on subscription account sign out make it on main
thread
- update cached subscription and entitlements on app launch
- hide "View Plans" button on expired subscription state as it is not
fully handled
- more coherent refresh of subscription settings


---
###### Internal references:
[Pull Request Review
Checklist](https://app.asana.com/0/1202500774821704/1203764234894239/f)
[Software Engineering
Expectations](https://app.asana.com/0/59792373528535/199064865822552)
[Technical Design
Template](https://app.asana.com/0/59792373528535/184709971311943)
[Pull Request
Documentation](https://app.asana.com/0/1202500774821704/1204012835277482/f)
  • Loading branch information
miasma13 authored Mar 21, 2024
1 parent 3034d50 commit e7d0897
Show file tree
Hide file tree
Showing 4 changed files with 53 additions and 72 deletions.
15 changes: 3 additions & 12 deletions DuckDuckGo/Application/AppDelegate.swift
Original file line number Diff line number Diff line change
Expand Up @@ -261,19 +261,10 @@ final class AppDelegate: NSObject, NSApplicationDelegate, FileDownloadManagerDel

Task {
let accountManager = AccountManager()
do {
try accountManager.migrateAccessTokenToNewStore()
} catch {
if let error = error as? AccountManager.MigrationError {
switch error {
case AccountManager.MigrationError.migrationFailed:
os_log(.default, log: .subscription, "Access token migration failed")
case AccountManager.MigrationError.noMigrationNeeded:
os_log(.default, log: .subscription, "No access token migration needed")
}
}
if let token = accountManager.accessToken {
_ = await SubscriptionService.getSubscription(accessToken: token, cachePolicy: .reloadIgnoringLocalCacheData)
_ = await accountManager.fetchEntitlements(cachePolicy: .reloadIgnoringLocalCacheData)
}
await accountManager.checkSubscriptionState()
}
#endif

Expand Down
4 changes: 3 additions & 1 deletion DuckDuckGo/Tab/View/BrowserTabViewController.swift
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,9 @@ final class BrowserTabViewController: NSViewController {
#if DBP
@objc
private func onDBPFeatureDisabled(_ notification: Notification) {
tabCollectionViewModel.removeAll(with: .dataBrokerProtection)
Task { @MainActor in
tabCollectionViewModel.removeAll(with: .dataBrokerProtection)
}
}

@objc
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,35 +95,10 @@ public final class PreferencesSubscriptionModel: ObservableObject {

self.isUserAuthenticated = accountManager.isUserAuthenticated

if let token = accountManager.accessToken {
if accountManager.isUserAuthenticated {
Task {
let subscriptionResult = await SubscriptionService.getSubscription(accessToken: token, cachePolicy: .returnCacheDataElseLoad)
if case .success(let subscription) = subscriptionResult {
self.updateDescription(for: subscription.expiresOrRenewsAt, status: subscription.status, period: subscription.billingPeriod)
self.subscriptionPlatform = subscription.platform
self.subscriptionStatus = subscription.status
}

switch await self.accountManager.hasEntitlement(for: .networkProtection, cachePolicy: .returnCacheDataElseLoad) {
case let .success(result):
self.hasAccessToVPN = result
case .failure:
self.hasAccessToVPN = false
}

switch await self.accountManager.hasEntitlement(for: .dataBrokerProtection, cachePolicy: .returnCacheDataElseLoad) {
case let .success(result):
self.hasAccessToDBP = result
case .failure:
self.hasAccessToDBP = false
}

switch await self.accountManager.hasEntitlement(for: .identityTheftRestoration, cachePolicy: .returnCacheDataElseLoad) {
case let .success(result):
self.hasAccessToITR = result
case .failure:
self.hasAccessToITR = false
}
await self.updateSubscription(with: .returnCacheDataElseLoad)
await self.updateAllEntitlement(with: .returnCacheDataElseLoad)
}
}

Expand Down Expand Up @@ -264,50 +239,62 @@ public final class PreferencesSubscriptionModel: ObservableObject {

@MainActor
func fetchAndUpdateSubscriptionDetails() {
self.isUserAuthenticated = accountManager.isUserAuthenticated

guard fetchSubscriptionDetailsTask == nil else { return }

fetchSubscriptionDetailsTask = Task { [weak self] in
defer {
self?.fetchSubscriptionDetailsTask = nil
}

guard let token = self?.accountManager.accessToken else { return }
await self?.updateSubscription(with: .reloadIgnoringLocalCacheData)
await self?.updateAllEntitlement(with: .reloadIgnoringLocalCacheData)
}
}

let subscriptionResult = await SubscriptionService.getSubscription(accessToken: token, cachePolicy: .reloadIgnoringLocalCacheData)
@MainActor
private func updateSubscription(with cachePolicy: SubscriptionService.CachePolicy) async {
guard let token = accountManager.accessToken else {
SubscriptionService.signOut()
return
}

if case .success(let subscription) = subscriptionResult {
self?.updateDescription(for: subscription.expiresOrRenewsAt, status: subscription.status, period: subscription.billingPeriod)
self?.subscriptionPlatform = subscription.platform
self?.subscriptionStatus = subscription.status
} else {
self?.accountManager.signOut()
}
switch await SubscriptionService.getSubscription(accessToken: token, cachePolicy: cachePolicy) {
case .success(let subscription):
updateDescription(for: subscription.expiresOrRenewsAt, status: subscription.status, period: subscription.billingPeriod)
subscriptionPlatform = subscription.platform
subscriptionStatus = subscription.status
case .failure:
break
}
}

if let self {
switch await self.accountManager.hasEntitlement(for: .networkProtection) {
case let .success(result):
hasAccessToVPN = result
case .failure:
hasAccessToVPN = false
}
@MainActor
private func updateAllEntitlement(with cachePolicy: AccountManager.CachePolicy) async {
switch await self.accountManager.hasEntitlement(for: .networkProtection, cachePolicy: cachePolicy) {
case let .success(result):
hasAccessToVPN = result
case .failure:
hasAccessToVPN = false
}

switch await self.accountManager.hasEntitlement(for: .dataBrokerProtection) {
case let .success(result):
hasAccessToDBP = result
case .failure:
hasAccessToDBP = false
}
switch await self.accountManager.hasEntitlement(for: .dataBrokerProtection, cachePolicy: cachePolicy) {
case let .success(result):
hasAccessToDBP = result
case .failure:
hasAccessToDBP = false
}

switch await self.accountManager.hasEntitlement(for: .identityTheftRestoration) {
case let .success(result):
hasAccessToITR = result
case .failure:
hasAccessToITR = false
}
}
switch await self.accountManager.hasEntitlement(for: .identityTheftRestoration, cachePolicy: cachePolicy) {
case let .success(result):
hasAccessToITR = result
case .failure:
hasAccessToITR = false
}
}

@MainActor
func updateDescription(for date: Date, status: Subscription.Status, period: Subscription.BillingPeriod) {

let formattedDate = dateFormatter.string(from: date)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -185,8 +185,9 @@ public struct PreferencesSubscriptionView: View {
TextMenuItemHeader(model.subscriptionDetails ?? UserText.preferencesSubscriptionInactiveHeader)
TextMenuItemCaption(UserText.preferencesSubscriptionExpiredCaption)
} buttons: {
Button(UserText.viewPlansButtonTitle) { model.purchaseAction() }
.buttonStyle(DefaultActionButtonStyle(enabled: true))
// We need to improve re-purchase flow
/* Button(UserText.viewPlansButtonTitle) { model.purchaseAction() }
.buttonStyle(DefaultActionButtonStyle(enabled: true)) */
Menu {
Button(UserText.removeFromThisDeviceButton, action: {
model.userEventHandler(.removeSubscriptionClick)
Expand Down

0 comments on commit e7d0897

Please sign in to comment.