[go: up one dir, main page]

[ios] Presents InfobarModal when Banner is tapped.

The Banner is animated to scale down and then back to its original size
before presenting the Modal.

TBR=sczs@chromium.org

(cherry picked from commit c4450e5ac680ff1ff2200df2b611d607bcc2147e)

Bug: 911864, 973168
Change-Id: Iac6f4435b39f188d7f24e2576b7ca429bcbccf0b
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1648534
Commit-Queue: Sergio Collazos <sczs@chromium.org>
Reviewed-by: Chris Lu <thegreenfrog@chromium.org>
Cr-Original-Commit-Position: refs/heads/master@{#668150}
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1656188
Reviewed-by: Sergio Collazos <sczs@chromium.org>
Cr-Commit-Position: refs/branch-heads/3809@{#257}
Cr-Branched-From: d82dec1a818f378c464ba307ddd9c92133eac355-refs/heads/master@{#665002}
diff --git a/ios/chrome/browser/infobars/infobar_metrics_recorder.h b/ios/chrome/browser/infobars/infobar_metrics_recorder.h
index cdaa336..3cc19fc 100644
--- a/ios/chrome/browser/infobars/infobar_metrics_recorder.h
+++ b/ios/chrome/browser/infobars/infobar_metrics_recorder.h
@@ -35,10 +35,12 @@
   TimedOut = 0,
   // Infobar Banner was dismissed by being swiped up.
   SwipedUp = 1,
-  // Infobar Banner was dismissed by being expanded into an Infobar Modal.
+  // Infobar Banner was dismissed by being dragged into an Infobar Modal.
   ExpandedToModal = 2,
+  // Infobar Banner was dismissed by being tapped into an Infobar Modal.
+  TappedToModal = 3,
   // Highest enumerator. Recommended by Histogram metrics best practices.
-  kMaxValue = ExpandedToModal,
+  kMaxValue = TappedToModal,
 };
 
 // Values for the UMA Mobile.Messages.Modal.Event histogram. These values
diff --git a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
index 0cbbd5b1..3717dfd 100644
--- a/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
+++ b/ios/chrome/browser/ui/infobars/banners/infobar_banner_view_controller.mm
@@ -23,8 +23,10 @@
 const CGFloat kBannerViewShadowOpacity = 0.23;
 
 // Banner View selected constants.
+const CGFloat kTappedBannerViewScale = 0.98;
 const CGFloat kSelectedBannerViewScale = 1.02;
 const CGFloat kSelectBannerAnimationDurationInSeconds = 0.2;
+const CGFloat kTappedBannerAnimationDurationInSeconds = 0.1;
 const CGFloat kSelectedBannerViewYShadowOffset = 8.0;
 
 // Bottom Grip constants.
@@ -226,6 +228,11 @@
   longPressGestureRecognizer.minimumPressDuration =
       kLongPressTimeDurationInSeconds;
   [self.view addGestureRecognizer:longPressGestureRecognizer];
+
+  UITapGestureRecognizer* tapGestureRecognizer = [[UITapGestureRecognizer alloc]
+      initWithTarget:self
+              action:@selector(animateBannerTappedAndPresentModal)];
+  [self.view addGestureRecognizer:tapGestureRecognizer];
 }
 
 - (void)viewDidAppear:(BOOL)animated {
@@ -289,7 +296,9 @@
   }
 
   if (gesture.state == UIGestureRecognizerStateEnded) {
-    [self animateBannerToOriginalState];
+    [self animateBannerToOriginalStateWithDuration:
+              kSelectBannerAnimationDurationInSeconds
+                                        completion:nil];
     // If dragged up by more than kChangeInPositionForDismissal at the time
     // the gesture ended, OR |self.shouldDismissAfterTouchesEnded| is YES.
     // Dismiss the banner.
@@ -333,15 +342,18 @@
 }
 
 // Animate the Banner back to its original size and styling.
-- (void)animateBannerToOriginalState {
-  [UIView
-      animateWithDuration:kSelectBannerAnimationDurationInSeconds
-               animations:^{
-                 self.view.superview.transform = CGAffineTransformIdentity;
-                 [self.view.layer
-                     setShadowOffset:CGSizeMake(0.0, kBannerViewYShadowOffset)];
-               }
-               completion:nil];
+- (void)animateBannerToOriginalStateWithDuration:(NSTimeInterval)duration
+                                      completion:(ProceduralBlock)completion {
+  [UIView animateWithDuration:duration
+      animations:^{
+        self.view.superview.transform = CGAffineTransformIdentity;
+        [self.view.layer
+            setShadowOffset:CGSizeMake(0.0, kBannerViewYShadowOffset)];
+      }
+      completion:^(BOOL finished) {
+        if (completion)
+          completion();
+      }];
 }
 
 // Animate the banner back to its original position.
@@ -353,6 +365,32 @@
                    completion:nil];
 }
 
+// Animate the Banner being tapped by scaling it down and then to its original
+// state. After the animation it presentd the Infobar Modal.
+- (void)animateBannerTappedAndPresentModal {
+  [UIView animateWithDuration:kTappedBannerAnimationDurationInSeconds
+      animations:^{
+        self.view.superview.transform = CGAffineTransformMakeScale(
+            kTappedBannerViewScale, kTappedBannerViewScale);
+        [self.view.layer
+            setShadowOffset:CGSizeMake(0.0, kSelectedBannerViewYShadowOffset)];
+      }
+      completion:^(BOOL finished) {
+        [self
+            animateBannerToOriginalStateWithDuration:
+                kTappedBannerAnimationDurationInSeconds
+                                          completion:^{
+                                            [self presentInfobarModalAfterTap];
+                                          }];
+      }];
+}
+
+- (void)presentInfobarModalAfterTap {
+  [self.metricsRecorder
+      recordBannerDismissType:MobileMessagesBannerDismissType::TappedToModal];
+  [self.delegate presentInfobarModalFromBanner];
+}
+
 #pragma mark - Accessibility
 
 - (NSArray*)accessibilityActions {
@@ -369,14 +407,14 @@
                 target:self
               selector:@selector(dismiss)];
 
-  UIAccessibilityCustomAction* expandAction =
+  UIAccessibilityCustomAction* modalAction =
       [[UIAccessibilityCustomAction alloc]
           initWithName:l10n_util::GetNSString(
                            IDS_IOS_INFOBAR_BANNER_OPTIONS_HINT)
                 target:self
-              selector:@selector(presentInfobarModal)];
+              selector:@selector(triggerInfobarModal)];
 
-  return @[ acceptAction, dismissAction, expandAction ];
+  return @[ acceptAction, dismissAction, modalAction ];
 }
 
 // A11y Custom actions selectors need to return a BOOL.
@@ -384,12 +422,12 @@
   [self bannerInfobarButtonWasPressed:nil];
   return NO;
 }
-- (BOOL)presentInfobarModal {
-  [self.metricsRecorder
-      recordBannerDismissType:MobileMessagesBannerDismissType::ExpandedToModal];
-  [self.delegate presentInfobarModalFromBanner];
+
+- (BOOL)triggerInfobarModal {
+  [self presentInfobarModalAfterTap];
   return NO;
 }
+
 - (BOOL)dismiss {
   [self.delegate dismissInfobarBanner:self animated:YES completion:nil];
   return NO;
diff --git a/ios/showcase/infobars/sc_infobar_banner_coordinator_egtest.mm b/ios/showcase/infobars/sc_infobar_banner_coordinator_egtest.mm
index 7699eac..3f04a7f 100644
--- a/ios/showcase/infobars/sc_infobar_banner_coordinator_egtest.mm
+++ b/ios/showcase/infobars/sc_infobar_banner_coordinator_egtest.mm
@@ -116,4 +116,31 @@
       assertWithMatcher:grey_nil()];
 }
 
+// Tests that the InfobarModal is presented when the Banner its tapped.
+- (void)testInfobarBannerTapped {
+  // Check Banner was presented.
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
+                                          kInfobarBannerViewIdentifier)]
+      assertWithMatcher:grey_notNil()];
+  // Tap Banner.
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
+                                          kInfobarBannerViewIdentifier)]
+      performAction:grey_tap()];
+  // Check Modal was presented.
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
+                                          kInfobarBannerPresentedModalLabel)]
+      assertWithMatcher:grey_notNil()];
+  // Dismiss Modal.
+  [[EarlGrey
+      selectElementWithMatcher:grey_accessibilityID(kInfobarModalCancelButton)]
+      performAction:grey_tap()];
+  // Check neither the Banner nor Modal are presented.
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
+                                          kInfobarBannerViewIdentifier)]
+      assertWithMatcher:grey_nil()];
+  [[EarlGrey selectElementWithMatcher:grey_accessibilityID(
+                                          kInfobarBannerPresentedModalLabel)]
+      assertWithMatcher:grey_nil()];
+}
+
 @end
diff --git a/tools/metrics/histograms/enums.xml b/tools/metrics/histograms/enums.xml
index d37fc22..5d3709dc 100644
--- a/tools/metrics/histograms/enums.xml
+++ b/tools/metrics/histograms/enums.xml
@@ -38680,6 +38680,7 @@
   <int value="0" label="TimedOut"/>
   <int value="1" label="SwipedUp"/>
   <int value="2" label="ExpandedToModal"/>
+  <int value="3" label="TappedToModal"/>
 </enum>
 
 <enum name="MobileMessagesBannerEvent">