From 4f7977817fed59f884e1b556a82be3df52dbb004 Mon Sep 17 00:00:00 2001 From: Kyle Hickinson Date: Mon, 4 Dec 2023 10:01:29 -0500 Subject: [PATCH] Fix #8371: Update Rewards icon properly when first enabling it (#8512) Also fixes a race condition for first time rewards users where the rewards service hasn't started before they tap the switch to turn it on would cause a UI bug --- .../Panel/BraveRewardsViewController.swift | 38 +++++++++++-------- .../Browser/BrowserViewController.swift | 2 +- .../BrowserViewController/BVC+Rewards.swift | 4 +- .../Brave/Frontend/Rewards/BraveRewards.swift | 17 +++++---- 4 files changed, 34 insertions(+), 27 deletions(-) diff --git a/Sources/Brave/Frontend/Brave Rewards/Panel/BraveRewardsViewController.swift b/Sources/Brave/Frontend/Brave Rewards/Panel/BraveRewardsViewController.swift index 92185985365..5b741dc7d17 100644 --- a/Sources/Brave/Frontend/Brave Rewards/Panel/BraveRewardsViewController.swift +++ b/Sources/Brave/Frontend/Brave Rewards/Panel/BraveRewardsViewController.swift @@ -95,14 +95,18 @@ class BraveRewardsViewController: UIViewController, PopoverContentComponent { rewardsView.publisherView.hostLabel.text = tab.url?.baseDomain } } + + private let rewardsServiceStartGroup = DispatchGroup() override func viewDidLoad() { super.viewDidLoad() rewardsView.rewardsToggle.isOn = rewards.isEnabled + rewardsServiceStartGroup.enter() rewards.startRewardsService { [weak self] in guard let self = self else { return } + defer { self.rewardsServiceStartGroup.leave() } if let rewardsAPI = self.rewards.rewardsAPI { let observer = RewardsObserver(rewardsAPI: rewardsAPI) rewardsAPI.add(observer) @@ -139,22 +143,24 @@ class BraveRewardsViewController: UIViewController, PopoverContentComponent { private var isCreatingWallet: Bool = false @objc private func rewardsToggleValueChanged() { - rewardsView.rewardsToggle.isUserInteractionEnabled = false - DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in - self?.rewardsView.rewardsToggle.isUserInteractionEnabled = true - } - let isOn = rewardsView.rewardsToggle.isOn - rewards.isEnabled = isOn - rewardsView.subtitleLabel.text = isOn ? Strings.Rewards.enabledBody : Strings.Rewards.disabledBody - if rewardsView.rewardsToggle.isOn { - rewardsView.statusView.setVisibleStatus(status: supportedListCount > 0 ? .rewardsOn : .rewardsOnNoCount) - } else { - rewardsView.statusView.setVisibleStatus(status: .rewardsOff) - } - if publisher != nil { - UIView.animate(withDuration: 0.15) { - self.rewardsView.publisherView.isHidden = !self.rewardsView.rewardsToggle.isOn - self.rewardsView.publisherView.alpha = self.rewardsView.rewardsToggle.isOn ? 1.0 : 0.0 + rewardsServiceStartGroup.notify(queue: .main) { [self] in + rewardsView.rewardsToggle.isUserInteractionEnabled = false + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { [weak self] in + self?.rewardsView.rewardsToggle.isUserInteractionEnabled = true + } + let isOn = rewardsView.rewardsToggle.isOn + rewards.isEnabled = isOn + rewardsView.subtitleLabel.text = isOn ? Strings.Rewards.enabledBody : Strings.Rewards.disabledBody + if rewardsView.rewardsToggle.isOn { + rewardsView.statusView.setVisibleStatus(status: supportedListCount > 0 ? .rewardsOn : .rewardsOnNoCount) + } else { + rewardsView.statusView.setVisibleStatus(status: .rewardsOff) + } + if publisher != nil { + UIView.animate(withDuration: 0.15) { + self.rewardsView.publisherView.isHidden = !self.rewardsView.rewardsToggle.isOn + self.rewardsView.publisherView.alpha = self.rewardsView.rewardsToggle.isOn ? 1.0 : 0.0 + } } } } diff --git a/Sources/Brave/Frontend/Browser/BrowserViewController.swift b/Sources/Brave/Frontend/Browser/BrowserViewController.swift index e922adac645..ca51bcb2d60 100644 --- a/Sources/Brave/Frontend/Browser/BrowserViewController.swift +++ b/Sources/Brave/Frontend/Browser/BrowserViewController.swift @@ -473,7 +473,7 @@ public class BrowserViewController: UIViewController { }) } - rewardsEnabledObserveration = rewards.observe(\.isEnabled, options: [.new]) { [weak self] _, _ in + rewardsEnabledObserveration = rewards.ads.observe(\.isEnabled, options: [.new]) { [weak self] _, _ in guard let self = self else { return } self.updateRewardsButtonState() self.setupAdsNotificationHandler() diff --git a/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+Rewards.swift b/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+Rewards.swift index adbfa912038..1ed8227ce83 100644 --- a/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+Rewards.swift +++ b/Sources/Brave/Frontend/Browser/BrowserViewController/BVC+Rewards.swift @@ -26,7 +26,7 @@ extension BrowserViewController { return } self.topToolbar.rewardsButton.isHidden = Preferences.Rewards.hideRewardsIcon.value || privateBrowsingManager.isPrivateBrowsing - self.topToolbar.rewardsButton.iconState = Preferences.Rewards.rewardsToggledOnce.value ? (rewards.isEnabled || rewards.isCreatingWallet ? .enabled : .disabled) : .initial + self.topToolbar.rewardsButton.iconState = rewards.isEnabled || rewards.isTurningOnRewards ? .enabled : (Preferences.Rewards.rewardsToggledOnce.value ? .disabled : .initial) } func showBraveRewardsPanel() { @@ -44,7 +44,7 @@ extension BrowserViewController { Preferences.FullScreenCallout.rewardsCalloutCompleted.value = true present(controller, animated: true) - topToolbar.rewardsButton.iconState = Preferences.Rewards.rewardsToggledOnce.value ? (rewards.isEnabled || rewards.isCreatingWallet ? .enabled : .disabled) : .initial + topToolbar.rewardsButton.iconState = Preferences.Rewards.rewardsToggledOnce.value ? (rewards.isEnabled || rewards.isTurningOnRewards ? .enabled : .disabled) : .initial return } diff --git a/Sources/Brave/Frontend/Rewards/BraveRewards.swift b/Sources/Brave/Frontend/Rewards/BraveRewards.swift index 5d308346419..b43df547a9e 100644 --- a/Sources/Brave/Frontend/Rewards/BraveRewards.swift +++ b/Sources/Brave/Frontend/Rewards/BraveRewards.swift @@ -85,12 +85,14 @@ public class BraveRewards: NSObject { if let toggleAds { self.ads.isEnabled = toggleAds } + self.isTurningOnRewards = false return } self.ads.initialize(walletInfo: walletInfo) { success in if success, let toggleAds { self.ads.isEnabled = toggleAds } + self.isTurningOnRewards = false } } } @@ -118,10 +120,9 @@ public class BraveRewards: NSObject { ads.isEnabled } set { - willChangeValue(for: \.isEnabled) - Preferences.Rewards.rewardsToggledOnce.value = true createWalletIfNeeded { [weak self] in guard let self = self else { return } + Preferences.Rewards.rewardsToggledOnce.value = true self.rewardsAPI?.setAutoContributeEnabled(newValue) let wasEnabled = self.ads.isEnabled if !wasEnabled && newValue { @@ -132,25 +133,25 @@ public class BraveRewards: NSObject { if !newValue { self.ads.isEnabled = newValue self.proposeAdsShutdown() + self.isTurningOnRewards = false } else { self.fetchWalletAndInitializeAds(toggleAds: true) } - self.didChangeValue(for: \.isEnabled) } } } - private(set) var isCreatingWallet: Bool = false + private(set) var isTurningOnRewards: Bool = false + private func createWalletIfNeeded(_ completion: (() -> Void)? = nil) { - if isCreatingWallet { + if isTurningOnRewards { // completion block will be hit by previous call return } - isCreatingWallet = true + isTurningOnRewards = true startRewardsService { guard let rewardsAPI = self.rewardsAPI else { return } - rewardsAPI.createWalletAndFetchDetails { [weak self] success in - self?.isCreatingWallet = false + rewardsAPI.createWalletAndFetchDetails { success in completion?() } }