chromium/chrome/android/features/tab_ui/java/src/org/chromium/chrome/browser/tasks/tab_management/TabListEditorUngroupAction.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.content.Context;
import android.graphics.drawable.Drawable;

import androidx.annotation.Nullable;
import androidx.appcompat.content.res.AppCompatResources;

import org.chromium.chrome.browser.tab.Tab;
import org.chromium.chrome.browser.tasks.tab_groups.TabGroupModelFilter;
import org.chromium.chrome.browser.tasks.tab_management.ActionConfirmationManager.ConfirmationResult;
import org.chromium.chrome.browser.tasks.tab_management.TabUiMetricsHelper.TabListEditorActionMetricGroups;
import org.chromium.chrome.tab_ui.R;

import java.util.List;
import java.util.stream.Collectors;

/** Ungroup action for the {@link TabListEditorMenu}. */
public class TabListEditorUngroupAction extends TabListEditorAction {
    /**
     * Create an action for ungrouping tabs.
     *
     * @param context 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.
     * @param actionConfirmationManager To show confirmation dialogs.
     */
    public static TabListEditorAction createAction(
            Context context,
            @ShowMode int showMode,
            @ButtonType int buttonType,
            @IconPosition int iconPosition,
            @Nullable ActionConfirmationManager actionConfirmationManager) {
        Drawable drawable = AppCompatResources.getDrawable(context, R.drawable.ic_widgets);
        return new TabListEditorUngroupAction(
                showMode, buttonType, iconPosition, drawable, actionConfirmationManager);
    }

    private final ActionConfirmationManager mActionConfirmationManager;

    private TabListEditorUngroupAction(
            @ShowMode int showMode,
            @ButtonType int buttonType,
            @IconPosition int iconPosition,
            Drawable drawable,
            @Nullable ActionConfirmationManager actionConfirmationManager) {
        super(
                R.id.tab_list_editor_ungroup_menu_item,
                showMode,
                buttonType,
                iconPosition,
                R.plurals.tab_selection_editor_ungroup_tabs,
                R.plurals.accessibility_tab_selection_editor_ungroup_tabs,
                drawable);
        mActionConfirmationManager = actionConfirmationManager;
    }

    @Override
    public void onSelectionStateChange(List<Integer> tabIds) {
        setEnabledAndItemCount(!tabIds.isEmpty(), tabIds.size());
    }

    @Override
    public boolean performAction(List<Tab> tabsToUngroup) {
        assert !editorSupportsActionOnRelatedTabs()
                : "Ungrouping is not supported when actions apply to related tabs.";

        if (tabsToUngroup == null || tabsToUngroup.isEmpty()) return false;

        TabGroupModelFilter filter = getTabGroupModelFilter();
        if (mActionConfirmationManager == null || filter.isIncognito()) {
            doRemoveTabs(tabsToUngroup);
            return true;
        }

        Tab firstTab = tabsToUngroup.get(0);
        List<Tab> relatedTabs = filter.getRelatedTabList(firstTab.getId());
        // Only trigger trigger confirmation when all the tabs are being removed, as that is when
        // the group will be deleted as a result.
        if (relatedTabs.size() <= tabsToUngroup.size()) {
            List<Integer> tabIdList =
                    tabsToUngroup.stream().map(Tab::getId).collect(Collectors.toList());
            mActionConfirmationManager.processRemoveTabAttempt(
                    tabIdList,
                    (@ConfirmationResult Integer result) -> {
                        if (result != ConfirmationResult.CONFIRMATION_NEGATIVE) {
                            doRemoveTabs(tabsToUngroup);
                        }
                    });
        } else {
            doRemoveTabs(tabsToUngroup);
        }

        return true;
    }

    private void doRemoveTabs(List<Tab> tabs) {
        TabGroupModelFilter filter = getTabGroupModelFilter();
        for (Tab tab : tabs) {
            filter.moveTabOutOfGroup(tab.getId());
        }
        TabUiMetricsHelper.recordSelectionEditorActionMetrics(
                TabListEditorActionMetricGroups.UNGROUP);
    }

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