chromium/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListEditorBookmarkAction.java

// Copyright 2022 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.browser.tasks.tab_management;

import android.app.Activity;
import android.graphics.drawable.Drawable;

import androidx.appcompat.content.res.AppCompatResources;

import org.chromium.base.ResettersForTesting;
import org.chromium.chrome.browser.bookmarks.BookmarkModel;
import org.chromium.chrome.browser.bookmarks.BookmarkUtils;
import org.chromium.chrome.browser.profiles.Profile;
import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tasks.tab_management.TabUiMetricsHelper.TabListEditorActionMetricGroups;
import org.chromium.chrome.browser.ui.messages.snackbar.SnackbarManager;
import org.chromium.chrome.tab_ui.R;

import java.util.List;

/** Bookmark action for the {@link TabListEditorMenu}. */
public class TabListEditorBookmarkAction extends TabListEditorAction {
    private Activity mActivity;
    private TabListEditorBookmarkActionDelegate mDelegate;

    /** Interface for passing params on bookmark action. */
    public interface TabListEditorBookmarkActionDelegate {
        /**
         * Bookmark selected tabs and show snackbar.
         * @param activity the current activity.
         * @param tabs the list of currently selected tabs to perform the action on.
         * @param snackbarManager the snackbarManager used to show the snackbar.
         */
        void bookmarkTabsAndShowSnackbar(
                Activity activity, List<Tab> tabs, SnackbarManager snackbarManager);
    }

    /**
     * Create an action for bookmarking tabs.
     * @param activity for loading resources.
     * @param showMode whether to show an action view.
     * @param buttonType the type of the action view.
     * @param iconPosition the position of the icon in the action view.
     */
    public static TabListEditorAction createAction(
            Activity activity,
            @ShowMode int showMode,
            @ButtonType int buttonType,
            @IconPosition int iconPosition) {
        Drawable drawable = AppCompatResources.getDrawable(activity, R.drawable.star_outline_24dp);
        TabListEditorBookmarkActionDelegate delegate =
                new TabListEditorBookmarkActionDelegateImpl();
        return new TabListEditorBookmarkAction(
                activity, showMode, buttonType, iconPosition, drawable, delegate);
    }

    private TabListEditorBookmarkAction(
            Activity activity,
            @ShowMode int showMode,
            @ButtonType int buttonType,
            @IconPosition int iconPosition,
            Drawable drawable,
            TabListEditorBookmarkActionDelegate delegate) {
        super(
                R.id.tab_list_editor_bookmark_menu_item,
                showMode,
                buttonType,
                iconPosition,
                R.plurals.tab_selection_editor_bookmark_tabs_action_button,
                R.plurals.accessibility_tab_selection_editor_bookmark_tabs_action_button,
                drawable);
        mActivity = activity;
        mDelegate = delegate;
    }

    private static class TabListEditorBookmarkActionDelegateImpl
            implements TabListEditorBookmarkActionDelegate {
        @Override
        public void bookmarkTabsAndShowSnackbar(
                Activity activity, List<Tab> tabs, SnackbarManager snackbarManager) {
            if (tabs.isEmpty()) return;

            Profile profile = tabs.get(0).getProfile();
            BookmarkModel bookmarkModel = BookmarkModel.getForProfile(profile);
            bookmarkModel.finishLoadingBookmarkModel(
                    () -> {
                        BookmarkUtils.addBookmarksOnMultiSelect(
                                activity, bookmarkModel, tabs, snackbarManager);
                    });
        }
    }

    @Override
    public void onSelectionStateChange(List<Integer> tabIds) {
        int size =
                editorSupportsActionOnRelatedTabs()
                        ? getTabCountIncludingRelatedTabs(getTabGroupModelFilter(), tabIds)
                        : tabIds.size();
        setEnabledAndItemCount(!tabIds.isEmpty(), size);
    }

    @Override
    public boolean performAction(List<Tab> tabs) {
        assert !tabs.isEmpty() : "Bookmark action should not be enabled for no tabs.";
        SnackbarManager snackbarManager = getActionDelegate().getSnackbarManager();
        snackbarManager.dismissAllSnackbars();

        if (mDelegate != null) {
            assert snackbarManager != null;
            mDelegate.bookmarkTabsAndShowSnackbar(mActivity, tabs, snackbarManager);
        }
        TabUiMetricsHelper.recordSelectionEditorActionMetrics(
                TabListEditorActionMetricGroups.BOOKMARK);
        return true;
    }

    @Override
    public boolean shouldHideEditorAfterAction() {
        return false;
    }

    void setDelegateForTesting(TabListEditorBookmarkActionDelegate delegate) {
        var oldValue = mDelegate;
        mDelegate = delegate;
        ResettersForTesting.register(() -> mDelegate = oldValue);
    }
}