Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 6babde40 authored by Shamali Patwa's avatar Shamali Patwa Committed by Android (Google) Code Review
Browse files

Merge "Move out picker related methods from widgets model" into main

parents d890a9e3 54bd36ef
Loading
Loading
Loading
Loading
+21 −26
Original line number Diff line number Diff line
@@ -47,11 +47,11 @@ import com.android.launcher3.model.WidgetItem;
import com.android.launcher3.model.WidgetPredictionsRequester;
import com.android.launcher3.model.WidgetsModel;
import com.android.launcher3.model.data.ItemInfo;
import com.android.launcher3.model.data.PackageItemInfo;
import com.android.launcher3.popup.PopupDataProvider;
import com.android.launcher3.util.ComponentKey;
import com.android.launcher3.widget.WidgetCell;
import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.picker.WidgetsFullSheet;

import java.util.ArrayList;
@@ -60,10 +60,8 @@ import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

/** An Activity that can host Launcher's widget picker. */
public class WidgetPickerActivity extends BaseActivity {
@@ -112,7 +110,8 @@ public class WidgetPickerActivity extends BaseActivity {
    private WidgetsModel mModel;
    private LauncherAppState mApp;
    private WidgetPredictionsRequester mWidgetPredictionsRequester;
    private final PopupDataProvider mPopupDataProvider = new PopupDataProvider(i -> {});
    private final PopupDataProvider mPopupDataProvider = new PopupDataProvider(i -> {
    });

    private int mDesiredWidgetWidth;
    private int mDesiredWidgetHeight;
@@ -287,41 +286,37 @@ public class WidgetPickerActivity extends BaseActivity {
        };
    }

    /** Updates the model with widgets, applies filters and launches the widgets sheet once
     * widgets are available */
    /**
     * Updates the model with widgets, applies filters and launches the widgets sheet once
     * widgets are available
     */
    private void refreshAndBindWidgets() {
        MODEL_EXECUTOR.execute(() -> {
            LauncherAppState app = LauncherAppState.getInstance(this);
            Context context = app.getContext();

            mModel.update(app, null);
            final List<WidgetsListBaseEntry> allWidgets =
                    mModel.getFilteredWidgetsListForPicker(context, mWidgetsFilter);
            final List<WidgetsListBaseEntry> defaultWidgets =
                    shouldShowDefaultWidgets() ? mModel.getFilteredWidgetsListForPicker(context,
                            mDefaultWidgetsFilter) : List.of();
            bindWidgets(allWidgets, defaultWidgets);
            bindWidgets(mModel.getWidgetsByPackageItem());
            // Open sheet once widgets are available, so that it doesn't interrupt the open
            // animation.
            openWidgetsSheet();
            if (mUiSurface != null) {
                Map<ComponentKey, WidgetItem> allWidgetItems = allWidgets.stream()
                        .filter(entry -> entry instanceof WidgetsListContentEntry)
                        .flatMap(entry -> entry.mWidgets.stream())
                        .distinct()
                        .collect(Collectors.toMap(
                                widget -> new ComponentKey(widget.componentName, widget.user),
                                Function.identity()
                        ));
                mWidgetPredictionsRequester = new WidgetPredictionsRequester(app.getContext(),
                        mUiSurface, allWidgetItems);
                        mUiSurface, mModel.getWidgetsByComponentKey());
                mWidgetPredictionsRequester.request(mAddedWidgets, this::bindRecommendedWidgets);
            }
        });
    }

    private void bindWidgets(List<WidgetsListBaseEntry> allWidgets,
            List<WidgetsListBaseEntry> defaultWidgets) {
    private void bindWidgets(Map<PackageItemInfo, List<WidgetItem>> widgets) {
        WidgetsListBaseEntriesBuilder builder = new WidgetsListBaseEntriesBuilder(
                mApp.getContext());

        final List<WidgetsListBaseEntry> allWidgets = builder.build(widgets, mWidgetsFilter);
        final List<WidgetsListBaseEntry> defaultWidgets =
                shouldShowDefaultWidgets() ? builder.build(widgets,
                        mDefaultWidgetsFilter) : List.of();

        MAIN_EXECUTOR.execute(() -> mPopupDataProvider.setAllWidgets(allWidgets, defaultWidgets));
    }

@@ -392,7 +387,7 @@ public class WidgetPickerActivity extends BaseActivity {
            mActiveOnBackAnimationCallback.onBackCancelled();
            mActiveOnBackAnimationCallback = null;
        }
    };
    }

    private boolean shouldShowDefaultWidgets() {
        // If optional filters such as size filter are present, we display them as default widgets.
+3 −2
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import com.android.launcher3.util.LooperExecutor;
import com.android.launcher3.util.LooperIdleLock;
import com.android.launcher3.util.PackageUserKey;
import com.android.launcher3.util.RunnableList;
import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;

import java.util.ArrayList;
@@ -195,8 +196,8 @@ public class BaseLauncherBinder {
        if (!WIDGETS_ENABLED) {
            return;
        }
        final List<WidgetsListBaseEntry> widgets =
                mBgDataModel.widgetsModel.getWidgetsListForPicker(mApp.getContext());
        List<WidgetsListBaseEntry> widgets = new WidgetsListBaseEntriesBuilder(mApp.getContext())
                .build(mBgDataModel.widgetsModel.getWidgetsByPackageItem());
        executeCallbacksTask(c -> c.bindAllWidgets(widgets), mUiExecutor);
    }

+4 −1
Original line number Diff line number Diff line
@@ -24,6 +24,7 @@ import com.android.launcher3.model.BgDataModel.FixedContainerItems
import com.android.launcher3.model.data.ItemInfo
import com.android.launcher3.model.data.WorkspaceItemInfo
import com.android.launcher3.util.PackageUserKey
import com.android.launcher3.widget.model.WidgetsListBaseEntriesBuilder
import java.util.Objects
import java.util.concurrent.Executor
import java.util.function.Predicate
@@ -78,7 +79,9 @@ class ModelTaskController(
    }

    fun bindUpdatedWidgets(dataModel: BgDataModel) {
        val widgets = dataModel.widgetsModel.getWidgetsListForPicker(app.context)
        val widgets =
            WidgetsListBaseEntriesBuilder(app.context)
                .build(dataModel.widgetsModel.widgetsByPackageItem)
        scheduleCallbackTask { it.bindAllWidgets(widgets) }
    }

+5 −47
Original line number Diff line number Diff line
@@ -26,7 +26,6 @@ import com.android.launcher3.AppFilter;
import com.android.launcher3.InvariantDeviceProfile;
import com.android.launcher3.LauncherAppState;
import com.android.launcher3.Utilities;
import com.android.launcher3.compat.AlphabeticIndexCompat;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.icons.ComponentWithLabelAndIcon;
import com.android.launcher3.icons.IconCache;
@@ -39,9 +38,6 @@ import com.android.launcher3.util.Preconditions;
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
import com.android.launcher3.widget.WidgetManagerHelper;
import com.android.launcher3.widget.WidgetSections;
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
import com.android.launcher3.widget.model.WidgetsListContentEntry;
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
import com.android.wm.shell.Flags;

import java.util.ArrayList;
@@ -75,6 +71,9 @@ public class WidgetsModel {
     * Returns all widgets keyed by their component key.
     */
    public synchronized Map<ComponentKey, WidgetItem> getWidgetsByComponentKey() {
        if (!WIDGETS_ENABLED) {
            return Collections.emptyMap();
        }
        return mWidgetsByPackageItem.values().stream()
                .flatMap(Collection::stream).distinct()
                .collect(Collectors.toMap(
@@ -87,51 +86,10 @@ public class WidgetsModel {
     * Returns widgets grouped by the package item that they should belong to.
     */
    public synchronized Map<PackageItemInfo, List<WidgetItem>> getWidgetsByPackageItem() {
        return mWidgetsByPackageItem;
    }

    /**
     * Returns a list of {@link WidgetsListBaseEntry} filtered using given widget item filter. All
     * {@link WidgetItem}s in a single row are sorted (based on label and user), but the overall
     * list of {@link WidgetsListBaseEntry}s is not sorted.
     *
     * @see com.android.launcher3.widget.picker.WidgetsListAdapter#setWidgets(List)
     */
    public synchronized ArrayList<WidgetsListBaseEntry> getFilteredWidgetsListForPicker(
            Context context,
            Predicate<WidgetItem> widgetItemFilter) {
        if (!WIDGETS_ENABLED) {
            return new ArrayList<>();
            return Collections.emptyMap();
        }
        ArrayList<WidgetsListBaseEntry> result = new ArrayList<>();
        AlphabeticIndexCompat indexer = new AlphabeticIndexCompat(context);

        for (Map.Entry<PackageItemInfo, List<WidgetItem>> entry :
                mWidgetsByPackageItem.entrySet()) {
            PackageItemInfo pkgItem = entry.getKey();
            List<WidgetItem> widgetItems = entry.getValue()
                    .stream()
                    .filter(widgetItemFilter).toList();
            if (!widgetItems.isEmpty()) {
                String sectionName = (pkgItem.title == null) ? "" :
                        indexer.computeSectionName(pkgItem.title);
                result.add(WidgetsListHeaderEntry.create(pkgItem, sectionName, widgetItems));
                result.add(new WidgetsListContentEntry(pkgItem, sectionName, widgetItems));
            }
        }
        return result;
    }

    /**
     * Returns a list of {@link WidgetsListBaseEntry}. All {@link WidgetItem} in a single row
     * are sorted (based on label and user), but the overall list of
     * {@link WidgetsListBaseEntry}s is not sorted.
     *
     * @see com.android.launcher3.widget.picker.WidgetsListAdapter#setWidgets(List)
     */
    public synchronized ArrayList<WidgetsListBaseEntry> getWidgetsListForPicker(Context context) {
        // return all items
        return getFilteredWidgetsListForPicker(context, /*widgetItemFilter=*/ item -> true);
        return mWidgetsByPackageItem;
    }

    /**
+51 −0
Original line number Diff line number Diff line
/*
 * Copyright (C) 2024 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.android.launcher3.widget.model

import android.content.Context
import com.android.launcher3.compat.AlphabeticIndexCompat
import com.android.launcher3.model.WidgetItem
import com.android.launcher3.model.data.PackageItemInfo
import java.util.function.Predicate

/**
 * A helper class that builds the list of [WidgetsListBaseEntry]s used by the UI to display widgets.
 */
class WidgetsListBaseEntriesBuilder(val context: Context) {

    /** Builds the widgets list entries in a format understandable by the widget picking UI. */
    @JvmOverloads
    fun build(
        widgetsByPackageItem: Map<PackageItemInfo, List<WidgetItem>>,
        widgetFilter: Predicate<WidgetItem> = Predicate<WidgetItem> { true },
    ): List<WidgetsListBaseEntry> {
        val indexer = AlphabeticIndexCompat(context)

        return buildList {
            for ((pkgItem, widgetItems) in widgetsByPackageItem.entries) {
                val filteredWidgetItems = widgetItems.filter { widgetFilter.test(it) }
                if (filteredWidgetItems.isNotEmpty()) {
                    // Enables fast scroll popup to show right characters in all locales.
                    val sectionName = pkgItem.title?.let { indexer.computeSectionName(it) } ?: ""

                    add(WidgetsListHeaderEntry.create(pkgItem, sectionName, filteredWidgetItems))
                    add(WidgetsListContentEntry(pkgItem, sectionName, filteredWidgetItems))
                }
            }
        }
    }
}
Loading