[go: nahoru, domu]

blob: a919a39cdf2ccdf92939cef48fb388a86728f303 [file] [log] [blame]
// Copyright 2019 The Chromium Authors
// 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.tasks;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.graphics.PorterDuff;
import android.graphics.drawable.Drawable;
import android.graphics.drawable.LayerDrawable;
import android.os.Build;
import android.util.AttributeSet;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewStub;
import android.widget.CompoundButton.OnCheckedChangeListener;
import android.widget.FrameLayout;
import androidx.annotation.ColorInt;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.coordinatorlayout.widget.CoordinatorLayout;
import com.google.android.material.appbar.AppBarLayout;
import org.chromium.chrome.R;
import org.chromium.chrome.browser.feed.FeedStreamViewResizer;
import org.chromium.chrome.browser.feed.FeedSurfaceCoordinator;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.lifecycle.ActivityLifecycleDispatcher;
import org.chromium.chrome.browser.ntp.IncognitoDescriptionView;
import org.chromium.chrome.browser.ntp.search.SearchBoxCoordinator;
import org.chromium.chrome.browser.preferences.Pref;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.features.start_surface.StartSurfaceConfiguration;
import org.chromium.components.browser_ui.styles.ChromeColors;
import org.chromium.components.browser_ui.widget.CoordinatorLayoutForPointer;
import org.chromium.components.browser_ui.widget.displaystyle.UiConfig;
import org.chromium.components.content_settings.CookieControlsEnforcement;
import org.chromium.components.user_prefs.UserPrefs;
import org.chromium.ui.base.WindowAndroid;
/** The view of the tasks surface. Set public for testing. */
public class TasksView extends CoordinatorLayoutForPointer {
private final Context mContext;
private FrameLayout mCardTabSwitcherContainer;
private AppBarLayout mHeaderView;
private ViewGroup mMvTilesContainerLayout;
private SearchBoxCoordinator mSearchBoxCoordinator;
private IncognitoDescriptionView mIncognitoDescriptionView;
private View.OnClickListener mIncognitoDescriptionLearnMoreListener;
private boolean mIncognitoCookieControlsToggleIsChecked;
private OnCheckedChangeListener mIncognitoCookieControlsToggleCheckedListener;
private @CookieControlsEnforcement int mIncognitoCookieControlsToggleEnforcement =
CookieControlsEnforcement.NO_ENFORCEMENT;
private View.OnClickListener mIncognitoCookieControlsIconClickListener;
private UiConfig mUiConfig;
private final boolean mIsSurfacePolishEnabled;
private final boolean mIsSurfacePolishOmniboxColorEnabled;
/** Default constructor needed to inflate via XML. */
public TasksView(Context context, AttributeSet attrs) {
super(context, attrs);
mContext = context;
mIsSurfacePolishEnabled = ChromeFeatureList.sSurfacePolish.isEnabled();
mIsSurfacePolishOmniboxColorEnabled =
mIsSurfacePolishEnabled
&& StartSurfaceConfiguration.SURFACE_POLISH_OMNIBOX_COLOR.getValue();
}
public void initialize(
ActivityLifecycleDispatcher activityLifecycleDispatcher,
boolean isIncognito,
WindowAndroid windowAndroid) {
assert mSearchBoxCoordinator != null
: "#onFinishInflate should be completed before the call to initialize.";
mSearchBoxCoordinator.initialize(activityLifecycleDispatcher, isIncognito, windowAndroid);
}
@Override
protected void onFinishInflate() {
super.onFinishInflate();
mCardTabSwitcherContainer = (FrameLayout) findViewById(R.id.tab_switcher_module_container);
mMvTilesContainerLayout = findViewById(R.id.mv_tiles_container);
mSearchBoxCoordinator = new SearchBoxCoordinator(getContext(), this);
mHeaderView = (AppBarLayout) findViewById(R.id.task_surface_header);
forceHeaderScrollable();
mUiConfig = new UiConfig(this);
setHeaderPadding();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
mUiConfig.updateDisplayStyle();
}
public ViewGroup getCardTabSwitcherContainer() {
return mCardTabSwitcherContainer;
}
public ViewGroup getBodyViewContainer() {
return findViewById(R.id.tasks_surface_body);
}
/**
* Set the visibility of the tasks surface body.
* @param isVisible Whether it's visible.
*/
void setSurfaceBodyVisibility(boolean isVisible) {
getBodyViewContainer().setVisibility(isVisible ? View.VISIBLE : View.GONE);
}
/**
* Set the visibility of the tab carousel.
*
* @param isVisible Whether it's visible.
*/
void setTabCardVisibility(boolean isVisible) {
mCardTabSwitcherContainer.setVisibility(isVisible ? View.VISIBLE : View.GONE);
}
/**
* @return The {@link SearchBoxCoordinator} representing the fake search box.
*/
SearchBoxCoordinator getSearchBoxCoordinator() {
return mSearchBoxCoordinator;
}
/** Set the visibility of the Most Visited Tiles. */
void setMostVisitedVisibility(int visibility) {
mMvTilesContainerLayout.setVisibility(visibility);
}
/** Set the visibility of the Most Visited Tiles. */
void setQueryTilesVisibility(int visibility) {
findViewById(R.id.query_tiles_container).setVisibility(visibility);
}
/**
* Set the incognito state.
* @param isIncognito Whether it's in incognito mode.
*/
void setIncognitoMode(boolean isIncognito) {
mSearchBoxCoordinator.setIncognitoMode(isIncognito);
Drawable searchBackground;
if (isIncognito) {
searchBackground =
AppCompatResources.getDrawable(
mContext, R.drawable.fake_search_box_bg_incognito);
} else if (mIsSurfacePolishOmniboxColorEnabled) {
searchBackground =
AppCompatResources.getDrawable(
mContext, R.drawable.home_surface_search_box_background_colorful);
} else if (mIsSurfacePolishEnabled) {
searchBackground =
AppCompatResources.getDrawable(
mContext, R.drawable.home_surface_search_box_background_neutral);
} else {
searchBackground = AppCompatResources.getDrawable(mContext, R.drawable.ntp_search_box);
}
if (searchBackground instanceof LayerDrawable) {
Drawable shapeDrawable =
((LayerDrawable) searchBackground)
.findDrawableByLayerId(R.id.fake_search_box_bg_shape);
if (shapeDrawable != null) {
@ColorInt
int searchBackgroundColor =
isIncognito
? getResources()
.getColor(R.color.toolbar_text_box_background_incognito)
: ChromeColors.getSurfaceColor(
mContext, R.dimen.toolbar_text_box_elevation);
shapeDrawable.mutate();
// TODO(https://crbug.com/1239289): Change back to #setTint once our min API level
// is 23.
shapeDrawable.setColorFilter(searchBackgroundColor, PorterDuff.Mode.SRC_IN);
}
}
mSearchBoxCoordinator.setBackground(searchBackground);
if (!mIsSurfacePolishEnabled) {
int hintTextColor =
mContext.getColor(
isIncognito
? R.color.locationbar_light_hint_text
: R.color.locationbar_dark_hint_text);
mSearchBoxCoordinator.setSearchBoxHintColor(hintTextColor);
}
}
/**
* Initialize incognito description view.
* Note that this interface is supposed to be called only once.
*/
void initializeIncognitoDescriptionView() {
assert mIncognitoDescriptionView == null;
ViewStub containerStub =
(ViewStub) findViewById(R.id.incognito_description_container_layout_stub);
View containerView = containerStub.inflate();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.P) {
containerView.setFocusable(true);
containerView.setFocusableInTouchMode(true);
}
ViewStub incognitoDescriptionViewStub =
(ViewStub) findViewById(R.id.task_view_incognito_layout_stub);
boolean isIncognitoNtpRevampEnabled = ChromeFeatureList.sIncognitoNtpRevamp.isEnabled();
if (isIncognitoNtpRevampEnabled) {
incognitoDescriptionViewStub.setLayoutResource(
R.layout.revamped_incognito_description_layout);
} else {
incognitoDescriptionViewStub.setLayoutResource(R.layout.incognito_description_layout);
}
mIncognitoDescriptionView =
(IncognitoDescriptionView) incognitoDescriptionViewStub.inflate();
// Inflate the correct cookie/tracking protection card.
ViewStub cardStub = findViewById(R.id.cookie_card_stub);
if (cardStub == null) return;
if (shouldShowTrackingProtectionNtp()) {
cardStub.setLayoutResource(
isIncognitoNtpRevampEnabled
? R.layout.revamped_incognito_tracking_protection_card
: R.layout.incognito_tracking_protection_card);
} else {
cardStub.setLayoutResource(
isIncognitoNtpRevampEnabled
? R.layout.revamped_incognito_cookie_controls_card
: R.layout.incognito_cookie_controls_card);
}
cardStub.inflate();
mIncognitoDescriptionView.formatTrackingProtectionText(getContext(), this);
if (mIncognitoDescriptionLearnMoreListener != null) {
setIncognitoDescriptionLearnMoreClickListener(mIncognitoDescriptionLearnMoreListener);
}
setIncognitoCookieControlsToggleChecked(mIncognitoCookieControlsToggleIsChecked);
if (mIncognitoCookieControlsToggleCheckedListener != null) {
setIncognitoCookieControlsToggleCheckedListener(
mIncognitoCookieControlsToggleCheckedListener);
}
setIncognitoCookieControlsToggleEnforcement(mIncognitoCookieControlsToggleEnforcement);
if (mIncognitoCookieControlsIconClickListener != null) {
setIncognitoCookieControlsIconClickListener(mIncognitoCookieControlsIconClickListener);
}
}
/**
* Set the visibility of the incognito description.
* @param isVisible Whether it's visible or not.
*/
void setIncognitoDescriptionVisibility(boolean isVisible) {
((View) mIncognitoDescriptionView).setVisibility(isVisible ? View.VISIBLE : View.GONE);
}
/**
* Set the incognito description learn more click listener.
* @param listener The given click listener.
*/
void setIncognitoDescriptionLearnMoreClickListener(View.OnClickListener listener) {
mIncognitoDescriptionLearnMoreListener = listener;
if (mIncognitoDescriptionView != null) {
mIncognitoDescriptionView.setLearnMoreOnclickListener(listener);
mIncognitoDescriptionLearnMoreListener = null;
}
}
/**
* Set the toggle on the cookie controls card.
* @param isChecked Whether it's checked or not.
*/
void setIncognitoCookieControlsToggleChecked(boolean isChecked) {
mIncognitoCookieControlsToggleIsChecked = isChecked;
if (mIncognitoDescriptionView != null) {
mIncognitoDescriptionView.setCookieControlsToggle(isChecked);
}
}
/**
* Set the incognito cookie controls toggle checked change listener.
* @param listener The given checked change listener.
*/
void setIncognitoCookieControlsToggleCheckedListener(OnCheckedChangeListener listener) {
mIncognitoCookieControlsToggleCheckedListener = listener;
if (mIncognitoDescriptionView != null) {
mIncognitoDescriptionView.setCookieControlsToggleOnCheckedChangeListener(listener);
mIncognitoCookieControlsToggleCheckedListener = null;
}
}
/**
* Set the enforcement rule for the incognito cookie controls toggle.
* @param enforcement The enforcement enum to set.
*/
void setIncognitoCookieControlsToggleEnforcement(@CookieControlsEnforcement int enforcement) {
mIncognitoCookieControlsToggleEnforcement = enforcement;
if (mIncognitoDescriptionView != null) {
mIncognitoDescriptionView.setCookieControlsEnforcement(enforcement);
}
}
/**
* Set the incognito cookie controls icon click listener.
* @param listener The given onclick listener.
*/
void setIncognitoCookieControlsIconClickListener(OnClickListener listener) {
mIncognitoCookieControlsIconClickListener = listener;
if (mIncognitoDescriptionView != null) {
mIncognitoDescriptionView.setCookieControlsIconOnclickListener(listener);
mIncognitoCookieControlsIconClickListener = null;
}
}
/**
* Set the top margin for the tasks surface body.
* @param topMargin The top margin to set.
*/
void setTasksSurfaceBodyTopMargin(int topMargin) {
MarginLayoutParams params = (MarginLayoutParams) getBodyViewContainer().getLayoutParams();
params.topMargin = topMargin;
}
/**
* Set the top margin for the mv tiles container.
* @param topMargin The top margin to set.
*/
void setMVTilesContainerTopMargin(int topMargin) {
MarginLayoutParams params = (MarginLayoutParams) mMvTilesContainerLayout.getLayoutParams();
params.topMargin = topMargin;
}
/**
* Set the left and right margin for the mv tiles container.
* @param margin The left and right margin to set.
*/
void setMVTilesContainerLeftAndRightMargin(int margin) {
MarginLayoutParams params = (MarginLayoutParams) mMvTilesContainerLayout.getLayoutParams();
params.leftMargin = margin;
params.rightMargin = margin;
}
/**
* Set the top margin for the single tab card.
* @param topMargin The top margin to set.
*/
void setSingleTabTopMargin(int topMargin) {
MarginLayoutParams params =
(MarginLayoutParams)
mHeaderView.findViewById(R.id.single_tab_view).getLayoutParams();
params.topMargin = topMargin;
}
/** Set the height of the top toolbar placeholder layout. */
void setTopToolbarPlaceholderHeight(int height) {
View topToolbarPlaceholder = findViewById(R.id.top_toolbar_placeholder);
ViewGroup.LayoutParams lp = topToolbarPlaceholder.getLayoutParams();
lp.height = height;
topToolbarPlaceholder.setLayoutParams(lp);
}
/** Reset the scrolling position by expanding the {@link #mHeaderView}. */
void resetScrollPosition() {
if (mHeaderView != null && mHeaderView.getHeight() != mHeaderView.getBottom()) {
mHeaderView.setExpanded(true, /* animate= */ false);
}
}
/**
* Add a header offset change listener.
* @param onOffsetChangedListener The given header offset change listener.
*/
public void addHeaderOffsetChangeListener(
AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
if (mHeaderView != null) {
mHeaderView.addOnOffsetChangedListener(onOffsetChangedListener);
}
}
/**
* Remove the given header offset change listener.
* @param onOffsetChangedListener The header offset change listener which should be removed.
*/
public void removeHeaderOffsetChangeListener(
AppBarLayout.OnOffsetChangedListener onOffsetChangedListener) {
if (mHeaderView != null) {
mHeaderView.removeOnOffsetChangedListener(onOffsetChangedListener);
}
}
/**
* Update the fake search box layout.
* @param height Current height of the fake search box layout.
* @param topMargin Current top margin of the fake search box layout.
* @param endPadding Current end padding of the fake search box layout.
* @param translationX Current translationX of text view in fake search box layout.
* @param buttonSize Current height and width of the buttons in fake search box layout.
* @param lensButtonLeftMargin Current left margin of the lens button in fake search box layout.
* @param searchTextSize Current size for the search text in the fake search box.
*/
public void updateFakeSearchBox(
int height,
int topMargin,
int endPadding,
float translationX,
int buttonSize,
int lensButtonLeftMargin,
float searchTextSize) {
if (mSearchBoxCoordinator.getView().getVisibility() != View.VISIBLE) return;
mSearchBoxCoordinator.setHeight(height);
mSearchBoxCoordinator.setTopMargin(topMargin);
mSearchBoxCoordinator.setEndPadding(endPadding);
mSearchBoxCoordinator.setTextViewTranslationX(translationX);
mSearchBoxCoordinator.setButtonsHeight(buttonSize);
mSearchBoxCoordinator.setButtonsWidth(buttonSize);
mSearchBoxCoordinator.setLensButtonLeftMargin(lensButtonLeftMargin);
mSearchBoxCoordinator.setSearchTextSize(searchTextSize);
}
/**
* Update both the fake search box height.
* @param height Current height of the fake search box.
*/
public void updateFakeSearchBoxHeight(int height) {
mSearchBoxCoordinator.setHeight(height);
}
/**
* Update the fake search box container.
* @param height Current height of the fake search box container.
*/
public void updateFakeSearchBoxContainer(int height) {
View fakeSearchBoxContainer = findViewById(R.id.fake_search_box);
ViewGroup.LayoutParams lpForContainer = fakeSearchBoxContainer.getLayoutParams();
if (lpForContainer.height == height) {
return;
}
lpForContainer.height = height;
}
private void forceHeaderScrollable() {
// TODO(https://crbug.com/1251632): Find out why scrolling was broken after
// crrev.com/c/3025127. Force the header view to be draggable as a workaround.
CoordinatorLayout.LayoutParams params =
(CoordinatorLayout.LayoutParams) mHeaderView.getLayoutParams();
AppBarLayout.Behavior behavior = new AppBarLayout.Behavior();
behavior.setDragCallback(
new AppBarLayout.Behavior.DragCallback() {
@Override
public boolean canDrag(AppBarLayout appBarLayout) {
return true;
}
});
params.setBehavior(behavior);
}
/**
* Make the padding of header consistent with that of Feed recyclerview which is sized by {@link
* FeedStreamViewResizer} in {@link FeedSurfaceCoordinator}
*/
private void setHeaderPadding() {
FeedStreamViewResizer.createAndAttach((Activity) mContext, mHeaderView, mUiConfig);
}
/**
* Set the background color for Start Surface.
* @param backgroundColor The drawable which contains the background color to set for the Start
* Surface.
*/
void setStartSurfaceBackgroundColor(int backgroundColor) {
setBackgroundColor(backgroundColor);
mHeaderView.setBackgroundColor(backgroundColor);
}
boolean shouldShowTrackingProtectionNtp() {
Profile profile =
Profile.getLastUsedRegularProfile()
.getPrimaryOTRProfile(/* createIfNeeded= */ true);
return (UserPrefs.get(profile).getBoolean(Pref.TRACKING_PROTECTION3PCD_ENABLED)
|| ChromeFeatureList.isEnabled(ChromeFeatureList.TRACKING_PROTECTION_3PCD));
}
}