blob: b707469a20a6b9886ab19a2f1ddc97fb06e949f0 [file] [log] [blame]
// 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 android.app.Activity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import org.chromium.base.supplier.Supplier;
import org.chromium.chrome.browser.feed.FeedLaunchReliabilityLoggingState;
import org.chromium.chrome.browser.feed.FeedSurfaceCoordinator;
import org.chromium.chrome.browser.feed.FeedSurfaceLifecycleManager;
import org.chromium.chrome.browser.feed.FeedSwipeRefreshLayout;
import org.chromium.chrome.browser.feed.shared.FeedSurfaceDelegate;
import org.chromium.chrome.browser.flags.ChromeFeatureList;
import org.chromium.chrome.browser.ntp.NewTabPageLaunchOrigin;
import org.chromium.chrome.browser.ntp.ScrollableContainerDelegate;
import org.chromium.chrome.browser.ntp.snippets.SectionHeaderView;
import org.chromium.chrome.browser.privacy.settings.PrivacyPreferencesManagerImpl;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.share.ShareDelegate;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tabmodel.TabModelSelector;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
import org.chromium.chrome.start_surface.R;
import org.chromium.components.browser_ui.bottomsheet.BottomSheetController;
import org.chromium.ui.base.WindowAndroid;
import org.chromium.ui.modelutil.PropertyModel;
import org.chromium.ui.modelutil.PropertyModelChangeProcessor;
/** The coordinator to control the explore surface. */
class ExploreSurfaceCoordinator implements FeedSurfaceDelegate {
private final Activity mActivity;
private final PropertyModelChangeProcessor mPropertyModelChangeProcessor;
private final FeedSurfaceController mFeedSurfaceController;
private final Supplier<Tab> mParentTabSupplier;
private final boolean mHasHeader;
private final SnackbarManager mSnackbarManager;
private final Supplier<ShareDelegate> mShareDelegateSupplier;
private final WindowAndroid mWindowAndroid;
private final TabModelSelector mTabModelSelector;
private ExploreSurfaceFeedLifecycleManager mExploreSurfaceFeedLifecycleManager;
// mExploreSurfaceNavigationDelegate is lightweight, we keep it across FeedSurfaceCoordinators
// after creating it during the first show.
private ExploreSurfaceNavigationDelegate mExploreSurfaceNavigationDelegate;
/** Interface to control the {@link FeedSurfaceDelegate} */
interface FeedSurfaceController {
/**
* Creates the {@link FeedSurfaceCoordinator} for the specified mode.
* @param isInNightMode Whether or not the feed surface is going to display in night mode.
* @param launchOrigin Where the feed was launched from.
* @return The {@link FeedSurfaceCoordinator}.
*/
FeedSurfaceCoordinator createFeedSurfaceCoordinator(boolean isInNightMode,
boolean isPlaceholderShown, @NewTabPageLaunchOrigin int launchOrigin);
}
/**
* @param activity The current {@link Activity}.
* @param parentView The parent {@link ViewGroup} for the start surface.
* @param containerPropertyModel The {@link PropertyModel} for the container.
* @param hasHeader Whether the surface has a header.
* @param bottomSheetController Controls the state of the bottom sheet.
* @param parentTabSupplier Supplies the current {@link Tab}.
* @param scrollableContainerDelegate Delegate for the scrollable container.
* @param snackbarManager Manages the snackbar.
* @param shareDelegateSupplier Supplies the {@link ShareDelegate}.
* @param windowAndroid The current {@link WindowAndroid}.
* @param tabModelSelector The current {@link TabModelSelector}.
*/
ExploreSurfaceCoordinator(@NonNull Activity activity, @NonNull ViewGroup parentView,
@NonNull PropertyModel containerPropertyModel, boolean hasHeader,
@NonNull BottomSheetController bottomSheetController,
@NonNull Supplier<Tab> parentTabSupplier,
@NonNull ScrollableContainerDelegate scrollableContainerDelegate,
@NonNull SnackbarManager snackbarManager,
@NonNull Supplier<ShareDelegate> shareDelegateSupplier,
@NonNull WindowAndroid windowAndroid, @NonNull TabModelSelector tabModelSelector,
FeedLaunchReliabilityLoggingState feedLaunchReliabilityLoggingState,
@Nullable FeedSwipeRefreshLayout swipeRefreshLayout) {
mActivity = activity;
mHasHeader = hasHeader;
mParentTabSupplier = parentTabSupplier;
mSnackbarManager = snackbarManager;
mShareDelegateSupplier = shareDelegateSupplier;
mWindowAndroid = windowAndroid;
mTabModelSelector = tabModelSelector;
mPropertyModelChangeProcessor = PropertyModelChangeProcessor.create(
containerPropertyModel, parentView, ExploreSurfaceViewBinder::bind);
mFeedSurfaceController = new FeedSurfaceController() {
@Override
public FeedSurfaceCoordinator createFeedSurfaceCoordinator(boolean isInNightMode,
boolean isPlaceholderShown, @NewTabPageLaunchOrigin int launchOrigin) {
return internalCreateFeedSurfaceCoordinator(mHasHeader, isInNightMode,
isPlaceholderShown, bottomSheetController, scrollableContainerDelegate,
launchOrigin, feedLaunchReliabilityLoggingState, swipeRefreshLayout);
}
};
}
/**
* Gets the {@link FeedSurfaceController}.
* @return the {@link FeedSurfaceController}.
*/
FeedSurfaceController getFeedSurfaceController() {
return mFeedSurfaceController;
}
// Implements FeedSurfaceDelegate.
@Override
public FeedSurfaceLifecycleManager createStreamLifecycleManager(
Activity activity, FeedSurfaceCoordinator coordinator) {
mExploreSurfaceFeedLifecycleManager =
new ExploreSurfaceFeedLifecycleManager(activity, mHasHeader, coordinator);
return mExploreSurfaceFeedLifecycleManager;
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
return false;
}
private FeedSurfaceCoordinator internalCreateFeedSurfaceCoordinator(boolean hasHeader,
boolean isInNightMode, boolean isPlaceholderShown,
BottomSheetController bottomSheetController,
ScrollableContainerDelegate scrollableContainerDelegate,
@NewTabPageLaunchOrigin int launchOrigin,
FeedLaunchReliabilityLoggingState feedLaunchReliabilityLoggingState,
FeedSwipeRefreshLayout swipeRefreshLayout) {
if (mExploreSurfaceNavigationDelegate == null) {
mExploreSurfaceNavigationDelegate =
new ExploreSurfaceNavigationDelegate(mParentTabSupplier);
}
Profile profile = Profile.getLastUsedRegularProfile();
SectionHeaderView sectionHeaderView = null;
if (hasHeader) {
LayoutInflater inflater = LayoutInflater.from(mActivity);
if (ChromeFeatureList.isEnabled(ChromeFeatureList.WEB_FEED)) {
sectionHeaderView = (SectionHeaderView) inflater.inflate(
org.chromium.chrome.R.layout.new_tab_page_multi_feed_header, null, false);
} else {
sectionHeaderView = (SectionHeaderView) inflater.inflate(
org.chromium.chrome.R.layout.new_tab_page_feed_v2_expandable_header, null,
false);
}
}
FeedSurfaceCoordinator feedSurfaceCoordinator = new FeedSurfaceCoordinator(mActivity,
mSnackbarManager, mWindowAndroid, null, null, sectionHeaderView, isInNightMode,
this, mExploreSurfaceNavigationDelegate, profile, isPlaceholderShown,
bottomSheetController, mShareDelegateSupplier, scrollableContainerDelegate,
launchOrigin, PrivacyPreferencesManagerImpl.getInstance(),
feedLaunchReliabilityLoggingState, swipeRefreshLayout);
feedSurfaceCoordinator.getView().setId(R.id.start_surface_explore_view);
feedSurfaceCoordinator.getRecyclerView().setOverScrollMode(View.OVER_SCROLL_NEVER);
return feedSurfaceCoordinator;
// TODO(crbug.com/982018): Customize surface background for incognito and dark mode.
// TODO(crbug.com/982018): Hide signin promo UI in incognito mode.
}
}