[iOS][Thumb Strip] Open/close thumb strip when scrolling in web view
The new ThumbStripMediator handles observing the regular/incognito WebStateLists to add the ViewRevealingVerticalPanHandler as a scrollViewProxy observer. This allows it to get scroll delegate callbacks from the active webstate. This CL also slightly fixes the BVC thumb strip hide/reveal behavior to correctly change the scroll view's content insets as well as the content offset. Bug: 1094335 Change-Id: I006a3e72a06b1e327ce0984cf84bc69c2e95fe7a Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2563556 Reviewed-by: Gauthier Ambard <gambard@chromium.org> Reviewed-by: Chris Lu <thegreenfrog@chromium.org> Commit-Queue: Robbie Gibson <rkgibson@google.com> Cr-Commit-Position: refs/heads/master@{#834183}
This commit is contained in:

committed by
Chromium LUCI CQ

parent
599ad0b15b
commit
609dba3217
ios/chrome/browser/ui
browser_view
gestures
BUILD.gnpan_handler_scroll_view.hpan_handler_scroll_view.mmview_revealing_vertical_pan_handler.hview_revealing_vertical_pan_handler.mm
tab_switcher
tab_grid
thumb_strip
@ -2903,6 +2903,7 @@ NSString* const kBrowserViewControllerSnackbarCategory =
|
||||
// view is taken, the snapshot will be a blank view. However, if the view's
|
||||
// parent is hidden but the view itself is not, the snapshot will not be a
|
||||
// blank view.
|
||||
[self.tabStripSnapshot removeFromSuperview];
|
||||
self.tabStripSnapshot = [self.tabStripView screenshotForAnimation];
|
||||
self.tabStripSnapshot.translatesAutoresizingMaskIntoConstraints = NO;
|
||||
self.tabStripSnapshot.transform =
|
||||
@ -2923,12 +2924,11 @@ NSString* const kBrowserViewControllerSnackbarCategory =
|
||||
// When the Fullscreen Provider is used, the web content extends up to the
|
||||
// top of the BVC view. It has a visible background and blocks the thumb
|
||||
// strip. Thus, when the view revealing process starts, the web content
|
||||
// frame must be moved down. To prevent the actual web content from jumping,
|
||||
// the content offset must be moved up by a corresponding amount.
|
||||
// frame must be moved down and the content inset is decreased. To prevent
|
||||
// the actual web content from jumping, the content offset must be moved up
|
||||
// by a corresponding amount.
|
||||
if (self.currentWebState && ![self isNTPActiveForCurrentWebState] &&
|
||||
ios::GetChromeBrowserProvider()
|
||||
->GetFullscreenProvider()
|
||||
->IsInitialized()) {
|
||||
fullscreen::features::ShouldUseSmoothScrolling()) {
|
||||
CGFloat toolbarHeight = [self expandedTopToolbarHeight];
|
||||
CGRect webStateViewFrame = UIEdgeInsetsInsetRect(
|
||||
[self viewForWebState:self.currentWebState].frame,
|
||||
@ -2940,6 +2940,12 @@ NSString* const kBrowserViewControllerSnackbarCategory =
|
||||
CGPoint scrollOffset = scrollProxy.contentOffset;
|
||||
scrollOffset.y += toolbarHeight;
|
||||
scrollProxy.contentOffset = scrollOffset;
|
||||
|
||||
// TODO(crbug.com/1155536): Inform FullscreenController about these
|
||||
// changes and allow it to calculate the correct overall contentInset.
|
||||
UIEdgeInsets contentInset = scrollProxy.contentInset;
|
||||
contentInset.top -= toolbarHeight;
|
||||
scrollProxy.contentInset = contentInset;
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3000,6 +3006,10 @@ NSString* const kBrowserViewControllerSnackbarCategory =
|
||||
|
||||
CRWWebViewScrollViewProxy* scrollProxy =
|
||||
self.currentWebState->GetWebViewProxy().scrollViewProxy;
|
||||
UIEdgeInsets contentInset = scrollProxy.contentInset;
|
||||
contentInset.top += toolbarHeight;
|
||||
scrollProxy.contentInset = contentInset;
|
||||
|
||||
CGPoint scrollOffset = scrollProxy.contentOffset;
|
||||
scrollOffset.y -= toolbarHeight;
|
||||
scrollProxy.contentOffset = scrollOffset;
|
||||
|
@ -8,11 +8,16 @@ source_set("gestures") {
|
||||
sources = [
|
||||
"layout_switcher.h",
|
||||
"layout_switcher_provider.h",
|
||||
"pan_handler_scroll_view.h",
|
||||
"pan_handler_scroll_view.mm",
|
||||
"view_revealing_animatee.h",
|
||||
"view_revealing_vertical_pan_handler.h",
|
||||
"view_revealing_vertical_pan_handler.mm",
|
||||
]
|
||||
deps = [ "//base" ]
|
||||
deps = [
|
||||
"//base",
|
||||
"//ios/web/public/ui",
|
||||
]
|
||||
configs += [ "//build/config/compiler:enable_arc" ]
|
||||
}
|
||||
|
||||
|
28
ios/chrome/browser/ui/gestures/pan_handler_scroll_view.h
Normal file
28
ios/chrome/browser/ui/gestures/pan_handler_scroll_view.h
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright 2020 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_GESTURES_PAN_HANDLER_SCROLL_VIEW_H_
|
||||
#define IOS_CHROME_BROWSER_UI_GESTURES_PAN_HANDLER_SCROLL_VIEW_H_
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
|
||||
@class CRWWebViewScrollViewProxy;
|
||||
|
||||
// This private class handles forwarding updates to these properties to an
|
||||
// underlying |UIScrollView| or |CRWWebViewScrollViewProxy|.
|
||||
@interface PanHandlerScrollView : NSObject
|
||||
|
||||
@property(nonatomic) CGPoint contentOffset;
|
||||
@property(nonatomic, assign) UIEdgeInsets contentInset;
|
||||
@property(nonatomic, readonly) UIPanGestureRecognizer* panGestureRecognizer;
|
||||
@property(nonatomic, readonly, getter=isDecelerating) BOOL decelerating;
|
||||
@property(nonatomic, readonly, getter=isDragging) BOOL dragging;
|
||||
|
||||
- (instancetype)initWithScrollView:(UIScrollView*)scrollView;
|
||||
- (instancetype)initWithWebViewScrollViewProxy:
|
||||
(CRWWebViewScrollViewProxy*)scrollViewProxy;
|
||||
|
||||
@end
|
||||
|
||||
#endif // IOS_CHROME_BROWSER_UI_GESTURES_PAN_HANDLER_SCROLL_VIEW_H_
|
72
ios/chrome/browser/ui/gestures/pan_handler_scroll_view.mm
Normal file
72
ios/chrome/browser/ui/gestures/pan_handler_scroll_view.mm
Normal file
@ -0,0 +1,72 @@
|
||||
// Copyright 2020 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/gestures/pan_handler_scroll_view.h"
|
||||
|
||||
#import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h"
|
||||
|
||||
#if !defined(__has_feature) || !__has_feature(objc_arc)
|
||||
#error "This file requires ARC support."
|
||||
#endif
|
||||
|
||||
@interface PanHandlerScrollView ()
|
||||
|
||||
@property(nonatomic, strong) UIScrollView* scrollView;
|
||||
@property(nonatomic, strong) CRWWebViewScrollViewProxy* scrollViewProxy;
|
||||
|
||||
@end
|
||||
|
||||
@implementation PanHandlerScrollView
|
||||
|
||||
- (instancetype)initWithScrollView:(UIScrollView*)scrollView {
|
||||
if (self = [super init]) {
|
||||
_scrollView = scrollView;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (instancetype)initWithWebViewScrollViewProxy:
|
||||
(CRWWebViewScrollViewProxy*)scrollViewProxy {
|
||||
if (self = [super init]) {
|
||||
_scrollViewProxy = scrollViewProxy;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (CGPoint)contentOffset {
|
||||
return (self.scrollView) ? self.scrollView.contentOffset
|
||||
: self.scrollViewProxy.contentOffset;
|
||||
}
|
||||
|
||||
- (void)setContentOffset:(CGPoint)contentOffset {
|
||||
self.scrollView.contentOffset = contentOffset;
|
||||
self.scrollViewProxy.contentOffset = contentOffset;
|
||||
}
|
||||
|
||||
- (UIEdgeInsets)contentInset {
|
||||
return (self.scrollView) ? self.scrollView.contentInset
|
||||
: self.scrollViewProxy.contentInset;
|
||||
}
|
||||
|
||||
- (void)setContentInset:(UIEdgeInsets)contentInset {
|
||||
self.scrollView.contentInset = contentInset;
|
||||
self.scrollViewProxy.contentInset = contentInset;
|
||||
}
|
||||
|
||||
- (UIPanGestureRecognizer*)panGestureRecognizer {
|
||||
return (self.scrollView) ? self.scrollView.panGestureRecognizer
|
||||
: self.scrollViewProxy.panGestureRecognizer;
|
||||
}
|
||||
|
||||
- (BOOL)isDecelerating {
|
||||
return (self.scrollView) ? self.scrollView.isDecelerating
|
||||
: self.scrollViewProxy.isDecelerating;
|
||||
}
|
||||
|
||||
- (BOOL)isDragging {
|
||||
return (self.scrollView) ? self.scrollView.isDragging
|
||||
: self.scrollViewProxy.isDragging;
|
||||
}
|
||||
|
||||
@end
|
@ -9,6 +9,7 @@
|
||||
|
||||
#import "ios/chrome/browser/ui/gestures/layout_switcher_provider.h"
|
||||
#import "ios/chrome/browser/ui/gestures/view_revealing_animatee.h"
|
||||
#import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h"
|
||||
|
||||
// Responsible for handling vertical pan gestures to reveal/hide a view behind
|
||||
// another.
|
||||
@ -21,7 +22,8 @@
|
||||
// TODO(crbug.com/1123512): Add support for going straight from a Hidden state
|
||||
// to a revealed state (and vice-versa) if the gesture's translation and
|
||||
// velocity are enough to trigger such transition.
|
||||
@interface ViewRevealingVerticalPanHandler : NSObject <UIScrollViewDelegate>
|
||||
@interface ViewRevealingVerticalPanHandler
|
||||
: NSObject <CRWWebViewScrollViewProxyObserver, UIScrollViewDelegate>
|
||||
|
||||
// |peekedHeight| is the height of the view when peeked (partially revealed).
|
||||
// |revealedCoverHeight| is the height of the cover view that remains visible
|
||||
|
@ -4,9 +4,11 @@
|
||||
|
||||
#import "ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h"
|
||||
|
||||
#include "base/logging.h"
|
||||
#import "base/notreached.h"
|
||||
#include "base/numerics/ranges.h"
|
||||
#import "ios/chrome/browser/ui/gestures/layout_switcher.h"
|
||||
#import "ios/chrome/browser/ui/gestures/pan_handler_scroll_view.h"
|
||||
|
||||
#if !defined(__has_feature) || !__has_feature(objc_arc)
|
||||
#error "This file requires ARC support."
|
||||
@ -366,27 +368,86 @@ const CGFloat kAnimationDuration = 0.25f;
|
||||
#pragma mark - UIScrollViewDelegate
|
||||
|
||||
- (void)scrollViewWillBeginDragging:(UIScrollView*)scrollView {
|
||||
PanHandlerScrollView* view =
|
||||
[[PanHandlerScrollView alloc] initWithScrollView:scrollView];
|
||||
[self panHandlerScrollViewWillBeginDragging:view];
|
||||
}
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView*)scrollView {
|
||||
PanHandlerScrollView* view =
|
||||
[[PanHandlerScrollView alloc] initWithScrollView:scrollView];
|
||||
[self panHandlerScrollViewDidScroll:view];
|
||||
}
|
||||
|
||||
- (void)scrollViewWillEndDragging:(UIScrollView*)scrollView
|
||||
withVelocity:(CGPoint)velocity
|
||||
targetContentOffset:(inout CGPoint*)targetContentOffset {
|
||||
PanHandlerScrollView* view =
|
||||
[[PanHandlerScrollView alloc] initWithScrollView:scrollView];
|
||||
[self panHandlerScrollViewWillEndDragging:view
|
||||
withVelocity:velocity
|
||||
targetContentOffset:targetContentOffset];
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDragging:(UIScrollView*)scrollView
|
||||
willDecelerate:(BOOL)decelerate {
|
||||
// No-op.
|
||||
}
|
||||
|
||||
#pragma mark - CRWWebViewScrollViewProxyObserver
|
||||
|
||||
- (void)webViewScrollViewWillBeginDragging:
|
||||
(CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
|
||||
PanHandlerScrollView* view = [[PanHandlerScrollView alloc]
|
||||
initWithWebViewScrollViewProxy:webViewScrollViewProxy];
|
||||
[self panHandlerScrollViewWillBeginDragging:view];
|
||||
}
|
||||
|
||||
- (void)webViewScrollViewDidScroll:
|
||||
(CRWWebViewScrollViewProxy*)webViewScrollViewProxy {
|
||||
PanHandlerScrollView* view = [[PanHandlerScrollView alloc]
|
||||
initWithWebViewScrollViewProxy:webViewScrollViewProxy];
|
||||
[self panHandlerScrollViewDidScroll:view];
|
||||
}
|
||||
|
||||
- (void)webViewScrollViewWillEndDragging:
|
||||
(CRWWebViewScrollViewProxy*)webViewScrollViewProxy
|
||||
withVelocity:(CGPoint)velocity
|
||||
targetContentOffset:(inout CGPoint*)targetContentOffset {
|
||||
PanHandlerScrollView* view = [[PanHandlerScrollView alloc]
|
||||
initWithWebViewScrollViewProxy:webViewScrollViewProxy];
|
||||
[self panHandlerScrollViewWillEndDragging:view
|
||||
withVelocity:velocity
|
||||
targetContentOffset:targetContentOffset];
|
||||
}
|
||||
|
||||
#pragma mark - UIScrollViewDelegate + CRWWebViewScrollViewProxyObserver
|
||||
|
||||
- (void)panHandlerScrollViewWillBeginDragging:
|
||||
(PanHandlerScrollView*)scrollView {
|
||||
switch (self.currentState) {
|
||||
case ViewRevealState::Hidden:
|
||||
case ViewRevealState::Hidden: {
|
||||
// The transition out of hidden state can only start if the scroll view
|
||||
// starts dragging from the top.
|
||||
if (!self.animator.isRunning && scrollView.contentOffset.y != 0) {
|
||||
CGFloat contentOffsetY =
|
||||
scrollView.contentOffset.y + scrollView.contentInset.top;
|
||||
if (contentOffsetY != 0) {
|
||||
return;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case ViewRevealState::Peeked:
|
||||
break;
|
||||
case ViewRevealState::Revealed:
|
||||
// The scroll views should be covered in Revealed state, so should not
|
||||
// be able to be scrolled.
|
||||
NOTREACHED();
|
||||
break;
|
||||
}
|
||||
[self panGestureBegan];
|
||||
self.lastScrollOffset = scrollView.contentOffset;
|
||||
}
|
||||
|
||||
- (void)scrollViewDidScroll:(UIScrollView*)scrollView {
|
||||
- (void)panHandlerScrollViewDidScroll:(PanHandlerScrollView*)scrollView {
|
||||
// These delegate methods are approximating the pan gesture handling from
|
||||
// above, so only change things if the user is actively scrolling.
|
||||
if (!scrollView.isDragging) {
|
||||
@ -404,15 +465,16 @@ const CGFloat kAnimationDuration = 0.25f;
|
||||
if (self.animator.fractionComplete > 0 &&
|
||||
self.animator.fractionComplete < 1) {
|
||||
CGPoint currentScrollOffset = scrollView.contentOffset;
|
||||
currentScrollOffset.y = std::max(self.lastScrollOffset.y, 0.0);
|
||||
currentScrollOffset.y = self.lastScrollOffset.y;
|
||||
scrollView.contentOffset = currentScrollOffset;
|
||||
}
|
||||
self.lastScrollOffset = scrollView.contentOffset;
|
||||
}
|
||||
|
||||
- (void)scrollViewWillEndDragging:(UIScrollView*)scrollView
|
||||
withVelocity:(CGPoint)velocity
|
||||
targetContentOffset:(inout CGPoint*)targetContentOffset {
|
||||
- (void)panHandlerScrollViewWillEndDragging:(PanHandlerScrollView*)scrollView
|
||||
withVelocity:(CGPoint)velocity
|
||||
targetContentOffset:
|
||||
(inout CGPoint*)targetContentOffset {
|
||||
if (self.currentState == ViewRevealState::Hidden &&
|
||||
self.animator.state != UIViewAnimatingStateActive) {
|
||||
return;
|
||||
@ -429,9 +491,4 @@ const CGFloat kAnimationDuration = 0.25f;
|
||||
[self panGestureEndedWithTranslation:translationY velocity:velocityY];
|
||||
}
|
||||
|
||||
- (void)scrollViewDidEndDragging:(UIScrollView*)scrollView
|
||||
willDecelerate:(BOOL)decelerate {
|
||||
// No-op.
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -148,6 +148,7 @@
|
||||
- (void)setIncognitoBrowser:(Browser*)incognitoBrowser {
|
||||
DCHECK(self.incognitoTabsMediator);
|
||||
self.incognitoTabsMediator.browser = incognitoBrowser;
|
||||
self.thumbStripCoordinator.incognitoBrowser = incognitoBrowser;
|
||||
}
|
||||
|
||||
- (void)stopChildCoordinatorsWithCompletion:(ProceduralBlock)completion {
|
||||
@ -400,6 +401,8 @@
|
||||
self.thumbStripCoordinator = [[ThumbStripCoordinator alloc]
|
||||
initWithBaseViewController:baseViewController
|
||||
browser:self.browser];
|
||||
self.thumbStripCoordinator.regularBrowser = _regularBrowser;
|
||||
self.thumbStripCoordinator.incognitoBrowser = _incognitoBrowser;
|
||||
[self.thumbStripCoordinator start];
|
||||
self.thumbStripCoordinator.panHandler.layoutSwitcherProvider =
|
||||
baseViewController;
|
||||
|
@ -9,12 +9,18 @@ source_set("thumb_strip") {
|
||||
"thumb_strip_attacher.h",
|
||||
"thumb_strip_coordinator.h",
|
||||
"thumb_strip_coordinator.mm",
|
||||
"thumb_strip_mediator.h",
|
||||
"thumb_strip_mediator.mm",
|
||||
]
|
||||
deps = [
|
||||
"//base",
|
||||
"//ios/chrome/browser/main:public",
|
||||
"//ios/chrome/browser/ui/coordinators:chrome_coordinators",
|
||||
"//ios/chrome/browser/ui/gestures",
|
||||
"//ios/chrome/browser/ui/tab_switcher/tab_grid/grid:grid_ui_constants",
|
||||
"//ios/chrome/browser/web_state_list",
|
||||
"//ios/web/public",
|
||||
"//ios/web/public/ui",
|
||||
]
|
||||
configs += [ "//build/config/compiler:enable_arc" ]
|
||||
}
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#import "ios/chrome/browser/ui/coordinators/chrome_coordinator.h"
|
||||
|
||||
@class ThumbStripCoordinator;
|
||||
@class ViewRevealingVerticalPanHandler;
|
||||
|
||||
// Coordinator for the thumb strip, which is a 1-row horizontal display of tab
|
||||
@ -19,6 +18,13 @@
|
||||
// The thumb strip's pan gesture handler.
|
||||
@property(nonatomic, strong) ViewRevealingVerticalPanHandler* panHandler;
|
||||
|
||||
// The regular browser used to observe scroll events to show/hide the thumb
|
||||
// strip.
|
||||
@property(nonatomic, assign) Browser* regularBrowser;
|
||||
// The incognito browser used to observe scroll events to show/hide the thumb
|
||||
// strip.
|
||||
@property(nonatomic, assign) Browser* incognitoBrowser;
|
||||
|
||||
@end
|
||||
|
||||
#endif // IOS_CHROME_BROWSER_UI_THUMB_STRIP_THUMB_STRIP_COORDINATOR_H_
|
||||
|
@ -4,8 +4,10 @@
|
||||
|
||||
#import "ios/chrome/browser/ui/thumb_strip/thumb_strip_coordinator.h"
|
||||
|
||||
#import "ios/chrome/browser/main/browser.h"
|
||||
#import "ios/chrome/browser/ui/gestures/view_revealing_vertical_pan_handler.h"
|
||||
#import "ios/chrome/browser/ui/tab_switcher/tab_grid/grid/grid_constants.h"
|
||||
#import "ios/chrome/browser/ui/thumb_strip/thumb_strip_mediator.h"
|
||||
|
||||
#if !defined(__has_feature) || !__has_feature(objc_arc)
|
||||
#error "This file requires ARC support."
|
||||
@ -19,6 +21,8 @@ const CGFloat kThumbStripHeight = 168.0f + 22.0f + 22.0f;
|
||||
|
||||
@interface ThumbStripCoordinator ()
|
||||
|
||||
@property(nonatomic, strong) ThumbStripMediator* mediator;
|
||||
|
||||
@end
|
||||
|
||||
@implementation ThumbStripCoordinator
|
||||
@ -31,10 +35,27 @@ const CGFloat kThumbStripHeight = 168.0f + 22.0f + 22.0f;
|
||||
initWithPeekedHeight:kThumbStripHeight
|
||||
revealedCoverHeight:kBVCHeightTabGrid
|
||||
baseViewHeight:baseViewHeight];
|
||||
|
||||
self.mediator = [[ThumbStripMediator alloc] init];
|
||||
if (self.regularBrowser) {
|
||||
self.mediator.regularWebStateList = self.regularBrowser->GetWebStateList();
|
||||
}
|
||||
if (self.incognitoBrowser) {
|
||||
self.mediator.incognitoWebStateList =
|
||||
self.incognitoBrowser->GetWebStateList();
|
||||
}
|
||||
self.mediator.webViewScrollViewObserver = self.panHandler;
|
||||
}
|
||||
|
||||
- (void)stop {
|
||||
self.panHandler = nil;
|
||||
self.mediator = nil;
|
||||
}
|
||||
|
||||
- (void)setIncognitoBrowser:(Browser*)incognitoBrowser {
|
||||
_incognitoBrowser = incognitoBrowser;
|
||||
self.mediator.incognitoWebStateList =
|
||||
_incognitoBrowser ? _incognitoBrowser->GetWebStateList() : nullptr;
|
||||
}
|
||||
|
||||
@end
|
||||
|
29
ios/chrome/browser/ui/thumb_strip/thumb_strip_mediator.h
Normal file
29
ios/chrome/browser/ui/thumb_strip/thumb_strip_mediator.h
Normal file
@ -0,0 +1,29 @@
|
||||
// Copyright 2020 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_THUMB_STRIP_THUMB_STRIP_MEDIATOR_H_
|
||||
#define IOS_CHROME_BROWSER_UI_THUMB_STRIP_THUMB_STRIP_MEDIATOR_H_
|
||||
|
||||
#include <UIKit/UIKit.h>
|
||||
|
||||
@protocol CRWWebViewScrollViewProxyObserver;
|
||||
class WebStateList;
|
||||
|
||||
// Mediator for the thumb strip. Handles observing changes in the active web
|
||||
// state.
|
||||
@interface ThumbStripMediator : NSObject
|
||||
|
||||
// The regular web state list to observe.
|
||||
@property(nonatomic, assign) WebStateList* regularWebStateList;
|
||||
// The incognito web state list to observe.
|
||||
@property(nonatomic, assign) WebStateList* incognitoWebStateList;
|
||||
|
||||
// The observer to register/deregister as CRWWebViewScrollViewProxyObserver for
|
||||
// the active webstates in the given WebStateLists.
|
||||
@property(nonatomic, weak) id<CRWWebViewScrollViewProxyObserver>
|
||||
webViewScrollViewObserver;
|
||||
|
||||
@end
|
||||
|
||||
#endif // IOS_CHROME_BROWSER_UI_THUMB_STRIP_THUMB_STRIP_MEDIATOR_H_
|
121
ios/chrome/browser/ui/thumb_strip/thumb_strip_mediator.mm
Normal file
121
ios/chrome/browser/ui/thumb_strip/thumb_strip_mediator.mm
Normal file
@ -0,0 +1,121 @@
|
||||
// Copyright 2020 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/thumb_strip/thumb_strip_mediator.h"
|
||||
|
||||
#include "ios/chrome/browser/web_state_list/web_state_list.h"
|
||||
#import "ios/chrome/browser/web_state_list/web_state_list_observer_bridge.h"
|
||||
#import "ios/web/public/ui/crw_web_view_proxy.h"
|
||||
#import "ios/web/public/ui/crw_web_view_scroll_view_proxy.h"
|
||||
#import "ios/web/public/web_state.h"
|
||||
|
||||
#if !defined(__has_feature) || !__has_feature(objc_arc)
|
||||
#error "This file requires ARC support."
|
||||
#endif
|
||||
|
||||
@interface ThumbStripMediator () <WebStateListObserving> {
|
||||
std::unique_ptr<WebStateListObserverBridge> _webStateListObserver;
|
||||
}
|
||||
@end
|
||||
|
||||
@implementation ThumbStripMediator
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
_webStateListObserver = std::make_unique<WebStateListObserverBridge>(self);
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)dealloc {
|
||||
if (_regularWebStateList) {
|
||||
_regularWebStateList->RemoveObserver(_webStateListObserver.get());
|
||||
}
|
||||
if (_incognitoWebStateList) {
|
||||
_incognitoWebStateList->RemoveObserver(_webStateListObserver.get());
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setRegularWebStateList:(WebStateList*)regularWebStateList {
|
||||
if (_regularWebStateList) {
|
||||
_regularWebStateList->RemoveObserver(_webStateListObserver.get());
|
||||
[self removeObserverFromWebState:_regularWebStateList->GetActiveWebState()];
|
||||
}
|
||||
|
||||
_regularWebStateList = regularWebStateList;
|
||||
|
||||
if (_regularWebStateList) {
|
||||
_regularWebStateList->AddObserver(_webStateListObserver.get());
|
||||
[self addObserverToWebState:_regularWebStateList->GetActiveWebState()];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setIncognitoWebStateList:(WebStateList*)incognitoWebStateList {
|
||||
if (_incognitoWebStateList) {
|
||||
_incognitoWebStateList->RemoveObserver(_webStateListObserver.get());
|
||||
[self
|
||||
removeObserverFromWebState:_incognitoWebStateList->GetActiveWebState()];
|
||||
}
|
||||
|
||||
_incognitoWebStateList = incognitoWebStateList;
|
||||
|
||||
if (_incognitoWebStateList) {
|
||||
_incognitoWebStateList->AddObserver(_webStateListObserver.get());
|
||||
[self addObserverToWebState:_incognitoWebStateList->GetActiveWebState()];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setWebViewScrollViewObserver:
|
||||
(id<CRWWebViewScrollViewProxyObserver>)observer {
|
||||
if (self.incognitoWebStateList) {
|
||||
[self removeObserverFromWebState:self.incognitoWebStateList
|
||||
->GetActiveWebState()];
|
||||
}
|
||||
if (self.regularWebStateList) {
|
||||
[self removeObserverFromWebState:self.regularWebStateList
|
||||
->GetActiveWebState()];
|
||||
}
|
||||
|
||||
_webViewScrollViewObserver = observer;
|
||||
if (self.incognitoWebStateList) {
|
||||
[self
|
||||
addObserverToWebState:self.incognitoWebStateList->GetActiveWebState()];
|
||||
}
|
||||
if (self.regularWebStateList) {
|
||||
[self addObserverToWebState:self.regularWebStateList->GetActiveWebState()];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Privates
|
||||
|
||||
// Remove |self.webViewScrollViewObserver| from the given |webState|. |webState|
|
||||
// can be nullptr.
|
||||
- (void)removeObserverFromWebState:(web::WebState*)webState {
|
||||
if (webState && self.webViewScrollViewObserver) {
|
||||
[webState->GetWebViewProxy().scrollViewProxy
|
||||
removeObserver:self.webViewScrollViewObserver];
|
||||
}
|
||||
}
|
||||
|
||||
// Add |self.webViewScrollViewObserver| to the given |webState|. |webState| can
|
||||
// be nullptr.
|
||||
- (void)addObserverToWebState:(web::WebState*)webState {
|
||||
if (webState && self.webViewScrollViewObserver) {
|
||||
[webState->GetWebViewProxy().scrollViewProxy
|
||||
addObserver:self.webViewScrollViewObserver];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - WebStateListObserving
|
||||
|
||||
- (void)webStateList:(WebStateList*)webStateList
|
||||
didChangeActiveWebState:(web::WebState*)newWebState
|
||||
oldWebState:(web::WebState*)oldWebState
|
||||
atIndex:(int)atIndex
|
||||
reason:(ActiveWebStateChangeReason)reason {
|
||||
[self removeObserverFromWebState:oldWebState];
|
||||
[self addObserverToWebState:newWebState];
|
||||
}
|
||||
|
||||
@end
|
Reference in New Issue
Block a user