| // 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" |
| |
| #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" |
| |
| #if !defined(__has_feature) || !__has_feature(objc_arc) |
| #error "This file requires ARC support." |
| #endif |
| |
| 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. |
| UIView* _container; |
| UILabel* _titleLabel; |
| UILabel* _subtitleLabel; |
| MDCButton* _textButton; |
| MDCButton* _floatingButton; |
| 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 = [[UIView alloc] initWithFrame:CGRectZero]; |
| [_container setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| [self addSubview:_container]; |
| |
| // Create and add title label to the container. |
| _titleLabel = [[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 = [[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 = [[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 = [[MDCFloatingButton alloc] init]; |
| [_floatingButton setTranslatesAutoresizingMaskIntoConstraints:NO]; |
| [[_floatingButton imageView] setTintColor:[UIColor whiteColor]]; |
| [_container addSubview:_floatingButton]; |
| |
| // Create and add activity indicator to the container. |
| _activityIndicator = |
| [[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, |
| @"subtitle" : _subtitleLabel, |
| @"button" : _textButton, |
| @"floatingButton" : _floatingButton, |
| @"activityIndicator" : _activityIndicator, |
| }; |
| 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 }, |
| @{ @"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)]; |
| subtitleString = [[NSMutableAttributedString alloc] |
| initWithString:l10n_util::GetNSString( |
| IDS_IOS_TAB_SWITCHER_SIGN_IN_ACCOUNT_PROMO)]; |
| 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)]; |
| subtitleString = [[NSMutableAttributedString alloc] |
| initWithString:l10n_util::GetNSString( |
| IDS_IOS_TAB_SWITCHER_SYNC_IS_OFF)]; |
| 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)]; |
| subtitleString = [[NSMutableAttributedString alloc] |
| initWithString:l10n_util::GetNSString( |
| IDS_IOS_OPEN_TABS_NO_SESSION_INSTRUCTIONS)]; |
| 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)]; |
| subtitleString = [[NSMutableAttributedString alloc] |
| initWithString:l10n_util::GetNSString( |
| IDS_IOS_TAB_SWITCHER_SYNC_IS_OFF)]; |
| 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)]; |
| subtitleString = [[NSMutableAttributedString alloc] |
| initWithString:l10n_util::GetNSString( |
| IDS_IOS_TAB_SWITCHER_NO_LOCAL_NON_INCOGNITO_TABS)]; |
| 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)]; |
| subtitleString = [[NSMutableAttributedString alloc] |
| initWithString:l10n_util::GetNSString( |
| IDS_IOS_TAB_SWITCHER_NO_LOCAL_INCOGNITO_TABS)]; |
| 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; |
| }; |
| |
| 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]; |
| |
| 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")); |
| 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 |