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

Commit bfc0c381 authored by Sunny Goyal's avatar Sunny Goyal
Browse files

Updating ItemInfoMatcher to work with java streams

Adding support for bulk removing items from a folder icon.
This fixes workspace item removal when a folder gets replaced
to an icon during the delete operation.

- Lets say user has a folder with the same app twice.
- User disables that app.
- Launcher removes all shorcuts of that app

However, because we call "replaceFolderWithFinalItem" during
this removal, we end up creating a new shortcut that does
not get tracked by the removal, so the user is left with
an enabled icon of the disabled app.

Bug: 162378169
Test: manual test, repo steps in bug
Change-Id: Iaf6550894c156b3b5ec2a5aa58bab76a4a28819e
parent f1db62cc
Loading
Loading
Loading
Loading
+22 −32
Original line number Diff line number Diff line
@@ -111,9 +111,11 @@ import com.android.launcher3.widget.WidgetManagerHelper;
import com.android.systemui.plugins.shared.LauncherOverlayManager.LauncherOverlay;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
 * The workspace is a wide area with a wallpaper and a finite number of pages.
@@ -3002,38 +3004,27 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
     * shortcuts are not removed.
     */
    public void removeItemsByMatcher(final ItemInfoMatcher matcher) {
        for (final CellLayout layoutParent: getWorkspaceAndHotseatCellLayouts()) {
            final ViewGroup layout = layoutParent.getShortcutsAndWidgets();

            IntSparseArrayMap<View> idToViewMap = new IntSparseArrayMap<>();
            ArrayList<ItemInfo> items = new ArrayList<>();
            for (int j = 0; j < layout.getChildCount(); j++) {
                final View view = layout.getChildAt(j);
                if (view.getTag() instanceof ItemInfo) {
                    ItemInfo item = (ItemInfo) view.getTag();
                    items.add(item);
                    idToViewMap.put(item.id, view);
                }
            }

            for (ItemInfo itemToRemove : matcher.filterItemInfos(items)) {
                View child = idToViewMap.get(itemToRemove.id);
        for (CellLayout layout : getWorkspaceAndHotseatCellLayouts()) {
            ShortcutAndWidgetContainer container = layout.getShortcutsAndWidgets();
            // Iterate in reverse order as we are removing items
            for (int i = container.getChildCount() - 1; i >= 0; i--) {
                View child = container.getChildAt(i);
                ItemInfo info = (ItemInfo) child.getTag();

                if (child != null) {
                    // Note: We can not remove the view directly from CellLayoutChildren as this
                    // does not re-mark the spaces as unoccupied.
                    layoutParent.removeViewInLayout(child);
                if (matcher.matchesInfo(info)) {
                    layout.removeViewInLayout(child);
                    if (child instanceof DropTarget) {
                        mDragController.removeDropTarget((DropTarget) child);
                    }
                } else if (itemToRemove.container >= 0) {
                    // The item may belong to a folder.
                    View parent = idToViewMap.get(itemToRemove.container);
                    if (parent instanceof FolderIcon) {
                        FolderInfo folderInfo = (FolderInfo) parent.getTag();
                        folderInfo.remove((WorkspaceItemInfo) itemToRemove, false);
                        if (((FolderIcon) parent).getFolder().isOpen()) {
                            ((FolderIcon) parent).getFolder().close(false /* animate */);
                } else if (child instanceof FolderIcon) {
                    FolderInfo folderInfo = (FolderInfo) info;
                    List<WorkspaceItemInfo> matches = folderInfo.contents.stream()
                            .filter(matcher::matchesInfo)
                            .collect(Collectors.toList());
                    if (!matches.isEmpty()) {
                        folderInfo.removeAll(matches, false);
                        if (((FolderIcon) child).getFolder().isOpen()) {
                            ((FolderIcon) child).getFolder().close(false /* animate */);
                        }
                    }
                }
@@ -3143,9 +3134,8 @@ public class Workspace extends PagedView<WorkspacePageIndicator>
    }

    public void removeAbandonedPromise(String packageName, UserHandle user) {
        HashSet<String> packages = new HashSet<>(1);
        packages.add(packageName);
        ItemInfoMatcher matcher = ItemInfoMatcher.ofPackages(packages, user);
        ItemInfoMatcher matcher = ItemInfoMatcher.ofPackages(
                Collections.singleton(packageName), user);
        mLauncher.getModelWriter().deleteItemsFromDatabase(matcher);
        removeItemsByMatcher(matcher);
    }
+3 −3
Original line number Diff line number Diff line
@@ -1394,10 +1394,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
        mItemsInvalidated = true;
    }

    public void onRemove(WorkspaceItemInfo item) {
    @Override
    public void onRemove(List<WorkspaceItemInfo> items) {
        mItemsInvalidated = true;
        View v = getViewForInfo(item);
        mContent.removeItem(v);
        items.stream().map(this::getViewForInfo).forEach(mContent::removeItem);
        if (mState == STATE_ANIMATING) {
            mRearrangeOnClose = true;
        } else {
+2 −2
Original line number Diff line number Diff line
@@ -695,9 +695,9 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
    }

    @Override
    public void onRemove(WorkspaceItemInfo item) {
    public void onRemove(List<WorkspaceItemInfo> items) {
        boolean wasDotted = mDotInfo.hasDot();
        mDotInfo.subtractDotInfo(mActivity.getDotInfoForItem(item));
        items.stream().map(mActivity::getDotInfoForItem).forEach(mDotInfo::subtractDotInfo);
        boolean isDotted = mDotInfo.hasDot();
        updateDotScale(wasDotted, isDotted);
        setContentDescription(getAccessiblityTitle(mInfo.title));
+4 −1
Original line number Diff line number Diff line
@@ -51,6 +51,7 @@ import java.util.List;
import java.util.concurrent.Executor;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import java.util.stream.StreamSupport;

/**
 * Class for handling model updates.
@@ -259,7 +260,9 @@ public class ModelWriter {
     * Removes all the items from the database matching {@param matcher}.
     */
    public void deleteItemsFromDatabase(ItemInfoMatcher matcher) {
        deleteItemsFromDatabase(matcher.filterItemInfos(mBgDataModel.itemsIdMap));
        deleteItemsFromDatabase(StreamSupport.stream(mBgDataModel.itemsIdMap.spliterator(), false)
                        .filter(matcher::matchesInfo)
                        .collect(Collectors.toList()));
    }

    /**
+14 −5
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.util.ContentWriter;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.OptionalInt;
import java.util.stream.IntStream;

@@ -137,9 +139,16 @@ public class FolderInfo extends ItemInfo {
     * @param item
     */
    public void remove(WorkspaceItemInfo item, boolean animate) {
        contents.remove(item);
        removeAll(Collections.singletonList(item), animate);
    }

    /**
     * Remove all matching app or shortcut. Does not change the DB.
     */
    public void removeAll(List<WorkspaceItemInfo> items, boolean animate) {
        contents.removeAll(items);
        for (int i = 0; i < mListeners.size(); i++) {
            mListeners.get(i).onRemove(item);
            mListeners.get(i).onRemove(items);
        }
        itemsChanged(animate);
    }
@@ -166,9 +175,9 @@ public class FolderInfo extends ItemInfo {
    }

    public interface FolderListener {
        public void onAdd(WorkspaceItemInfo item, int rank);
        public void onRemove(WorkspaceItemInfo item);
        public void onItemsChanged(boolean animate);
        void onAdd(WorkspaceItemInfo item, int rank);
        void onRemove(List<WorkspaceItemInfo> item);
        void onItemsChanged(boolean animate);
    }

    public boolean hasOption(int optionFlag) {
Loading