Commit f0445b06 authored by gogerald's avatar gogerald Committed by Commit Bot

[StartSurface] Introduce fake search box

This is the second patch of splitting the bigger one
https://chromium-review.googlesource.com/c/chromium/src/+/1797069

It depends on
https://chromium-review.googlesource.com/c/chromium/src/+/1817106

Screenshots
https://drive.google.com/file/d/1FBGZygqGDlFA2e1Mr_81HAVWpzn_1-yc/view?usp=sharing

Additional design discussion context:
https://docs.google.com/document/d/1Igy8tZll_WtZyg7c5lxWzOYuxb3OGzJ39YcBW_em37s/edit?usp=sharing

Bug: 982018
Change-Id: Ib93ae336cd77eb89296ed5cb68b2b62f5b45b94d
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1822820
Commit-Queue: Ganggui Tang <gogerald@chromium.org>
Reviewed-by: default avatarYusuf Ozuysal <yusufo@chromium.org>
Auto-Submit: Ganggui Tang <gogerald@chromium.org>
Cr-Commit-Position: refs/heads/master@{#702978}
parent f24dc81c
......@@ -89,6 +89,7 @@ android_library("java") {
"java/src/org/chromium/chrome/features/start_surface/StartSurfaceLayout.java",
"java/src/org/chromium/chrome/features/start_surface/StartSurfaceMediator.java",
"java/src/org/chromium/chrome/features/start_surface/StartSurfaceProperties.java",
"java/src/org/chromium/chrome/features/start_surface/StartSurfaceLocationBarDelegate.java",
"java/src/org/chromium/chrome/features/start_surface/SecondaryTasksSurfaceViewBinder.java",
"java/src/org/chromium/chrome/features/start_surface/TasksSurfaceViewBinder.java",
]
......
......@@ -75,6 +75,10 @@ public class StartSurfaceCoordinator implements StartSurface {
@Nullable
private TabSwitcher.OnTabSelectingListener mOnTabSelectingListener;
// Non-null in SurfaceMode.TASKS_ONLY, SurfaceMode.TWO_PANES and SurfaceMode.SINGLE_PANE modes.
@Nullable
private StartSurfaceLocationBarDelegate mStartSurfaceLocationBarDelegate;
public StartSurfaceCoordinator(ChromeActivity activity) {
mActivity = activity;
mSurfaceMode = computeSurfaceMode();
......@@ -96,10 +100,15 @@ public class StartSurfaceCoordinator implements StartSurface {
: mExploreSurfaceCoordinator.getFeedSurfaceCreator(),
mSurfaceMode == SurfaceMode.SINGLE_PANE ? this::initializeSecondaryTasksSurface
: null,
mSurfaceMode);
mSurfaceMode, mStartSurfaceLocationBarDelegate);
}
// Implements StartSurface.
@Override
public void setStateChangeObserver(StartSurface.StateObserver observer) {
mStartSurfaceMediator.setStateChangeObserver(observer);
}
@Override
public void setOnTabSelectingListener(StartSurface.OnTabSelectingListener listener) {
if (mTasksSurface != null) {
......@@ -158,8 +167,12 @@ public class StartSurfaceCoordinator implements StartSurface {
mPropertyModel.set(TOP_BAR_HEIGHT,
mActivity.getResources().getDimensionPixelSize(R.dimen.toolbar_height_no_shadow));
mTasksSurface = TabManagementModuleProvider.getDelegate().createTasksSurface(
mActivity, mSurfaceMode == SurfaceMode.SINGLE_PANE, mPropertyModel);
// TODO(crbug.com/1000295): Formalize the way to get the location bar.
mStartSurfaceLocationBarDelegate = new StartSurfaceLocationBarDelegate(
mActivity.getToolbarManager().getToolbarLayoutForTesting().getLocationBar());
mTasksSurface = TabManagementModuleProvider.getDelegate().createTasksSurface(mActivity,
mPropertyModel, mStartSurfaceLocationBarDelegate,
mSurfaceMode == SurfaceMode.SINGLE_PANE);
// The tasks surface is added to the explore surface in the single pane mode below.
if (mSurfaceMode != SurfaceMode.SINGLE_PANE) {
......@@ -191,11 +204,12 @@ public class StartSurfaceCoordinator implements StartSurface {
private TabSwitcher.Controller initializeSecondaryTasksSurface() {
assert mSurfaceMode == SurfaceMode.SINGLE_PANE;
assert mSecondaryTasksSurface == null;
assert mStartSurfaceLocationBarDelegate != null;
PropertyModel propertyModel = new PropertyModel(TasksSurfaceProperties.ALL_KEYS);
mStartSurfaceMediator.setSecondaryTasksSurfacePropertyModel(propertyModel);
mSecondaryTasksSurface = TabManagementModuleProvider.getDelegate().createTasksSurface(
mActivity, false, propertyModel);
mActivity, propertyModel, mStartSurfaceLocationBarDelegate, false);
mSecondaryTasksSurfacePropertyModelChangeProcessor =
createTasksViewPropertyModelChangeProcessor(
mSecondaryTasksSurface.getContainerView(),
......
// Copyright 2019 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.
package org.chromium.chrome.features.start_surface;
import androidx.annotation.Nullable;
import org.chromium.chrome.browser.omnibox.LocationBar;
import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
import org.chromium.chrome.browser.tasks.TasksSurface;
/** The delegate to interact with the {@link LocationBar}. */
class StartSurfaceLocationBarDelegate
implements TasksSurface.FakeSearchBoxDelegate, StartSurfaceMediator.Delegate {
private final LocationBar mLocationBar;
StartSurfaceLocationBarDelegate(LocationBar locationBar) {
mLocationBar = locationBar;
}
// Implements TasksSurface.FakeSearchBoxDelegate.
@Override
public void requestUrlFocus(@Nullable String pastedText) {
mLocationBar.setUrlBarFocus(true);
}
// Implements StartSurfaceMediator.Delegate.
@Override
public void addUrlFocusChangeListener(UrlFocusChangeListener listener) {
mLocationBar.addUrlFocusChangeListener(listener);
}
@Override
public void removeUrlFocusChangeListener(UrlFocusChangeListener listener) {
mLocationBar.removeUrlFocusChangeListener(listener);
}
}
......@@ -4,6 +4,7 @@
package org.chromium.chrome.features.start_surface;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MORE_TABS_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
import static org.chromium.chrome.features.start_surface.StartSurfaceProperties.BOTTOM_BAR_CLICKLISTENER;
......@@ -25,10 +26,10 @@ import org.chromium.base.ContextUtils;
import org.chromium.base.ObserverList;
import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.browser.feed.FeedSurfaceCoordinator;
import org.chromium.chrome.browser.omnibox.UrlFocusChangeListener;
import org.chromium.chrome.browser.tabmodel.EmptyTabModelSelectorObserver;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil;
import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
import org.chromium.chrome.start_surface.R;
import org.chromium.ui.modelutil.PropertyModel;
......@@ -49,6 +50,21 @@ class StartSurfaceMediator
int SINGLE_PANE = 3;
}
/** The delegate to interact with the location bar. */
interface Delegate {
/**
* Add the given url focus change listener.
* @param listener The given listener.
*/
void addUrlFocusChangeListener(UrlFocusChangeListener listener);
/**
* Remove the given url focus change listener.
* @param listener The given listener.
*/
void removeUrlFocusChangeListener(UrlFocusChangeListener listener);
}
/** Interface to initialize a secondary tasks surface for more tabs. */
interface SecondaryTasksSurfaceInitializer {
/**
......@@ -74,21 +90,29 @@ class StartSurfaceMediator
@Nullable
private PropertyModel mSecondaryTasksSurfacePropertyModel;
private boolean mIsIncognito;
@Nullable
private Delegate mDelegate;
@Nullable
UrlFocusChangeListener mUrlFocusChangeListener;
@Nullable
private StartSurface.StateObserver mStateObserver;
StartSurfaceMediator(TabSwitcher.Controller controller, TabModelSelector tabModelSelector,
@Nullable PropertyModel propertyModel,
@Nullable ExploreSurfaceCoordinator.FeedSurfaceCreator feedSurfaceCreator,
@Nullable SecondaryTasksSurfaceInitializer secondaryTasksSurfaceInitializer,
@SurfaceMode int surfaceMode) {
@SurfaceMode int surfaceMode, @Nullable Delegate delegate) {
mController = controller;
mPropertyModel = propertyModel;
mFeedSurfaceCreator = feedSurfaceCreator;
mSecondaryTasksSurfaceInitializer = secondaryTasksSurfaceInitializer;
mSurfaceMode = surfaceMode;
mDelegate = delegate;
if (mPropertyModel != null) {
assert mSurfaceMode == SurfaceMode.SINGLE_PANE || mSurfaceMode == SurfaceMode.TWO_PANES
|| mSurfaceMode == SurfaceMode.TASKS_ONLY;
assert mDelegate != null;
mIsIncognito = tabModelSelector.isIncognitoSelected();
tabModelSelector.addObserver(new EmptyTabModelSelectorObserver() {
......@@ -107,6 +131,7 @@ class StartSurfaceMediator
@Override
public void onHomeButtonClicked() {
setExploreSurfaceVisibility(false);
notifyStateChange();
RecordUserAction.record("StartSurface.TwoPanes.BottomBar.TapHome");
}
......@@ -115,6 +140,7 @@ class StartSurfaceMediator
// TODO(crbug.com/982018): Hide the Tab switcher toolbar when showing
// explore surface.
setExploreSurfaceVisibility(true);
notifyStateChange();
RecordUserAction.record(
"StartSurface.TwoPanes.BottomBar.TapExploreSurface");
}
......@@ -144,10 +170,23 @@ class StartSurfaceMediator
int toolbarHeight =
ContextUtils.getApplicationContext().getResources().getDimensionPixelSize(
R.dimen.toolbar_height_no_shadow);
int topControlsHeight = ReturnToChromeExperimentsUtil.shouldShowOmniboxOnTabSwitcher()
? toolbarHeight * 2
: toolbarHeight;
mPropertyModel.set(TOP_BAR_HEIGHT, topControlsHeight);
mPropertyModel.set(TOP_BAR_HEIGHT, toolbarHeight);
mUrlFocusChangeListener = new UrlFocusChangeListener() {
@Override
public void onUrlFocusChange(boolean hasFocus) {
// No fake search box on the explore pane in two panes mode.
if (mSurfaceMode != SurfaceMode.TWO_PANES
|| !mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE)) {
mPropertyModel.set(IS_FAKE_SEARCH_BOX_VISIBLE, !hasFocus);
}
if (mPropertyModel.get(IS_SECONDARY_SURFACE_VISIBLE)) {
mSecondaryTasksSurfacePropertyModel.set(
IS_FAKE_SEARCH_BOX_VISIBLE, !hasFocus);
}
notifyStateChange();
}
};
}
mController.addOverviewModeObserver(this);
}
......@@ -160,6 +199,10 @@ class StartSurfaceMediator
mSecondaryTasksSurfacePropertyModel.set(MV_TILES_VISIBLE, false);
}
void setStateChangeObserver(StartSurface.StateObserver observer) {
mStateObserver = observer;
}
// Implements StartSurface.Controller
@Override
public boolean overviewVisible() {
......@@ -214,7 +257,9 @@ class StartSurfaceMediator
mPropertyModel.set(FEED_SURFACE_COORDINATOR,
mFeedSurfaceCreator.createFeedSurfaceCoordinator());
}
mPropertyModel.set(IS_SHOWING_OVERVIEW, true);
mDelegate.addUrlFocusChangeListener(mUrlFocusChangeListener);
}
mController.showOverview(animate);
......@@ -230,12 +275,14 @@ class StartSurfaceMediator
setSecondaryTasksSurfaceVisibility(false);
setExploreSurfaceVisibility(true);
notifyStateChange();
return true;
}
if (mPropertyModel != null && mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE)
&& mSurfaceMode == SurfaceMode.TWO_PANES) {
setExploreSurfaceVisibility(false);
notifyStateChange();
return true;
}
......@@ -255,12 +302,20 @@ class StartSurfaceMediator
for (StartSurface.OverviewModeObserver observer : mObservers) {
observer.finishedShowing();
}
// TODO(crbug.com/982018): Move to showOverview before overview is showing.
// Note that Tab switcher mode toolbar is lazily created when showing Tab switcher the first
// time.
if (mSurfaceMode != SurfaceMode.NO_START_SURFACE) {
notifyStateChange();
}
}
@Override
public void startedHiding() {
if (mPropertyModel != null) {
mPropertyModel.set(IS_SHOWING_OVERVIEW, false);
mDelegate.removeUrlFocusChangeListener(mUrlFocusChangeListener);
destroyFeedSurfaceCoordinator();
}
for (StartSurface.OverviewModeObserver observer : mObservers) {
......@@ -275,6 +330,13 @@ class StartSurfaceMediator
}
}
private void destroyFeedSurfaceCoordinator() {
FeedSurfaceCoordinator feedSurfaceCoordinator =
mPropertyModel.get(FEED_SURFACE_COORDINATOR);
if (feedSurfaceCoordinator != null) feedSurfaceCoordinator.destroy();
mPropertyModel.set(FEED_SURFACE_COORDINATOR, null);
}
// Implements View.OnClickListener, which listens for the more tabs button.
@Override
public void onClick(View v) {
......@@ -332,22 +394,18 @@ class StartSurfaceMediator
// always show the Home Pane, so the Explore Pane stays hidden.
if (mIsIncognito) setExploreSurfaceVisibility(false);
}
}
private void destroyFeedSurfaceCoordinator() {
FeedSurfaceCoordinator feedSurfaceCoordinator =
mPropertyModel.get(FEED_SURFACE_COORDINATOR);
if (feedSurfaceCoordinator != null) feedSurfaceCoordinator.destroy();
mPropertyModel.set(FEED_SURFACE_COORDINATOR, null);
notifyStateChange();
}
private void setSecondaryTasksSurfaceVisibility(boolean isVisible) {
assert mSurfaceMode == SurfaceMode.SINGLE_PANE;
if (isVisible) {
if (mSecondaryTasksSurfaceController == null) {
mSecondaryTasksSurfaceController = mSecondaryTasksSurfaceInitializer.initialize();
}
mSecondaryTasksSurfacePropertyModel.set(IS_FAKE_SEARCH_BOX_VISIBLE, mIsIncognito);
mSecondaryTasksSurfaceController.showOverview(false);
} else {
if (mSecondaryTasksSurfaceController == null) return;
......@@ -355,4 +413,34 @@ class StartSurfaceMediator
}
mPropertyModel.set(IS_SECONDARY_SURFACE_VISIBLE, isVisible);
}
private void notifyStateChange() {
assert mSurfaceMode != SurfaceMode.NO_START_SURFACE;
if (mStateObserver != null) {
mStateObserver.onStateChanged(shouldShowTabSwitcherToolbar());
}
}
private boolean shouldShowTabSwitcherToolbar() {
if (mSurfaceMode == SurfaceMode.SINGLE_PANE) {
// Show Tab switcher toolbar when showing more Tabs and in incognito single pane when
// fake search box is visible.
if (mPropertyModel.get(IS_SECONDARY_SURFACE_VISIBLE)) {
return !mIsIncognito
|| (mIsIncognito
&& mSecondaryTasksSurfacePropertyModel.get(
IS_FAKE_SEARCH_BOX_VISIBLE));
}
}
// Do not show Tab switcher toolbar on explore pane.
if (mSurfaceMode == SurfaceMode.TWO_PANES
&& mPropertyModel.get(IS_EXPLORE_SURFACE_VISIBLE)) {
return false;
}
// Do not show Tab switcher toolbar when focusing the Omnibox.
return mPropertyModel.get(IS_FAKE_SEARCH_BOX_VISIBLE);
}
}
......@@ -8,6 +8,25 @@ import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
/** Interface to communicate with the start surface. */
public interface StartSurface {
/**
* An observer that is notified when the start surface internal state, excluding
* the states notified in {@link OverviewModeObserver}, is changed.
*/
interface StateObserver {
/**
* Called when the internal state is changed.
* @param shouldShowTabSwitcherToolbar Whether or not should show the Tab switcher toolbar.
*/
void onStateChanged(boolean shouldShowTabSwitcherToolbar);
}
/**
* Set the given {@link StateObserver}.
* Note that this will override the previous observer.
* @param observer The given observer.
*/
void setStateChangeObserver(StateObserver observer);
/**
* Defines an interface to pass out tab selecting event.
*/
......
......@@ -10,6 +10,10 @@
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<!-- Search box -->
<include layout="@layout/fake_search_box_layout"/>
<HorizontalScrollView android:id="@+id/mv_tiles_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
......@@ -22,6 +26,7 @@
android:orientation="horizontal"
android:paddingBottom="@dimen/tasks_view_items_vertical_spacing" />
</HorizontalScrollView>
<LinearLayout
android:id="@+id/tab_switcher_title"
android:layout_width="match_parent"
......
......@@ -6,6 +6,8 @@ package org.chromium.chrome.browser.tasks;
import android.view.ViewGroup;
import androidx.annotation.Nullable;
import org.chromium.chrome.browser.compositor.layouts.Layout;
import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
......@@ -15,6 +17,15 @@ import org.chromium.chrome.browser.tasks.tab_management.TabSwitcher;
* {@link TasksSurfaceCoordinator}.
*/
public interface TasksSurface {
/** The delegate for the fake search box on the tasks surface. */
public interface FakeSearchBoxDelegate {
/**
* Interface to request focusing on the URL bar.
* @param pastedText The text to be pasted in the Omnibox or null.
* */
void requestUrlFocus(@Nullable String pastedText);
}
/**
* Set the listener to get the {@link Layout#onTabSelecting} event from the Grid Tab Switcher.
* @param listener The {@link TabSwitcher.OnTabSelectingListener} to use.
......
......@@ -26,8 +26,8 @@ public class TasksSurfaceCoordinator implements TasksSurface {
private final MostVisitedListCoordinator mMostVisitedList;
private final TasksSurfaceMediator mMediator;
public TasksSurfaceCoordinator(
ChromeActivity activity, boolean isTabCarousel, PropertyModel propertyModel) {
public TasksSurfaceCoordinator(ChromeActivity activity, PropertyModel propertyModel,
TasksSurface.FakeSearchBoxDelegate fakeSearchBoxDelegate, boolean isTabCarousel) {
mView = (TasksView) LayoutInflater.from(activity).inflate(R.layout.tasks_view_layout, null);
mPropertyModelChangeProcessor =
PropertyModelChangeProcessor.create(propertyModel, mView, TasksViewBinder::bind);
......@@ -39,7 +39,8 @@ public class TasksSurfaceCoordinator implements TasksSurface {
activity, mView.getTabSwitcherContainer());
}
mMediator = new TasksSurfaceMediator(activity, propertyModel, isTabCarousel);
mMediator = new TasksSurfaceMediator(
activity, propertyModel, fakeSearchBoxDelegate, isTabCarousel);
LinearLayout mvTilesLayout = mView.findViewById(R.id.mv_tiles_layout);
mMostVisitedList = new MostVisitedListCoordinator(activity, mvTilesLayout, propertyModel);
......
......@@ -4,9 +4,14 @@
package org.chromium.chrome.browser.tasks;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
import android.content.Context;
import android.support.annotation.Nullable;
import android.view.View;
import org.chromium.ui.modelutil.PropertyModel;
......@@ -14,10 +19,30 @@ import org.chromium.ui.modelutil.PropertyModel;
* Mediator for handling {@link TasksSurface}-related logic.
*/
class TasksSurfaceMediator {
@Nullable
private final TasksSurface.FakeSearchBoxDelegate mFakeSearchBoxDelegate;
private final PropertyModel mModel;
TasksSurfaceMediator(Context context, PropertyModel model, boolean isTabCarousel) {
TasksSurfaceMediator(Context context, PropertyModel model,
TasksSurface.FakeSearchBoxDelegate fakeSearchBoxDelegate, boolean isTabCarousel) {
mFakeSearchBoxDelegate = fakeSearchBoxDelegate;
assert mFakeSearchBoxDelegate != null;
mModel = model;
mModel.set(IS_TAB_CAROUSEL, isTabCarousel);
mModel.set(FAKE_SEARCH_BOX_CLICK_LISTENER, new View.OnClickListener() {
@Override
public void onClick(View v) {
mFakeSearchBoxDelegate.requestUrlFocus(null);
}
});
// Set the initial state.
mModel.set(IS_FAKE_SEARCH_BOX_VISIBLE, true);
mModel.set(IS_VOICE_RECOGNITION_BUTTON_VISIBLE, false);
// TODO(crbug.com/982018): Enable voice recognition button in the fake search box.
// TODO(crbug.com/982018): Enable long press and paste search in the fake search box.
// TODO(crbug.com/982018): Change the fake search box in incognito and dark mode.
}
}
......@@ -15,12 +15,21 @@ import org.chromium.ui.modelutil.PropertyModel;
public class TasksSurfaceProperties {
private TasksSurfaceProperties() {}
public static final PropertyModel.WritableBooleanPropertyKey IS_FAKE_SEARCH_BOX_VISIBLE =
new PropertyModel.WritableBooleanPropertyKey();
public static final PropertyModel.WritableBooleanPropertyKey IS_TAB_CAROUSEL =
new PropertyModel.WritableBooleanPropertyKey();
public static final PropertyModel
.WritableBooleanPropertyKey IS_VOICE_RECOGNITION_BUTTON_VISIBLE =
new PropertyModel.WritableBooleanPropertyKey();
public static final PropertyModel
.WritableObjectPropertyKey<View.OnClickListener> FAKE_SEARCH_BOX_CLICK_LISTENER =
new PropertyModel.WritableObjectPropertyKey<View.OnClickListener>();
public static final PropertyModel
.WritableObjectPropertyKey<View.OnClickListener> MORE_TABS_CLICK_LISTENER =
new PropertyModel.WritableObjectPropertyKey<View.OnClickListener>();
public static final PropertyModel.WritableBooleanPropertyKey MV_TILES_VISIBLE = IS_VISIBLE;
public static final PropertyKey[] ALL_KEYS =
new PropertyKey[] {IS_TAB_CAROUSEL, MORE_TABS_CLICK_LISTENER, MV_TILES_VISIBLE};
public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {IS_FAKE_SEARCH_BOX_VISIBLE,
IS_TAB_CAROUSEL, IS_VOICE_RECOGNITION_BUTTON_VISIBLE, FAKE_SEARCH_BOX_CLICK_LISTENER,
MORE_TABS_CLICK_LISTENER, MV_TILES_VISIBLE};
}
......@@ -59,6 +59,30 @@ class TasksView extends LinearLayout {
}
}
/**
* Set the given listener for the fake search box.
* @param listener The given listener.
*/
void setFakeSearchBoxClickListener(@Nullable View.OnClickListener listener) {
findViewById(R.id.search_box_text).setOnClickListener(listener);
}
/**
* Set the visibility of the fake search box.
* @param isVisible Whether it's visible.
*/
void setFakeSearchBoxVisibility(boolean isVisible) {
findViewById(R.id.search_box).setVisibility(isVisible ? View.VISIBLE : View.GONE);
}
/**
* Set the visibility of the voice recognition button.
* @param isVisible Whether it's visible.
*/
void setVoiceRecognitionButtonVisibility(boolean isVisible) {
findViewById(R.id.voice_search_button).setVisibility(isVisible ? View.VISIBLE : View.GONE);
}
/**
* Set the visibility of the Most Visited Tiles.
*/
......
......@@ -4,7 +4,10 @@
package org.chromium.chrome.browser.tasks;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.FAKE_SEARCH_BOX_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_FAKE_SEARCH_BOX_VISIBLE;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_TAB_CAROUSEL;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.IS_VOICE_RECOGNITION_BUTTON_VISIBLE;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MORE_TABS_CLICK_LISTENER;
import static org.chromium.chrome.browser.tasks.TasksSurfaceProperties.MV_TILES_VISIBLE;
......@@ -16,8 +19,15 @@ import org.chromium.ui.modelutil.PropertyModel;
// The view binder of the tasks surface view.
class TasksViewBinder {
public static void bind(PropertyModel model, TasksView view, PropertyKey propertyKey) {
if (propertyKey == IS_TAB_CAROUSEL) {
if (propertyKey == FAKE_SEARCH_BOX_CLICK_LISTENER) {
view.setFakeSearchBoxClickListener(model.get(FAKE_SEARCH_BOX_CLICK_LISTENER));
} else if (propertyKey == IS_FAKE_SEARCH_BOX_VISIBLE) {
view.setFakeSearchBoxVisibility(model.get(IS_FAKE_SEARCH_BOX_VISIBLE));
} else if (propertyKey == IS_TAB_CAROUSEL) {
view.setIsTabCarousel(model.get(IS_TAB_CAROUSEL));
} else if (propertyKey == IS_VOICE_RECOGNITION_BUTTON_VISIBLE) {
view.setVoiceRecognitionButtonVisibility(
model.get(IS_VOICE_RECOGNITION_BUTTON_VISIBLE));
} else if (propertyKey == MORE_TABS_CLICK_LISTENER) {
view.setMoreTabsOnClickListener(model.get(MORE_TABS_CLICK_LISTENER));
} else if (propertyKey == MV_TILES_VISIBLE) {
......
......@@ -37,10 +37,7 @@ class TabListContainerProperties {
public static final PropertyModel.WritableIntPropertyKey SHADOW_TOP_MARGIN =
new PropertyModel.WritableIntPropertyKey();
public static final PropertyModel.WritableIntPropertyKey TOP_PADDING =
new PropertyModel.WritableIntPropertyKey();
public static final PropertyKey[] ALL_KEYS = new PropertyKey[] {IS_VISIBLE, IS_INCOGNITO,
VISIBILITY_LISTENER, INITIAL_SCROLL_INDEX, ANIMATE_VISIBILITY_CHANGES,
TOP_CONTROLS_HEIGHT, BOTTOM_CONTROLS_HEIGHT, SHADOW_TOP_MARGIN, TOP_PADDING};
TOP_CONTROLS_HEIGHT, BOTTOM_CONTROLS_HEIGHT, SHADOW_TOP_MARGIN};
}
......@@ -11,7 +11,6 @@ import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerP
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.IS_VISIBLE;
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.SHADOW_TOP_MARGIN;
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.TOP_CONTROLS_HEIGHT;
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.TOP_PADDING;
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.VISIBILITY_LISTENER;
import android.support.v7.widget.LinearLayoutManager;
......@@ -58,9 +57,6 @@ class TabListContainerViewBinder {
view.requestLayout();
} else if (SHADOW_TOP_MARGIN == propertyKey) {
view.setShadowTopMargin(model.get(SHADOW_TOP_MARGIN));
} else if (TOP_PADDING == propertyKey) {
view.setPadding(view.getPaddingLeft(), model.get(TOP_PADDING), view.getPaddingRight(),
view.getPaddingBottom());
}
}
}
......@@ -29,13 +29,14 @@ public interface TabManagementDelegate {
/**
* Create the {@link TasksSurface}
* @param activity The {@link ChromeActivity} that creates this surface.
* @param isTabCarousel Whether show the Tabs in carousel mode.
* @param propertyModel The {@link PropertyModel} contains the {@link TasksSurfaceProperties} to
* communicate with this surface.
* @param fakeSearchBoxDelegate The delegate of the fake search box.
* @param isTabCarousel Whether show the Tabs in carousel mode.
* @return The {@TasksSurface}.
*/
TasksSurface createTasksSurface(
ChromeActivity activity, boolean isTabCarousel, PropertyModel propertyModel);
TasksSurface createTasksSurface(ChromeActivity activity, PropertyModel propertyModel,
TasksSurface.FakeSearchBoxDelegate fakeSearchBoxDelegate, boolean isTabCarousel);
/**
* Create the {@link TabSwitcher} to display Tabs in grid.
......
......@@ -32,9 +32,10 @@ import org.chromium.ui.modelutil.PropertyModel;
@UsedByReflection("TabManagementModule")
public class TabManagementDelegateImpl implements TabManagementDelegate {
@Override
public TasksSurface createTasksSurface(
ChromeActivity activity, boolean isTabCarousel, PropertyModel propertyModel) {
return new TasksSurfaceCoordinator(activity, isTabCarousel, propertyModel);
public TasksSurface createTasksSurface(ChromeActivity activity, PropertyModel propertyModel,
TasksSurface.FakeSearchBoxDelegate fakeSearchBoxDelegate, boolean isTabCarousel) {
return new TasksSurfaceCoordinator(
activity, propertyModel, fakeSearchBoxDelegate, isTabCarousel);
}
@Override
......
......@@ -11,7 +11,6 @@ import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerP
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.IS_VISIBLE;
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.SHADOW_TOP_MARGIN;
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.TOP_CONTROLS_HEIGHT;
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.TOP_PADDING;
import static org.chromium.chrome.browser.tasks.tab_management.TabListContainerProperties.VISIBILITY_LISTENER;
import android.graphics.Bitmap;
......@@ -249,10 +248,7 @@ class TabSwitcherMediator implements TabSwitcher.Controller, TabListRecyclerView
// Container view takes care of padding and margin in start surface.
if (mode != TabListCoordinator.TabListMode.CAROUSEL) {
// TODO(crbug.com/1010310): Remove the start surface check when tasks-only start surface
// can replace the omnibox check.
int topControlsHeight = ReturnToChromeExperimentsUtil.shouldShowOmniboxOnTabSwitcher()
&& FeatureUtilities.isStartSurfaceEnabled()
? 0
: fullscreenManager.getTopControlsHeight();
mContainerViewModel.set(TOP_CONTROLS_HEIGHT, topControlsHeight);
......@@ -262,17 +258,9 @@ class TabSwitcherMediator implements TabSwitcher.Controller, TabListRecyclerView
int toolbarHeight =
ContextUtils.getApplicationContext().getResources().getDimensionPixelSize(
R.dimen.toolbar_height_no_shadow);
if (ReturnToChromeExperimentsUtil.shouldShowOmniboxOnTabSwitcher()
&& !FeatureUtilities.isStartSurfaceEnabled()) {
// TODO(crbug.com/1010310): Remove this and the TOP_PADDING property once this can
// be replaced by tasks-only start surface mode.
mContainerViewModel.set(TOP_PADDING, toolbarHeight);
mContainerViewModel.set(SHADOW_TOP_MARGIN, 2 * toolbarHeight);
} else {
mContainerViewModel.set(SHADOW_TOP_MARGIN,
FeatureUtilities.isStartSurfaceEnabled() ? 0 : toolbarHeight);
}
mContainerViewModel.set(SHADOW_TOP_MARGIN,
ReturnToChromeExperimentsUtil.shouldShowOmniboxOnTabSwitcher() ? 0
: toolbarHeight);
}
mContainerView = containerView;
......
......@@ -10,14 +10,6 @@
android:layout_height="wrap_content"
android:minHeight="@dimen/control_container_height" >
<ViewStub
android:id="@+id/tab_switcher_toolbar_stub"
android:layout_width="match_parent"
android:layout_marginTop="@dimen/tab_strip_height"
android:layout_height="@dimen/toolbar_height_no_shadow"
android:inflatedId="@+id/tab_switcher_toolbar"
android:layout="@layout/tab_switcher_toolbar" />
<view
class="org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer$ToolbarViewResourceFrameLayout"
android:id="@+id/toolbar_container"
......@@ -57,4 +49,12 @@
android:layout_gravity="end|top"
android:layout="@layout/find_toolbar" />
</view>
<ViewStub
android:id="@+id/tab_switcher_toolbar_stub"
android:layout_width="match_parent"
android:layout_marginTop="@dimen/tab_strip_height"
android:layout_height="@dimen/toolbar_height_no_shadow"
android:inflatedId="@+id/tab_switcher_toolbar"
android:layout="@layout/tab_switcher_toolbar" />
</org.chromium.chrome.browser.toolbar.top.ToolbarControlContainer>
<?xml version="1.0" encoding="utf-8"?>
<!-- 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. -->
<view
class="org.chromium.chrome.browser.ntp.NewTabPageLayout$SearchBoxContainerView"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/search_box"
android:layout_width="match_parent"
android:layout_height="@dimen/ntp_search_box_height"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="0dp"
android:layout_marginBottom="1dp"
android:gravity="center_vertical"
android:addStatesFromChildren="true"
android:background="@drawable/ntp_search_box"
android:orientation="horizontal"
android:paddingStart="@dimen/location_bar_lateral_padding" >
<!-- TODO(crbug.com/900912): Fix and remove lint ignore -->
<EditText
tools:ignore="Autofill,LabelFor"
style="@style/TextAppearance.NewTabPageSearchBoxText"
android:id="@+id/search_box_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="12dp"
android:layout_weight="1"
android:background="@null"
android:ellipsize="end"
android:focusableInTouchMode="false"
android:focusable="false"
android:gravity="center_vertical"
android:inputType="text"
android:singleLine="true"
android:hint="@string/search_or_type_web_address" />
<!-- Padding start is applied so that microphone icon appears in the same location as it
does in the main url bar. The microphone button in the url bar is 48dp wide with 4dp
start padding. -->
<org.chromium.ui.widget.ChromeImageView
android:id="@+id/voice_search_button"
android:layout_width="48dp"
android:layout_height="match_parent"
android:paddingStart="4dp"
android:contentDescription="@string/accessibility_toolbar_btn_mic"
android:src="@drawable/btn_mic"
android:scaleType="centerInside"
app:tint="@color/standard_mode_tint" />
</view>
......@@ -26,49 +26,7 @@
android:layout_marginBottom="23dp" />
<!-- Search box -->
<view
class="org.chromium.chrome.browser.ntp.NewTabPageLayout$SearchBoxContainerView"
android:id="@+id/search_box"
android:layout_width="match_parent"
android:layout_height="@dimen/ntp_search_box_height"
android:layout_marginStart="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="0dp"
android:layout_marginBottom="1dp"
android:gravity="center_vertical"
android:addStatesFromChildren="true"
android:background="@drawable/ntp_search_box"
android:orientation="horizontal"
android:paddingStart="@dimen/location_bar_lateral_padding" >
<!-- TODO(crbug.com/900912): Fix and remove lint ignore -->
<EditText
tools:ignore="Autofill,LabelFor"
style="@style/TextAppearance.NewTabPageSearchBoxText"
android:id="@+id/search_box_text"
android:layout_width="0dp"
android:layout_height="match_parent"
android:layout_marginEnd="12dp"
android:layout_weight="1"
android:background="@null"
android:ellipsize="end"
android:focusableInTouchMode="false"
android:focusable="false"
android:gravity="center_vertical"
android:inputType="text"
android:singleLine="true" />
<!-- Padding start is applied so that microphone icon appears in the same location as it
does in the main url bar. The microphone button in the url bar is
48dp wide with 4dp start padding. -->
<org.chromium.ui.widget.ChromeImageView
android:id="@+id/voice_search_button"
android:layout_width="48dp"
android:layout_height="match_parent"
android:paddingStart="4dp"
android:contentDescription="@string/accessibility_toolbar_btn_mic"
android:src="@drawable/btn_mic"
android:scaleType="centerInside"
app:tint="@color/standard_mode_tint" />
</view>
<include layout="@layout/fake_search_box_layout"/>
<!-- Middle spacer -->
<View
......
......@@ -386,6 +386,13 @@ public class ChromeTabbedActivity extends ChromeActivity implements ScreenshotMo
}
}
@Override
public void onOverviewModeStateChanged(boolean showTabSwitcherToolbar) {
for (OverviewModeObserver observer : mOverviewModeObserverList) {
observer.onOverviewModeStateChanged(showTabSwitcherToolbar);
}
}
@Override
public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {
for (OverviewModeObserver observer : mOverviewModeObserverList) {
......
......@@ -16,6 +16,9 @@ public class EmptyOverviewModeObserver implements OverviewModeObserver {
@Override
public void onOverviewModeFinishedShowing() {}
@Override
public void onOverviewModeStateChanged(boolean showTabSwitcherToolbar) {}
@Override
public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {}
......
......@@ -15,6 +15,7 @@ import org.chromium.base.metrics.RecordUserAction;
import org.chromium.chrome.browser.accessibility_tab_switcher.OverviewListLayout;
import org.chromium.chrome.browser.compositor.TitleCache;
import org.chromium.chrome.browser.compositor.bottombar.OverlayPanel.StateChangeReason;
import org.chromium.chrome.browser.compositor.layouts.OverviewModeBehavior.OverviewModeObserver;
import org.chromium.chrome.browser.compositor.layouts.components.LayoutTab;
import org.chromium.chrome.browser.compositor.layouts.components.VirtualView;
import org.chromium.chrome.browser.compositor.layouts.content.TabContentManager;
......@@ -93,6 +94,14 @@ public class LayoutManagerChrome extends LayoutManager implements OverviewModeCo
TabManagementDelegate tabManagementDelegate =
TabManagementModuleProvider.getDelegate();
assert tabManagementDelegate != null;
startSurface.setStateChangeObserver(new StartSurface.StateObserver() {
@Override
public void onStateChanged(boolean shouldShowTabSwitcherToolbar) {
for (OverviewModeObserver observer : mOverviewModeObservers) {
observer.onOverviewModeStateChanged(shouldShowTabSwitcherToolbar);
}
}
});
mOverviewLayout = tabManagementDelegate.createStartSurfaceLayout(
context, this, renderHost, startSurface);
} else {
......
......@@ -25,6 +25,12 @@ public interface OverviewModeBehavior {
*/
void onOverviewModeFinishedShowing();
/**
* Called when the internal state is changed.
* @param showTabSwitcherToolbar Whether or not request showing the Tab switcher toolbar.
*/
void onOverviewModeStateChanged(boolean showTabSwitcherToolbar);
/**
* Called when overview mode starts hiding.
* @param showToolbar Whether or not to show the normal toolbar when animating out of
......
......@@ -295,9 +295,6 @@ public class NewTabPageLayout extends LinearLayout implements TileGroup.Observer
TraceEvent.begin(TAG + ".initializeSearchBoxTextView()");
final TextView searchBoxTextView = mSearchBoxView.findViewById(R.id.search_box_text);
String hintText = getResources().getString(R.string.search_or_type_web_address);
searchBoxTextView.setHint(hintText);
searchBoxTextView.setOnClickListener(v -> mManager.focusSearchBox(false, null));
searchBoxTextView.addTextChangedListener(new TextWatcher() {
@Override
......
......@@ -59,14 +59,13 @@ public final class ReturnToChromeExperimentsUtil {
* Whether we should display the omnibox on the tab switcher in addition to the
* tab switcher toolbar.
*
* @return true if the tab switcher on return and tab grid features are both ON, else false.
* @return true if the tab grid and the start surface features are both ON, else false.
*/
public static boolean shouldShowOmniboxOnTabSwitcher() {
return ChromeFeatureList.isInitialized()
&& (FeatureUtilities.isGridTabSwitcherEnabled()
|| FeatureUtilities.isTabGroupsAndroidEnabled())
&& (ChromeFeatureList.isEnabled(ChromeFeatureList.TAB_SWITCHER_ON_RETURN)
|| FeatureUtilities.isStartSurfaceEnabled());
&& FeatureUtilities.isStartSurfaceEnabled();
}
/**
......
......@@ -674,6 +674,11 @@ public class ToolbarManager implements ScrimObserver, ToolbarTabController, UrlF
updateButtonStatus();
}
@Override
public void onOverviewModeStateChanged(boolean showTabSwitcherToolbar) {
mToolbar.updateTabSwitcherToolbarState(showTabSwitcherToolbar);
}
@Override
public void onOverviewModeStartedHiding(boolean showToolbar, boolean delayAnimation) {
mToolbar.setTabSwitcherMode(false, showToolbar, delayAnimation);
......
......@@ -163,22 +163,28 @@ class TabSwitcherModeTTCoordinatorPhone implements TemplateUrlServiceObserver {
}
void setTabSwitcherToolbarVisibility(boolean shouldShowTabSwitcherToolbar) {
final float targetAlpha = shouldShowTabSwitcherToolbar ? 1.0f : 0.0f;
if ((mTabSwitcherModeToolbar.getVisibility() == View.VISIBLE)
== shouldShowTabSwitcherToolbar) {
return;
}
final float targetAlpha = shouldShowTabSwitcherToolbar ? 1.0f : 0.0f;
mTabSwitcherModeToolbar.animate()
.alpha(targetAlpha)
.setDuration(TopToolbarCoordinator.TAB_SWITCHER_MODE_NORMAL_ANIMATION_DURATION_MS)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationStart(Animator animation) {
if (shouldShowTabSwitcherToolbar)
if (shouldShowTabSwitcherToolbar) {
mTabSwitcherModeToolbar.setVisibility(View.VISIBLE);
}
}
@Override
public void onAnimationEnd(Animator animation) {
if (!shouldShowTabSwitcherToolbar)
if (!shouldShowTabSwitcherToolbar) {
mTabSwitcherModeToolbar.setVisibility(View.GONE);
}
}
});
}
......
......@@ -24,7 +24,6 @@ import org.chromium.chrome.browser.device.DeviceClassManager;
import org.chromium.chrome.browser.preferences.PrefServiceBridge;
import org.chromium.chrome.browser.tabmodel.TabModel;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.tasks.ReturnToChromeExperimentsUtil;
import org.chromium.chrome.browser.toolbar.IncognitoStateProvider;
import org.chromium.chrome.browser.toolbar.IncognitoToggleTabLayout;
import org.chromium.chrome.browser.toolbar.MenuButton;
......@@ -178,12 +177,6 @@ public class TabSwitcherModeTTPhone extends OptimizedFrameLayout
} else {
if (mNewTabImageButton != null) mNewTabImageButton.setEnabled(true);
if (mNewTabViewButton != null) mNewTabViewButton.setEnabled(true);
if (ReturnToChromeExperimentsUtil.shouldShowOmniboxOnTabSwitcher()) {
// Bump this down by the height of the toolbar so the omnibox can be visible.
MarginLayoutParams params = (MarginLayoutParams) getLayoutParams();
params.topMargin =
getResources().getDimensionPixelSize(R.dimen.toolbar_height_no_shadow);
}
}
mVisiblityAnimator.addListener(new CancelAwareAnimatorListener() {
......
......@@ -114,4 +114,10 @@ public interface Toolbar {
* @return The primary color to use for the background drawable.
*/
int getPrimaryColor();
/**
* Update the Tab switcher toolbar state.
* @param requestToShow Whether or not request showing the Tab switcher toolbar.
*/
void updateTabSwitcherToolbarState(boolean requestToShow);
}
......@@ -210,6 +210,17 @@ public class TopToolbarCoordinator implements Toolbar {
return mToolbarLayout.getToolbarDataProvider().getPrimaryColor();
}
@Override
public void updateTabSwitcherToolbarState(boolean requestToShow) {
if (mTabSwitcherModeCoordinatorPhone == null
|| mToolbarLayout.getToolbarDataProvider() == null
|| !mToolbarLayout.getToolbarDataProvider().isInOverviewAndShowingOmnibox()) {
return;
}
mTabSwitcherModeCoordinatorPhone.setTabSwitcherToolbarVisibility(requestToShow);
}
@Override
public void getPositionRelativeToContainer(View containerView, int[] position) {
mToolbarLayout.getPositionRelativeToContainer(containerView, position);
......@@ -482,12 +493,6 @@ public class TopToolbarCoordinator implements Toolbar {
*/
public void onUrlFocusChange(boolean hasFocus) {
mToolbarLayout.onUrlFocusChange(hasFocus);
if (mToolbarLayout.getToolbarDataProvider() != null
&& mToolbarLayout.getToolbarDataProvider().isInOverviewAndShowingOmnibox()
&& mTabSwitcherModeCoordinatorPhone != null) {
mTabSwitcherModeCoordinatorPhone.setTabSwitcherToolbarVisibility(!hasFocus);
}
}
/**
......
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