Skip to content

Commit

Permalink
15. Subscription sign-out notification observers and Design Feedback (#…
Browse files Browse the repository at this point in the history
…2528)

Task/Issue URL: https://app.asana.com/0/414235014887631/1206458412095677/f

Description:
- Design review feedback updates (copy, layout fixes, etc)
- Removes debug flags on alpha builds (cc @graeme)
- Add notification observers for signOut on notifications
  • Loading branch information
afterxleep authored Mar 1, 2024
1 parent fb2b820 commit d761d61
Show file tree
Hide file tree
Showing 9 changed files with 109 additions and 61 deletions.
8 changes: 3 additions & 5 deletions DuckDuckGo.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -2467,6 +2467,7 @@
D69FBF752B28BE3600B505F1 /* SettingsSubscriptionView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SettingsSubscriptionView.swift; sourceTree = "<group>"; };
D6BFCB5E2B7524AA0051FF81 /* SubscriptionPIRView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionPIRView.swift; sourceTree = "<group>"; };
D6BFCB602B7525160051FF81 /* SubscriptionPIRViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SubscriptionPIRViewModel.swift; sourceTree = "<group>"; };
D6CF463D2B9252DB000782AD /* BrowserServicesKit */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = BrowserServicesKit; path = ../BrowserServicesKit; sourceTree = "<group>"; };
D6D95CE02B6D52DA00960317 /* RootPresentationMode.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RootPresentationMode.swift; sourceTree = "<group>"; };
D6D95CE22B6D9F8800960317 /* AsyncHeadlessWebViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AsyncHeadlessWebViewModel.swift; sourceTree = "<group>"; };
D6E0C1822B7A2B1E00D5E1E9 /* DesktopDownloadView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DesktopDownloadView.swift; sourceTree = "<group>"; };
Expand Down Expand Up @@ -3710,6 +3711,7 @@
84E341891E2F7EFB00BDBA6F = {
isa = PBXGroup;
children = (
D6CF463D2B9252DB000782AD /* BrowserServicesKit */,
EE3B98EB2A963515002F63A0 /* WidgetsExtensionAlpha.entitlements */,
6FB030C7234331B400A10DB9 /* Configuration.xcconfig */,
EEB8FDB92A990AEE00EBEDCF /* Configuration-Alpha.xcconfig */,
Expand Down Expand Up @@ -9365,10 +9367,6 @@
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
Expand All @@ -9380,7 +9378,7 @@
ONLY_ACTIVE_ARCH = YES;
OTHER_LDFLAGS = "-ld_classic";
SDKROOT = iphoneos;
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG NETWORK_PROTECTION ALPHA SUBSCRIPTION";
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "NETWORK_PROTECTION ALPHA SUBSCRIPTION";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
TARGETED_DEVICE_FAMILY = "1,2";
VALID_ARCHS = "$(ARCHS_STANDARD_64_BIT)";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,6 @@
"version" : "3.0.0"
}
},
{
"identity" : "browserserviceskit",
"kind" : "remoteSourceControl",
"location" : "https://github.com/DuckDuckGo/BrowserServicesKit",
"state" : {
"revision" : "045a8782c3dbbf79fc088b38120dea1efadc13e1",
"version" : "114.1.0"
}
},
{
"identity" : "cocoaasyncsocket",
"kind" : "remoteSourceControl",
Expand Down
1 change: 0 additions & 1 deletion DuckDuckGo/SettingsSubscriptionView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ struct SettingsSubscriptionView: View {
private var manageSubscriptionView: some View {
Text(UserText.settingsPProManageSubscription)
.daxBodyRegular()
.foregroundColor(Color.init(designSystemColor: .accent))
}

private var purchaseSubscriptionView: some View {
Expand Down
27 changes: 21 additions & 6 deletions DuckDuckGo/SettingsViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,7 @@ final class SettingsViewModel: ObservableObject {
private let voiceSearchHelper: VoiceSearchHelperProtocol
#if SUBSCRIPTION
private var accountManager: AccountManager
private var signOutObserver: Any?
#endif


Expand Down Expand Up @@ -215,7 +216,14 @@ final class SettingsViewModel: ObservableObject {
self.accountManager = accountManager
self.voiceSearchHelper = voiceSearchHelper
self.onAppearNavigationTarget = navigateOnAppearDestination

setupNotificationObservers()
}

deinit {
signOutObserver = nil
}

#else
// MARK: Default Init
init(state: SettingsState? = nil,
Expand All @@ -233,7 +241,7 @@ final class SettingsViewModel: ObservableObject {
// MARK: Private methods
extension SettingsViewModel {

// This manual (re)initialzation will go away once appSettings and
// This manual (re)initialization will go away once appSettings and
// other dependencies are observable (Such as AppIcon and netP)
// and we can use subscribers (Currently called from the view onAppear)
private func initState() {
Expand Down Expand Up @@ -339,12 +347,8 @@ extension SettingsViewModel {

// Fetch available subscriptions from the backend (or sign out)
switch await SubscriptionService.getSubscriptionDetails(token: token) {
case .success(let response) where !response.isSubscriptionActive:

// Account is active but there's not a valid subscription
signOutUser()

case .success(let response):
case .success(let response) where response.isSubscriptionActive:

// Cache Subscription state
cacheSubscriptionState(active: true)
Expand All @@ -365,6 +369,7 @@ extension SettingsViewModel {
}

default:
// Account is active but there's not a valid subscription / entitlements
signOutUser()
}
}
Expand All @@ -390,6 +395,16 @@ extension SettingsViewModel {
self?.state.subscription.canPurchase = !products.isEmpty
}.store(in: &cancellables)
}

private func setupNotificationObservers() {
signOutObserver = NotificationCenter.default.addObserver(forName: .accountDidSignOut, object: nil, queue: .main) { [weak self] _ in
if #available(iOS 15.0, *) {
guard let strongSelf = self else { return }
Task { await strongSelf.setupSubscriptionEnvironment() }
}
}
}

#endif

#if NETWORK_PROTECTION
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,8 @@ final class SubscriptionSettingsViewModel: ObservableObject {

let accountManager: AccountManager
private var subscriptionUpdateTimer: Timer?
private var signOutObserver: Any?

@Published var subscriptionDetails: String = ""
@Published var subscriptionType: String = ""
@Published var shouldDisplayRemovalNotice: Bool = false
Expand All @@ -45,6 +47,7 @@ final class SubscriptionSettingsViewModel: ObservableObject {
self.accountManager = accountManager
Task { await fetchAndUpdateSubscriptionDetails() }
setupSubscriptionUpdater()
setupNotificationObservers()
}

private var dateFormatter: DateFormatter = {
Expand Down Expand Up @@ -76,6 +79,14 @@ final class SubscriptionSettingsViewModel: ObservableObject {
}
}

private func setupNotificationObservers() {
signOutObserver = NotificationCenter.default.addObserver(forName: .accountDidSignOut, object: nil, queue: .main) { [weak self] _ in
DispatchQueue.main.async {
self?.shouldDismissView = true
}
}
}

private func setupSubscriptionUpdater() {
subscriptionUpdateTimer = Timer.scheduledTimer(withTimeInterval: 10.0, repeats: true) { [weak self] _ in
guard let strongSelf = self else { return }
Expand All @@ -94,7 +105,9 @@ final class SubscriptionSettingsViewModel: ObservableObject {

func removeSubscription() {
AccountManager().signOut()
ActionMessageView.present(message: UserText.subscriptionRemovalConfirmation)
let messageView = ActionMessageView()
ActionMessageView.present(message: UserText.subscriptionRemovalConfirmation,
presentationLocation: .withoutBottomBar)
}

func manageSubscription() {
Expand All @@ -120,6 +133,7 @@ final class SubscriptionSettingsViewModel: ObservableObject {

deinit {
subscriptionUpdateTimer?.invalidate()
signOutObserver = nil
}


Expand Down
93 changes: 60 additions & 33 deletions DuckDuckGo/Subscription/Views/SubscriptionRestoreView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -37,27 +37,38 @@ struct SubscriptionRestoreView: View {
static let appleIDIcon = "Platform-Apple-16"
static let emailIcon = "Email-16"
static let headerLineSpacing = 10.0
static let viewStackSpacing = 20.0
static let footerLineSpacing = 7.0
static let openIndicator = "chevron.up"
static let closedIndicator = "chevron.down"
static let cornerRadius = 12.0
static let buttonCornerRadius = 8.0
static let buttonInsets = EdgeInsets(top: 10.0, leading: 16.0, bottom: 10.0, trailing: 16.0)
static let cellLineSpacing = 12.0
static let cellPadding = 8.0
static let headerPadding = EdgeInsets(top: 16.0, leading: 16.0, bottom: 0, trailing: 16.0)
static let cellPadding = 20.0
static let headerPadding = EdgeInsets(top: 16.0, leading: 30.0, bottom: 0, trailing: 30.0)
static let viewPadding: CGFloat = 18.0
static let listPadding = EdgeInsets(top: 0, leading: 30, bottom: 0, trailing: 30)
static let borderWidth: CGFloat = 1.0
}

var body: some View {
ZStack {
VStack {
VStack(spacing: Constants.viewStackSpacing) {

// Email Activation View Hidden link
NavigationLink(destination: SubscriptionEmailView(isAddingDevice: viewModel.isAddingDevice), isActive: $isActive) {
EmptyView()
}.isDetailLink(false)

headerView
listView
}
optionsView
footerView

Spacer()
}.background(Color(designSystemColor: .background))


.navigationTitle(viewModel.isAddingDevice ? UserText.subscriptionAddDeviceTitle : UserText.subscriptionActivate)
.navigationBarBackButtonHidden(viewModel.transactionStatus != .idle)
.applyInsetGroupedListStyle()
Expand Down Expand Up @@ -95,7 +106,7 @@ struct SubscriptionRestoreView: View {
HStack {
Image(icon)
Text(text)
.daxBodyRegular()
.daxSubheadSemibold()
.foregroundColor(Color(designSystemColor: .textPrimary))
}
)
Expand Down Expand Up @@ -143,7 +154,7 @@ struct SubscriptionRestoreView: View {
})
.background(Color(designSystemColor: .accent))
.cornerRadius(Constants.buttonCornerRadius)
.padding(.top, Constants.cellPadding)
.padding(.top, Constants.cellLineSpacing)
)
}

Expand All @@ -162,22 +173,23 @@ struct SubscriptionRestoreView: View {

private var headerView: some View {
VStack(spacing: Constants.headerLineSpacing) {
Image(Constants.heroImage)
Image(Constants.heroImage).padding(.bottom, Constants.cellLineSpacing)
Text(viewModel.isAddingDevice ? UserText.subscriptionAddDeviceHeaderTitle : UserText.subscriptionActivateTitle)
.daxHeadline()
.multilineTextAlignment(.center)
.foregroundColor(Color(designSystemColor: .textPrimary))
Text(viewModel.isAddingDevice ? UserText.subscriptionAddDeviceDescription : UserText.subscriptionActivateDescription)
Text(viewModel.isAddingDevice ? UserText.subscriptionAddDeviceDescription : UserText.subscriptionActivateHeaderDescription)
.daxFootnoteRegular()
.foregroundColor(Color(designSystemColor: .textSecondary))
.multilineTextAlignment(.center)
}.padding(Constants.headerPadding)
}
.padding(Constants.headerPadding)
}

@ViewBuilder
private var footerView: some View {
if !viewModel.isAddingDevice {
VStack(alignment: .leading) {
VStack(alignment: .leading, spacing: Constants.footerLineSpacing) {
Text(UserText.subscriptionActivateDescription)
.daxFootnoteRegular()
.foregroundColor(Color(designSystemColor: .textSecondary))
Expand All @@ -188,32 +200,38 @@ struct SubscriptionRestoreView: View {
.daxFootnoteSemibold()
.foregroundColor(Color(designSystemColor: .accent))
})
}.padding(.top, Constants.headerLineSpacing)
}
.padding(Constants.listPadding)
}
}

private var listView: some View {
List {
Section(footer: footerView) {
ForEach(Array(zip(listItems.indices, listItems)), id: \.1.id) { _, item in
VStack(alignment: .leading, spacing: Constants.cellLineSpacing) {
HStack {
item.content
Spacer()
if listItems.count > 1 {
Image(systemName: expandedItemId == item.id ? Constants.openIndicator : Constants.closedIndicator)
.foregroundColor(Color(designSystemColor: .textPrimary))
}
}
.contentShape(Rectangle())
.onTapGesture {
expandedItemId = expandedItemId == item.id ? 0 : item.id
}
if expandedItemId == item.id {
item.expandedContent
private var optionsView: some View {
VStack {
ForEach(Array(zip(listItems.indices, listItems)), id: \.1.id) { _, item in
VStack(alignment: .leading, spacing: Constants.cellLineSpacing) {
HStack {
item.content
Spacer()
if listItems.count > 1 {
Image(systemName: expandedItemId == item.id ? Constants.openIndicator : Constants.closedIndicator)
.foregroundColor(Color(designSystemColor: .textPrimary))
}
}.padding(Constants.cellPadding)
}
.contentShape(Rectangle())
.onTapGesture {
expandedItemId = expandedItemId == item.id ? 0 : item.id
}
if expandedItemId == item.id {
item.expandedContent
}
}
.padding(Constants.cellPadding)
.background(Color(designSystemColor: .panel))
.overlay(
RoundedRectangle(cornerRadius: Constants.cornerRadius)
.stroke(Color(designSystemColor: .lines), lineWidth: Constants.borderWidth)
)
.padding(Constants.listPadding)
}
}
}
Expand Down Expand Up @@ -264,5 +282,14 @@ struct SubscriptionRestoreView: View {
let content: AnyView
let expandedContent: AnyView
}

}

@available(iOS 15.0, *)
struct SubscriptionRestoreView_Previews: PreviewProvider {
static var previews: some View {
SubscriptionRestoreView()
.previewDevice("iPhone 12")
}
}
#endif
8 changes: 4 additions & 4 deletions DuckDuckGo/Subscription/Views/SubscriptionSettingsView.swift
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ struct SubscriptionSettingsView: View {
@StateObject var sceneEnvironment = SceneEnvironment()

@ViewBuilder
private var listView: some View {
private var optionsView: some View {
List {
Section {
VStack(alignment: .center, spacing: 7) {
Expand All @@ -54,6 +54,7 @@ struct SubscriptionSettingsView: View {
SettingsCustomCell(content: {
Text(UserText.subscriptionChangePlan)
.daxBodyRegular()
.foregroundColor(Color.init(designSystemColor: .accent))
},
action: { Task { viewModel.manageSubscription() } },
isButton: true)
Expand All @@ -65,7 +66,6 @@ struct SubscriptionSettingsView: View {
SettingsCustomCell(content: {
Text(UserText.subscriptionAddDeviceButton)
.daxBodyRegular()
.foregroundColor(Color.init(designSystemColor: .accent))
})
}

Expand Down Expand Up @@ -119,10 +119,10 @@ struct SubscriptionSettingsView: View {
var body: some View {
Group {
if #available(iOS 16.0, *) {
listView
optionsView
.scrollDisabled(true)
} else {
listView
optionsView
}
}
.navigationBarTitleDisplayMode(.inline)
Expand Down
Loading

0 comments on commit d761d61

Please sign in to comment.