Commit 7bef8818 authored by stkhapugin@chromium.org's avatar stkhapugin@chromium.org Committed by Commit Bot

[iOS] Create a new popup presenter for UI Refresh.

Creates a new popup presenter, renames the old one to "Legacy". Removes
existing forking on IsUIRefreshPhase1Enabled, otherwise the new class
is a copy of the Legacy one.
Adds a protocol to allow having two implementations for presenters.

This will allow not having forking everywhere in the file.

Bug: 821817
Cq-Include-Trybots: luci.chromium.try:ios-simulator-full-configs;master.tryserver.chromium.mac:ios-simulator-cronet
Change-Id: I1c3ee5c30d50123544f2288ec95d8e80e7b59032
Reviewed-on: https://chromium-review.googlesource.com/1107981
Commit-Queue: Stepan Khapugin <stkhapugin@chromium.org>
Reviewed-by: default avatarGauthier Ambard <gambard@chromium.org>
Cr-Commit-Position: refs/heads/master@{#568969}
parent 100632aa
......@@ -6,6 +6,9 @@ source_set("popup") {
sources = [
"omnibox_popup_coordinator.h",
"omnibox_popup_coordinator.mm",
"omnibox_popup_generic_presenter.h",
"omnibox_popup_legacy_presenter.h",
"omnibox_popup_legacy_presenter.mm",
"omnibox_popup_mediator.h",
"omnibox_popup_mediator.mm",
"omnibox_popup_positioner.h",
......
......@@ -8,10 +8,12 @@
#include "components/omnibox/browser/autocomplete_result.h"
#include "ios/chrome/browser/browser_state/chrome_browser_state.h"
#import "ios/chrome/browser/ui/commands/command_dispatcher.h"
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_legacy_presenter.h"
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_mediator.h"
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h"
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_controller.h"
#include "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_view_ios.h"
#include "ios/chrome/browser/ui/ui_util.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......@@ -58,10 +60,15 @@
self.mediator.incognito = self.browserState->IsOffTheRecord();
self.mediator.consumer = self.popupViewController;
self.mediator.presenter = [[OmniboxPopupPresenter alloc]
initWithPopupPositioner:self.positioner
popupViewController:self.popupViewController];
if (IsUIRefreshPhase1Enabled()) {
self.mediator.presenter = [[OmniboxPopupPresenter alloc]
initWithPopupPositioner:self.positioner
popupViewController:self.popupViewController];
} else {
self.mediator.presenter = [[OmniboxPopupLegacyPresenter alloc]
initWithPopupPositioner:self.positioner
popupViewController:self.popupViewController];
}
self.popupViewController.imageRetriever = self.mediator;
self.popupViewController.delegate = self.mediator;
[self.dispatcher
......
// Copyright 2018 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.
#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_GENERIC_PRESENTER_H_
#define IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_GENERIC_PRESENTER_H_
#import <UIKit/UIKit.h>
@protocol OmniboxPopupPositioner;
// A generic omnibox popup presenter, serving as a common API for the UI Refresh
// and Legacy implementations.
@protocol OmniboxPopupGenericPresenter<NSObject>
// Updates appearance depending on the content size of the presented view
// controller by changing the visible height of the popup. When the popup was
// not previously shown, it will appear with "expansion" animation.
- (void)updateHeightAndAnimateAppearanceIfNecessary;
// Call this to hide the popup with animation.
- (void)animateCollapse;
@end
#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_GENERIC_PRESENTER_H_
// Copyright 2017 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.
#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_LEGACY_PRESENTER_H_
#define IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_LEGACY_PRESENTER_H_
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_generic_presenter.h"
// The pre-UI Refresh implementation of the popup presenter.
@interface OmniboxPopupLegacyPresenter : NSObject<OmniboxPopupGenericPresenter>
- (instancetype)initWithPopupPositioner:(id<OmniboxPopupPositioner>)positioner
popupViewController:(UIViewController*)viewController;
@end
#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_POPUP_OMNIBOX_POPUP_LEGACY_PRESENTER_H_
// Copyright 2017 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/omnibox/popup/omnibox_popup_legacy_presenter.h"
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_positioner.h"
#import "ios/chrome/browser/ui/toolbar/public/features.h"
#include "ios/chrome/browser/ui/ui_util.h"
#import "ios/chrome/browser/ui/uikit_ui_util.h"
#include "ios/chrome/browser/ui/util/constraints_ui_util.h"
#import "ios/chrome/browser/ui/util/named_guide.h"
#include "ios/chrome/grit/ios_theme_resources.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
#endif
namespace {
const CGFloat kExpandAnimationDuration = 0.1;
const CGFloat kCollapseAnimationDuration = 0.05;
const CGFloat kShadowHeight = 10;
const CGFloat kiPadVerticalOffset = 3;
NS_INLINE CGFloat BottomPadding() {
return IsIPadIdiom() ? kShadowHeight : 0;
}
} // namespace
@interface OmniboxPopupLegacyPresenter ()
// Constraint for the bottom anchor of the popup.
@property(nonatomic, strong) NSLayoutConstraint* bottomConstraint;
@property(nonatomic, weak) id<OmniboxPopupPositioner> positioner;
@property(nonatomic, weak) UIViewController* viewController;
@property(nonatomic, strong) UIView* popupContainerView;
@end
@implementation OmniboxPopupLegacyPresenter
@synthesize viewController = _viewController;
@synthesize positioner = _positioner;
@synthesize popupContainerView = _popupContainerView;
@synthesize bottomConstraint = _bottomConstraint;
- (instancetype)initWithPopupPositioner:(id<OmniboxPopupPositioner>)positioner
popupViewController:(UIViewController*)viewController {
self = [super init];
if (self) {
_positioner = positioner;
_viewController = viewController;
// Set up a container for presentation.
UIView* popupContainer = [[UIView alloc] init];
_popupContainerView = popupContainer;
popupContainer.translatesAutoresizingMaskIntoConstraints = NO;
popupContainer.layoutMargins = UIEdgeInsetsMake(0, 0, BottomPadding(), 0);
// Add the view controller's view to the container.
[popupContainer addSubview:viewController.view];
viewController.view.translatesAutoresizingMaskIntoConstraints = NO;
AddSameConstraintsToSidesWithInsets(
viewController.view, popupContainer,
LayoutSides::kLeading | LayoutSides::kTrailing | LayoutSides::kBottom |
LayoutSides::kTop,
ChromeDirectionalEdgeInsetsMake(0, 0, BottomPadding(), 0));
// Add a shadow.
UIImageView* shadowView = [[UIImageView alloc]
initWithImage:NativeImage(IDR_IOS_TOOLBAR_SHADOW_FULL_BLEED)];
[shadowView setUserInteractionEnabled:NO];
[shadowView setTranslatesAutoresizingMaskIntoConstraints:NO];
[popupContainer addSubview:shadowView];
// On iPhone, the shadow is on the top of the popup, as if it's cast by
// the omnibox; on iPad, the shadow is cast by the popup instead, so it's
// below the popup.
AddSameConstraintsToSides(shadowView, popupContainer,
LayoutSides::kLeading | LayoutSides::kTrailing);
AddSameConstraintsToSides(
shadowView, popupContainer,
IsIPadIdiom() ? LayoutSides::kBottom : LayoutSides::kTop);
}
return self;
}
- (void)updateHeightAndAnimateAppearanceIfNecessary {
UIView* popup = self.popupContainerView;
if (!popup.superview) {
UIViewController* parentVC = [self.positioner popupParentViewController];
[parentVC addChildViewController:self.viewController];
[[self.positioner popupParentView] addSubview:popup];
[self.viewController didMoveToParentViewController:parentVC];
[self initialLayout];
}
if (!IsIPadIdiom()) {
self.bottomConstraint.active = YES;
}
if (popup.bounds.size.height == 0) {
// Animate if it expanding.
[UIView animateWithDuration:kExpandAnimationDuration
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[[popup superview] layoutIfNeeded];
}
completion:nil];
}
}
- (void)animateCollapse {
UIView* retainedPopupView = self.popupContainerView;
UIViewController* retainedViewController = self.viewController;
if (!IsIPadIdiom()) {
self.bottomConstraint.active = NO;
}
[UIView animateWithDuration:kCollapseAnimationDuration
delay:0
options:UIViewAnimationOptionCurveEaseInOut
animations:^{
[[self.popupContainerView superview] layoutIfNeeded];
}
completion:^(BOOL) {
[retainedViewController willMoveToParentViewController:nil];
[retainedPopupView removeFromSuperview];
[retainedViewController removeFromParentViewController];
}];
}
#pragma mark - Private
// Layouts the popup when it is just added to the view hierarchy.
- (void)initialLayout {
UIView* popup = self.popupContainerView;
// Creates the constraints if the view is newly added to the view hierarchy.
// On iPad the height of the popup is fixed.
// This constraint will only be activated on iPhone as the popup is taking
// the full height.
self.bottomConstraint = [popup.bottomAnchor
constraintEqualToAnchor:[popup superview].bottomAnchor];
// Position the top anchor of the popup relatively to the layout guide
// positioned on the omnibox.
UILayoutGuide* topLayout =
[NamedGuide guideWithName:kOmniboxGuide view:popup];
NSLayoutConstraint* topConstraint =
[popup.topAnchor constraintEqualToAnchor:topLayout.bottomAnchor];
if (IsIPadIdiom()) {
topConstraint.constant = kiPadVerticalOffset;
}
[NSLayoutConstraint activateConstraints:@[
[popup.leadingAnchor constraintEqualToAnchor:popup.superview.leadingAnchor],
[popup.trailingAnchor
constraintEqualToAnchor:popup.superview.trailingAnchor],
topConstraint,
]];
[popup layoutIfNeeded];
[[popup superview] layoutIfNeeded];
}
@end
......@@ -11,7 +11,7 @@
#import "ios/chrome/browser/ui/omnibox/autocomplete_result_consumer.h"
#import "ios/chrome/browser/ui/omnibox/image_retriever.h"
@class OmniboxPopupPresenter;
@protocol OmniboxPopupGenericPresenter;
namespace image_fetcher {
class IOSImageDataFetcherWrapper;
......@@ -54,7 +54,7 @@ class OmniboxPopupMediatorDelegate {
@property(nonatomic, assign, getter=isOpen) BOOL open;
// Presenter for the popup, handling the positioning and the presentation
// animations.
@property(nonatomic, strong) OmniboxPopupPresenter* presenter;
@property(nonatomic, strong) id<OmniboxPopupGenericPresenter> presenter;
@end
......
......@@ -11,7 +11,7 @@
#include "components/omnibox/browser/autocomplete_match.h"
#include "components/omnibox/browser/autocomplete_result.h"
#import "ios/chrome/browser/ui/omnibox/autocomplete_match_formatter.h"
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_presenter.h"
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_generic_presenter.h"
#if !defined(__has_feature) || !__has_feature(objc_arc)
#error "This file requires ARC support."
......
// Copyright 2017 The Chromium Authors. All rights reserved.
// Copyright 2018 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.
#ifndef IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_POPUP_PRESENTER_H_
#define IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_POPUP_PRESENTER_H_
#import <UIKit/UIKit.h>
#import "ios/chrome/browser/ui/omnibox/popup/omnibox_popup_generic_presenter.h"
@protocol OmniboxPopupPositioner;
@interface OmniboxPopupPresenter : NSObject
// The UI Refresh implementation of the popup presenter.
@interface OmniboxPopupPresenter : NSObject<OmniboxPopupGenericPresenter>
- (instancetype)initWithPopupPositioner:(id<OmniboxPopupPositioner>)positioner
popupViewController:(UIViewController*)viewController;
// Updates appearance depending on the content size of the presented view
// controller by changing the visible height of the popup. When the popup was
// not previously shown, it will appear with "expansion" animation.
- (void)updateHeightAndAnimateAppearanceIfNecessary;
// Call this to hide the popup with animation.
- (void)animateCollapse;
@end
#endif // IOS_CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_POPUP_PRESENTER_H_
// Copyright 2017 The Chromium Authors. All rights reserved.
// Copyright 2018 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.
......@@ -20,8 +20,7 @@ namespace {
const CGFloat kExpandAnimationDuration = 0.1;
const CGFloat kCollapseAnimationDuration = 0.05;
const CGFloat kShadowHeight = 10;
const CGFloat kiPadVerticalOffset = 3;
const CGFloat kRefreshVerticalOffset = 6;
const CGFloat kVerticalOffset = 6;
NS_INLINE CGFloat BottomPadding() {
return IsIPadIdiom() ? kShadowHeight : 0;
}
......@@ -149,13 +148,7 @@ NS_INLINE CGFloat BottomPadding() {
[NamedGuide guideWithName:kOmniboxGuide view:popup];
NSLayoutConstraint* topConstraint =
[popup.topAnchor constraintEqualToAnchor:topLayout.bottomAnchor];
if (IsUIRefreshPhase1Enabled()) {
// TODO(crbug.com/846337) Remove this workaround and clean up popup
// presentation.
topConstraint.constant = kRefreshVerticalOffset;
} else if (IsIPadIdiom()) {
topConstraint.constant = kiPadVerticalOffset;
}
topConstraint.constant = kVerticalOffset;
[NSLayoutConstraint activateConstraints:@[
[popup.leadingAnchor constraintEqualToAnchor:popup.superview.leadingAnchor],
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment