From 2ee257bf7527d4b3f8b8994127004c7399521b6c Mon Sep 17 00:00:00 2001 From: Kyle Hickinson Date: Mon, 23 Oct 2023 12:18:02 -0400 Subject: [PATCH] Fix #8211: Remove the dislike swipe action on ads (#8304) This also cleans up and removes the unused open swipe action and accompanying pan gesture --- .../Brave Rewards/Ads/Contents.json | 6 -- .../dislike-ad-icon.imageset/Contents.json | 22 ----- .../thumbsdown@2x.png | Bin 1078 -> 0 bytes .../thumbsdown@3x.png | Bin 1637 -> 0 bytes .../Brave Rewards/RewardsNotification.swift | 80 +----------------- .../Frontend/Brave Rewards/Ads/AdView.swift | 54 ------------ .../Ads/AdsNotificationHandler.swift | 3 - 7 files changed, 1 insertion(+), 164 deletions(-) delete mode 100644 Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/Contents.json delete mode 100644 Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/dislike-ad-icon.imageset/Contents.json delete mode 100644 Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/dislike-ad-icon.imageset/thumbsdown@2x.png delete mode 100644 Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/dislike-ad-icon.imageset/thumbsdown@3x.png diff --git a/Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/Contents.json b/Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/Contents.json deleted file mode 100644 index 73c00596a7f..00000000000 --- a/Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/Contents.json +++ /dev/null @@ -1,6 +0,0 @@ -{ - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/dislike-ad-icon.imageset/Contents.json b/Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/dislike-ad-icon.imageset/Contents.json deleted file mode 100644 index 89f958983ac..00000000000 --- a/Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/dislike-ad-icon.imageset/Contents.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "images" : [ - { - "idiom" : "universal", - "scale" : "1x" - }, - { - "filename" : "thumbsdown@2x.png", - "idiom" : "universal", - "scale" : "2x" - }, - { - "filename" : "thumbsdown@3x.png", - "idiom" : "universal", - "scale" : "3x" - } - ], - "info" : { - "author" : "xcode", - "version" : 1 - } -} diff --git a/Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/dislike-ad-icon.imageset/thumbsdown@2x.png b/Sources/Brave/Assets/Images.xcassets/Brave Rewards/Ads/dislike-ad-icon.imageset/thumbsdown@2x.png deleted file mode 100644 index 38083a85022ed7d146ffd186cfbd54e2acccac6d..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1078 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 diff --git a/Sources/Brave/Frontend/Brave Notifications/Brave Rewards/RewardsNotification.swift b/Sources/Brave/Frontend/Brave Notifications/Brave Rewards/RewardsNotification.swift index 26d4d0143af..55e02c932a3 100644 --- a/Sources/Brave/Frontend/Brave Notifications/Brave Rewards/RewardsNotification.swift +++ b/Sources/Brave/Frontend/Brave Notifications/Brave Rewards/RewardsNotification.swift @@ -16,8 +16,6 @@ class RewardsNotification: NSObject, BraveNotification { case dismissed /// The user ignored the ad for a given amount of time for it to automatically dismiss case timedOut - /// The user clicked the thumbs down button by swiping on the ad - case disliked } var view: UIView @@ -31,14 +29,13 @@ class RewardsNotification: NSObject, BraveNotification { if !AppConstants.buildChannel.isPublic, let override = Preferences.Rewards.adsDurationOverride.value, override > 0 { dismissTimeInterval = TimeInterval(override) } - return adView.swipeTranslation != 0 ? .explicit : .automatic(after: dismissTimeInterval) + return .automatic(after: dismissTimeInterval) } private let handler: (Action) -> Void func willDismiss(timedOut: Bool) { guard let adView = view as? AdView else { return } - adView.setSwipeTranslation(0, animated: true) handler(timedOut ? .timedOut : .dismissed) } @@ -60,88 +57,13 @@ class RewardsNotification: NSObject, BraveNotification { adView.adContentButton.bodyLabel.text = ad.body adView.adContentButton.addTarget(self, action: #selector(tappedAdView(_:)), for: .touchUpInside) - adView.openSwipeButton.addTarget(self, action: #selector(tappedOpen(_:)), for: .touchUpInside) - adView.dislikeSwipeButton.addTarget(self, action: #selector(tappedDisliked(_:)), for: .touchUpInside) - - let swipePanGesture = UIPanGestureRecognizer(target: self, action: #selector(swipePannedAdView(_:))) - swipePanGesture.delegate = self - adView.addGestureRecognizer(swipePanGesture) } @objc private func tappedAdView(_ sender: AdContentButton) { guard let adView = sender.superview as? AdView else { return } - if sender.transform.tx != 0 { - adView.setSwipeTranslation(0, animated: true) - return - } dismissAction?() handler(.opened) } - - @objc private func tappedOpen(_ sender: AdSwipeButton) { - dismissAction?() - handler(.opened) - } - - @objc private func tappedDisliked(_ sender: AdSwipeButton) { - dismissAction?() - handler(.disliked) - } - - // Distance travelled after decelerating to zero velocity at a constant rate - private func project(initialVelocity: CGFloat, decelerationRate: CGFloat) -> CGFloat { - return (initialVelocity / 1000.0) * decelerationRate / (1.0 - decelerationRate) - } - - private let actionTriggerThreshold: CGFloat = 180.0 - private let actionRestThreshold: CGFloat = 90.0 - - private var swipeState: CGFloat = 0 - @objc private func swipePannedAdView(_ pan: UIPanGestureRecognizer) { - guard let adView = pan.view as? AdView else { return } - switch pan.state { - case .began: - swipeState = adView.adContentButton.transform.tx - case .changed: - let tx = swipeState + pan.translation(in: adView).x - if tx < -actionTriggerThreshold && !adView.dislikeSwipeButton.isHighlighted { - UIImpactFeedbackGenerator(style: .medium).bzzt() - } - adView.dislikeSwipeButton.isHighlighted = tx < -actionTriggerThreshold - adView.adContentButton.transform.tx = min(0, tx) - adView.setNeedsLayout() - case .ended: - let velocity = pan.velocity(in: adView).x - let tx = swipeState + pan.translation(in: adView).x - let projected = project(initialVelocity: velocity, decelerationRate: UIScrollView.DecelerationRate.normal.rawValue) - if /*tx > actionTriggerThreshold ||*/ tx < -actionTriggerThreshold { - adView.setSwipeTranslation(0, animated: true, panVelocity: velocity) - dismissAction?() - handler(tx > 0 ? .opened : .disliked) - break - } else if /*tx + projected > actionRestThreshold ||*/ tx + projected < -actionRestThreshold { - adView.setSwipeTranslation((tx + projected) > 0 ? actionRestThreshold : -actionRestThreshold, animated: true, panVelocity: velocity) - break - } - fallthrough - case .cancelled: - adView.setSwipeTranslation(0, animated: true) - default: - break - } - } -} - -extension RewardsNotification: UIGestureRecognizerDelegate { - - func gestureRecognizerShouldBegin(_ gestureRecognizer: UIGestureRecognizer) -> Bool { - if let pan = gestureRecognizer as? UIPanGestureRecognizer { - let velocity = pan.velocity(in: pan.view) - // Horizontal only - return abs(velocity.x) > abs(velocity.y) - } - return false - } } extension RewardsNotification { diff --git a/Sources/Brave/Frontend/Brave Rewards/Ads/AdView.swift b/Sources/Brave/Frontend/Brave Rewards/Ads/AdView.swift index 86fb335bc95..72d9a5ba2e1 100644 --- a/Sources/Brave/Frontend/Brave Rewards/Ads/AdView.swift +++ b/Sources/Brave/Frontend/Brave Rewards/Ads/AdView.swift @@ -8,71 +8,17 @@ import Shared public class AdView: UIView { let adContentButton = AdContentButton() - let openSwipeButton = AdSwipeButton(contentType: .text(Strings.Ads.open, textColor: .white)).then { - $0.backgroundColor = .braveBlurpleTint - } - let dislikeSwipeButton = AdSwipeButton(contentType: .image(UIImage(named: "dislike-ad-icon", in: .module, compatibleWith: nil)!)).then { - $0.backgroundColor = .braveErrorLabel - } public override init(frame: CGRect) { super.init(frame: frame) addSubview(adContentButton) - // addSubview(openSwipeButton) - addSubview(dislikeSwipeButton) adContentButton.snp.makeConstraints { $0.edges.equalTo(self) } } - public override func layoutSubviews() { - super.layoutSubviews() - - // let openWidth = max(0, adContentButton.frame.minX - 8) - // openSwipeButton.frame = CGRect( - // x: 0, - // y: 0, - // width: openWidth, - // height: adContentButton.bounds.height - // ) - // openSwipeButton.alpha = max(0, openWidth - 30) / 20 - - let dislikeWidth = max(0, bounds.width - adContentButton.frame.maxX - 8) - dislikeSwipeButton.frame = CGRect( - x: adContentButton.frame.maxX + 8, - y: 0, - width: dislikeWidth, - height: adContentButton.bounds.height - ) - dislikeSwipeButton.alpha = max(0, dislikeWidth - 30) / 20 - } - - var swipeTranslation: CGFloat { - return adContentButton.transform.tx - } - - /// Set the horizontal swipe translation - func setSwipeTranslation(_ tx: CGFloat, animated: Bool = false, panVelocity: CGFloat? = nil, completionBlock: (() -> Void)? = nil) { - if animated { - let springTiming = UISpringTimingParameters(dampingRatio: 0.9) - let animator = UIViewPropertyAnimator(duration: 0.3, timingParameters: springTiming) - animator.addAnimations { [self] in - adContentButton.transform.tx = tx - setNeedsLayout() - layoutIfNeeded() - } - animator.addCompletion { _ in - completionBlock?() - } - animator.startAnimation() - } else { - adContentButton.transform.tx = tx - setNeedsLayout() - } - } - @available(*, unavailable) required init(coder: NSCoder) { fatalError() diff --git a/Sources/Brave/Frontend/Brave Rewards/Ads/AdsNotificationHandler.swift b/Sources/Brave/Frontend/Brave Rewards/Ads/AdsNotificationHandler.swift index 3bcc463a9cd..11a57e938af 100644 --- a/Sources/Brave/Frontend/Brave Rewards/Ads/AdsNotificationHandler.swift +++ b/Sources/Brave/Frontend/Brave Rewards/Ads/AdsNotificationHandler.swift @@ -48,9 +48,6 @@ class AdsNotificationHandler: BraveAdsNotificationHandler { self.ads.reportNotificationAdEvent(notification.placementID, eventType: .dismissed, completion: { _ in }) case .timedOut: self.ads.reportNotificationAdEvent(notification.placementID, eventType: .timedOut, completion: { _ in }) - case .disliked: - self.ads.reportNotificationAdEvent(notification.placementID, eventType: .dismissed, completion: { _ in }) - self.ads.toggleThumbsDown(forAd: notification.creativeInstanceID, advertiserId: notification.advertiserID, segment: notification.segment) } self.actionOccured?(notification, action) }