Index: ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.mm |
diff --git a/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.mm b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.mm |
new file mode 100644 |
index 0000000000000000000000000000000000000000..57eed01f33ca460058340fbdbba7a4c116a56666 |
--- /dev/null |
+++ b/ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.mm |
@@ -0,0 +1,420 @@ |
+// Copyright 2015 The Chromium Authors. All rights reserved. |
+// Use of this source code is governed by a BSD-style license that can be |
+// found in the LICENSE file. |
+ |
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_panel_overlay_view.h" |
+ |
+#import "base/mac/scoped_nsobject.h" |
+#include "base/metrics/user_metrics.h" |
+#include "base/metrics/user_metrics_action.h" |
+#import "ios/chrome/browser/ui/colors/MDCPalette+CrAdditions.h" |
+#import "ios/chrome/browser/ui/commands/UIKit+ChromeExecuteCommand.h" |
+#include "ios/chrome/browser/ui/commands/ios_command_ids.h" |
+#import "ios/chrome/browser/ui/commands/show_signin_command.h" |
+#import "ios/chrome/browser/ui/material_components/activity_indicator.h" |
+#import "ios/chrome/browser/ui/sync/sync_util.h" |
+#import "ios/chrome/browser/ui/tab_switcher/tab_switcher_model.h" |
+#import "ios/chrome/browser/ui/uikit_ui_util.h" |
+#include "ios/chrome/grit/ios_chromium_strings.h" |
+#include "ios/chrome/grit/ios_strings.h" |
+#include "ios/public/provider/chrome/browser/chrome_browser_provider.h" |
+#import "ios/third_party/material_components_ios/src/components/ActivityIndicator/src/MaterialActivityIndicator.h" |
+#import "ios/third_party/material_components_ios/src/components/Buttons/src/MaterialButtons.h" |
+#import "ios/third_party/material_components_ios/src/components/ShadowElevations/src/MaterialShadowElevations.h" |
+#import "ios/third_party/material_components_ios/src/components/Typography/src/MaterialTypography.h" |
+#include "ui/base/l10n/l10n_util.h" |
+ |
+TabSwitcherPanelOverlayType PanelOverlayTypeFromSignInPanelsType( |
+ TabSwitcherSignInPanelsType signInPanelType) { |
+ switch (signInPanelType) { |
+ case TabSwitcherSignInPanelsType::PANEL_USER_SIGNED_OUT: |
+ return TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_SIGNED_OUT; |
+ case TabSwitcherSignInPanelsType::PANEL_USER_SIGNED_IN_SYNC_OFF: |
+ return TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_SIGNED_IN_SYNC_OFF; |
+ case TabSwitcherSignInPanelsType::PANEL_USER_SIGNED_IN_SYNC_IN_PROGRESS: |
+ return TabSwitcherPanelOverlayType:: |
+ OVERLAY_PANEL_USER_SIGNED_IN_SYNC_IN_PROGRESS; |
+ case TabSwitcherSignInPanelsType::PANEL_USER_SIGNED_IN_SYNC_ON_NO_SESSIONS: |
+ return TabSwitcherPanelOverlayType:: |
+ OVERLAY_PANEL_USER_SIGNED_IN_SYNC_ON_NO_SESSIONS; |
+ case TabSwitcherSignInPanelsType::NO_PANEL: |
+ return TabSwitcherPanelOverlayType::OVERLAY_PANEL_EMPTY; |
+ } |
+} |
+ |
+namespace { |
+const CGFloat kContainerOriginYOffset = -58.0; |
+const CGFloat kContainerWidth = 400.0; |
+const CGFloat kTitleMinimumLineHeight = 32.0; |
+const CGFloat kSubtitleMinimunLineHeight = 24.0; |
+} |
+ |
+@interface TabSwitcherPanelOverlayView () |
+ |
+// Updates the texts of labels and button according to the current |
+// |overlayType|. |
+- (void)updateText; |
+// Updates the button target and tag according to the current |overlayType|. |
+- (void)updateButtonTarget; |
+// Sends a SignIn chrome command. |
+- (void)showSignIn; |
+ |
+@end |
+ |
+@implementation TabSwitcherPanelOverlayView { |
+ ios::ChromeBrowserState* _browserState; // Weak. |
+ base::scoped_nsobject<UIView> _container; |
+ base::scoped_nsobject<UILabel> _titleLabel; |
+ base::scoped_nsobject<UILabel> _subtitleLabel; |
+ base::scoped_nsobject<MDCButton> _textButton; |
+ base::scoped_nsobject<MDCButton> _floatingButton; |
+ base::scoped_nsobject<MDCActivityIndicator> _activityIndicator; |
+ std::string _recordedMetricString; |
+} |
+ |
+@synthesize overlayType = _overlayType; |
+ |
+- (instancetype)initWithFrame:(CGRect)frame |
+ browserState:(ios::ChromeBrowserState*)browserState { |
+ self = [super initWithFrame:frame]; |
+ if (self) { |
+ _browserState = browserState; |
+ // Create and add container. Will be vertically and horizontally centered. |
+ _container.reset([[UIView alloc] initWithFrame:CGRectZero]); |
+ [_container setTranslatesAutoresizingMaskIntoConstraints:NO]; |
+ [self addSubview:_container]; |
+ |
+ // Create and add title label to the container. |
+ _titleLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]); |
+ [_titleLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; |
+ [_titleLabel setFont:[MDCTypography headlineFont]]; |
+ [_titleLabel |
+ setTextColor:[UIColor |
+ colorWithWhite:1 |
+ alpha:[MDCTypography headlineFontOpacity]]]; |
+ [_titleLabel setLineBreakMode:NSLineBreakByWordWrapping]; |
+ [_titleLabel setNumberOfLines:0]; |
+ [_titleLabel setTextAlignment:NSTextAlignmentCenter]; |
+ [_container addSubview:_titleLabel]; |
+ |
+ // Create and add subtitle label to the container. |
+ _subtitleLabel.reset([[UILabel alloc] initWithFrame:CGRectZero]); |
+ [_subtitleLabel setTranslatesAutoresizingMaskIntoConstraints:NO]; |
+ [_subtitleLabel setFont:[MDCTypography subheadFont]]; |
+ [_subtitleLabel |
+ setTextColor:[UIColor |
+ colorWithWhite:1 |
+ alpha:[MDCTypography display1FontOpacity]]]; |
+ [_subtitleLabel setNumberOfLines:0]; |
+ [_container addSubview:_subtitleLabel]; |
+ |
+ // Create and add button to the container. |
+ _textButton.reset([[MDCRaisedButton alloc] init]); |
+ [_textButton setElevation:MDCShadowElevationNone |
+ forState:UIControlStateNormal]; |
+ MDCPalette* buttonPalette = [MDCPalette cr_bluePalette]; |
+ [_textButton |
+ setInkColor:[[buttonPalette tint300] colorWithAlphaComponent:0.5f]]; |
+ [_textButton setBackgroundColor:[buttonPalette tint500] |
+ forState:UIControlStateNormal]; |
+ [_textButton setBackgroundColor:[UIColor colorWithWhite:0.8f alpha:1.0f] |
+ forState:UIControlStateDisabled]; |
+ [_textButton setTranslatesAutoresizingMaskIntoConstraints:NO]; |
+ [[_textButton imageView] setTintColor:[UIColor whiteColor]]; |
+ [_textButton setCustomTitleColor:[UIColor whiteColor]]; |
+ [_container addSubview:_textButton]; |
+ |
+ // Create and add floatingButton to the container. |
+ _floatingButton.reset([[MDCFloatingButton alloc] init]); |
+ [_floatingButton setTranslatesAutoresizingMaskIntoConstraints:NO]; |
+ [[_floatingButton imageView] setTintColor:[UIColor whiteColor]]; |
+ [_container addSubview:_floatingButton]; |
+ |
+ // Create and add activity indicator to the container. |
+ _activityIndicator.reset( |
+ [[MDCActivityIndicator alloc] initWithFrame:CGRectZero]); |
+ [_activityIndicator setCycleColors:ActivityIndicatorBrandedCycleColors()]; |
+ [_activityIndicator setTranslatesAutoresizingMaskIntoConstraints:NO]; |
+ [_container addSubview:_activityIndicator]; |
+ |
+ // Set constraints on all of the container's subviews. |
+ AddSameCenterXConstraint(_container, _titleLabel); |
+ AddSameCenterXConstraint(_container, _subtitleLabel); |
+ NSDictionary* viewsDictionary = @{ |
+ @"title" : _titleLabel.get(), |
+ @"subtitle" : _subtitleLabel.get(), |
+ @"button" : _textButton.get(), |
+ @"floatingButton" : _floatingButton.get(), |
+ @"activityIndicator" : _activityIndicator.get(), |
+ }; |
+ AddSameCenterXConstraint(_container, _textButton); |
+ AddSameCenterXConstraint(_container, _floatingButton); |
+ AddSameCenterXConstraint(_container, _activityIndicator); |
+ NSArray* constraints = @[ |
+ @"V:|-0-[title]-12-[subtitle]-48-[button]-0-|", |
+ @"V:[subtitle]-35-[floatingButton(==48)]-0-|", |
+ @"V:[subtitle]-24-[activityIndicator]", @"H:|-[title]-|", |
+ @"H:|-[subtitle]-|", @"H:[button(==180)]", @"H:[floatingButton(==48)]" |
+ ]; |
+ ApplyVisualConstraints(constraints, viewsDictionary, _container); |
+ |
+ // Sets the container's width relative to the parent. |
+ ApplyVisualConstraintsWithMetrics( |
+ @[ |
+ @"H:|-(>=0)-[container(==containerWidth@999)]-(>=0)-|", |
+ ], |
+ @{ @"container" : _container.get() }, |
+ @{ @"containerWidth" : @(kContainerWidth) }, self); |
+ } |
+ return self; |
+} |
+ |
+- (void)layoutSubviews { |
+ [super layoutSubviews]; |
+ CGRect containerFrame = [_container frame]; |
+ containerFrame.origin.x = |
+ (self.frame.size.width - containerFrame.size.width) / 2; |
+ containerFrame.origin.y = |
+ (self.frame.size.height - containerFrame.size.height) / 2 + |
+ kContainerOriginYOffset; |
+ [_container setFrame:containerFrame]; |
+} |
+ |
+- (void)setOverlayType:(TabSwitcherPanelOverlayType)overlayType { |
+ _overlayType = overlayType; |
+ [self updateText]; |
+ [self updateButtonTarget]; |
+} |
+ |
+#pragma mark - Private |
+ |
+- (void)updateText { |
+ NSMutableAttributedString* titleString = nil; |
+ NSMutableAttributedString* subtitleString = nil; |
+ |
+ NSString* buttonTitle = nil; |
+ UIImage* buttonImage = nil; |
+ NSString* buttonAccessibilityLabel = nil; |
+ UIColor* floatingButtonNormalBackgroundColor = nil; |
+ UIColor* floatingButtonDisabledBackgroundColor = nil; |
+ UIColor* floatingButtonInkColor = nil; |
+ BOOL spinnerIsHidden = YES; |
+ switch (self.overlayType) { |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_EMPTY: |
+ break; |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_SIGNED_OUT: |
+ titleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_SIGN_IN_ACCOUNT_TITLE)] |
+ autorelease]; |
+ subtitleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_SIGN_IN_ACCOUNT_PROMO)] |
+ autorelease]; |
+ buttonTitle = |
+ l10n_util::GetNSString(IDS_IOS_TAB_SWITCHER_SIGN_IN_ACCOUNT_BUTTON); |
+ break; |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_SIGNED_IN_SYNC_OFF: |
+ titleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_ENABLE_SYNC_TITLE)] |
+ autorelease]; |
+ subtitleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_SYNC_IS_OFF)] autorelease]; |
+ buttonTitle = |
+ l10n_util::GetNSString(IDS_IOS_TAB_SWITCHER_ENABLE_SYNC_BUTTON); |
+ break; |
+ case TabSwitcherPanelOverlayType:: |
+ OVERLAY_PANEL_USER_SIGNED_IN_SYNC_ON_NO_SESSIONS: |
+ titleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_NO_TABS_TO_SYNC_PROMO)] |
+ autorelease]; |
+ subtitleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_OPEN_TABS_NO_SESSION_INSTRUCTIONS)] |
+ autorelease]; |
+ break; |
+ case TabSwitcherPanelOverlayType:: |
+ OVERLAY_PANEL_USER_SIGNED_IN_SYNC_IN_PROGRESS: |
+ titleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_SYNC_IN_PROGRESS_PROMO)] |
+ autorelease]; |
+ subtitleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_SYNC_IS_OFF)] autorelease]; |
+ spinnerIsHidden = NO; |
+ break; |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_NO_OPEN_TABS: |
+ titleString = [[[NSMutableAttributedString alloc] |
+ initWithString: |
+ l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_NO_LOCAL_NON_INCOGNITO_TABS_TITLE)] |
+ autorelease]; |
+ subtitleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_NO_LOCAL_NON_INCOGNITO_TABS)] |
+ autorelease]; |
+ buttonImage = [UIImage imageNamed:@"tabswitcher_new_tab_fab"]; |
+ buttonImage = [buttonImage |
+ imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; |
+ floatingButtonInkColor = |
+ [[[MDCPalette cr_bluePalette] tint300] colorWithAlphaComponent:0.5f]; |
+ floatingButtonNormalBackgroundColor = |
+ [[MDCPalette cr_bluePalette] tint500]; |
+ floatingButtonDisabledBackgroundColor = |
+ [UIColor colorWithWhite:0.8f alpha:1.0f]; |
+ buttonAccessibilityLabel = |
+ l10n_util::GetNSString(IDS_IOS_TAB_SWITCHER_CREATE_NEW_TAB); |
+ break; |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_NO_INCOGNITO_TABS: |
+ titleString = [[[NSMutableAttributedString alloc] |
+ initWithString: |
+ l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_NO_LOCAL_INCOGNITO_TABS_PROMO)] |
+ autorelease]; |
+ subtitleString = [[[NSMutableAttributedString alloc] |
+ initWithString:l10n_util::GetNSString( |
+ IDS_IOS_TAB_SWITCHER_NO_LOCAL_INCOGNITO_TABS)] |
+ autorelease]; |
+ buttonImage = [UIImage imageNamed:@"tabswitcher_new_tab_fab"]; |
+ buttonImage = [buttonImage |
+ imageWithRenderingMode:UIImageRenderingModeAlwaysTemplate]; |
+ |
+ floatingButtonInkColor = |
+ [[[MDCPalette greyPalette] tint300] colorWithAlphaComponent:0.25f]; |
+ floatingButtonNormalBackgroundColor = [[MDCPalette greyPalette] tint500]; |
+ floatingButtonDisabledBackgroundColor = |
+ [UIColor colorWithWhite:0.8f alpha:1.0f]; |
+ buttonAccessibilityLabel = |
+ l10n_util::GetNSString(IDS_IOS_TAB_SWITCHER_CREATE_NEW_INCOGNITO_TAB); |
+ break; |
+ }; |
+ |
+ base::scoped_nsobject<NSMutableParagraphStyle> titleStyle( |
+ [[NSMutableParagraphStyle alloc] init]); |
+ [titleStyle setMinimumLineHeight:kTitleMinimumLineHeight]; |
+ [titleStyle setAlignment:NSTextAlignmentCenter]; |
+ [titleStyle setLineBreakMode:NSLineBreakByWordWrapping]; |
+ [titleString addAttribute:NSParagraphStyleAttributeName |
+ value:titleStyle |
+ range:NSMakeRange(0, [titleString length])]; |
+ [_titleLabel setAttributedText:titleString]; |
+ |
+ base::scoped_nsobject<NSMutableParagraphStyle> subtitleStyle( |
+ [[NSMutableParagraphStyle alloc] init]); |
+ [subtitleStyle setMinimumLineHeight:kSubtitleMinimunLineHeight]; |
+ [subtitleStyle setAlignment:NSTextAlignmentCenter]; |
+ [subtitleStyle setLineBreakMode:NSLineBreakByWordWrapping]; |
+ [subtitleString addAttribute:NSParagraphStyleAttributeName |
+ value:subtitleStyle |
+ range:NSMakeRange(0, [subtitleString length])]; |
+ [_subtitleLabel setAttributedText:subtitleString]; |
+ |
+ [_textButton setTitle:buttonTitle forState:UIControlStateNormal]; |
+ [_textButton setImage:buttonImage forState:UIControlStateNormal]; |
+ [_floatingButton setTitle:buttonTitle forState:UIControlStateNormal]; |
+ [_floatingButton setImage:buttonImage forState:UIControlStateNormal]; |
+ [_floatingButton setInkColor:floatingButtonInkColor]; |
+ [_floatingButton setBackgroundColor:floatingButtonNormalBackgroundColor |
+ forState:UIControlStateNormal]; |
+ [_floatingButton setBackgroundColor:floatingButtonDisabledBackgroundColor |
+ forState:UIControlStateDisabled]; |
+ |
+ [_floatingButton setAccessibilityLabel:buttonAccessibilityLabel]; |
+ [_activityIndicator setHidden:spinnerIsHidden]; |
+ if (spinnerIsHidden) { |
+ [_activityIndicator stopAnimating]; |
+ } else { |
+ [_activityIndicator startAnimating]; |
+ } |
+} |
+ |
+- (void)updateButtonTarget { |
+ NSInteger tag = 0; |
+ SEL selector = nil; |
+ _recordedMetricString = ""; |
+ |
+ BOOL shouldShowTextButton = YES; |
+ BOOL shouldShowFloatingButton = NO; |
+ switch (self.overlayType) { |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_EMPTY: |
+ shouldShowTextButton = NO; |
+ break; |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_SIGNED_OUT: |
+ selector = @selector(showSignIn); |
+ _recordedMetricString = "MobileTabSwitcherSignIn"; |
+ break; |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_SIGNED_IN_SYNC_OFF: |
+ selector = @selector(showSyncSettings); |
+ _recordedMetricString = "MobileTabSwitcherEnableSync"; |
+ break; |
+ case TabSwitcherPanelOverlayType:: |
+ OVERLAY_PANEL_USER_SIGNED_IN_SYNC_ON_NO_SESSIONS: |
+ shouldShowTextButton = NO; |
+ break; |
+ case TabSwitcherPanelOverlayType:: |
+ OVERLAY_PANEL_USER_SIGNED_IN_SYNC_IN_PROGRESS: |
+ shouldShowTextButton = NO; |
+ break; |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_NO_OPEN_TABS: |
+ tag = IDC_NEW_TAB; |
+ selector = @selector(rootViewControllerChromeCommand:); |
+ _recordedMetricString = "MobileTabSwitcherCreateNonIncognitoTab"; |
+ shouldShowTextButton = NO; |
+ shouldShowFloatingButton = YES; |
+ break; |
+ case TabSwitcherPanelOverlayType::OVERLAY_PANEL_USER_NO_INCOGNITO_TABS: |
+ tag = IDC_NEW_INCOGNITO_TAB; |
+ selector = @selector(rootViewControllerChromeCommand:); |
+ _recordedMetricString = "MobileTabSwitcherCreateIncognitoTab"; |
+ shouldShowTextButton = NO; |
+ shouldShowFloatingButton = YES; |
+ break; |
+ } |
+ |
+ [_textButton setTag:tag]; |
+ [_textButton addTarget:self |
+ action:selector |
+ forControlEvents:UIControlEventTouchUpInside]; |
+ [_textButton addTarget:self |
+ action:@selector(recordMetrics) |
+ forControlEvents:UIControlEventTouchUpInside]; |
+ [_textButton setHidden:!shouldShowTextButton]; |
+ [_floatingButton setTag:tag]; |
+ [_floatingButton addTarget:self |
+ action:selector |
+ forControlEvents:UIControlEventTouchUpInside]; |
+ [_floatingButton addTarget:self |
+ action:@selector(recordMetrics) |
+ forControlEvents:UIControlEventTouchUpInside]; |
+ [_floatingButton setHidden:!shouldShowFloatingButton]; |
+} |
+ |
+- (void)showSignIn { |
+ base::RecordAction(base::UserMetricsAction("Signin_Signin_FromTabSwitcher")); |
+ base::scoped_nsobject<ShowSigninCommand> command([[ShowSigninCommand alloc] |
+ initWithOperation:AUTHENTICATION_OPERATION_SIGNIN |
+ signInAccessPoint:signin_metrics::AccessPoint:: |
+ ACCESS_POINT_TAB_SWITCHER]); |
+ [self chromeExecuteCommand:command]; |
+} |
+ |
+- (void)showSyncSettings { |
+ [self chromeExecuteCommand:ios_internal::sync::GetSyncCommandForBrowserState( |
+ _browserState)]; |
+} |
+ |
+- (void)rootViewControllerChromeCommand:(id)command { |
+ [self chromeExecuteCommand:command]; |
+} |
+ |
+- (void)recordMetrics { |
+ if (!_recordedMetricString.length()) |
+ return; |
+ base::RecordAction(base::UserMetricsAction(_recordedMetricString.c_str())); |
+} |
+ |
+@end |