diff options
14 files changed, 188 insertions, 363 deletions
diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java index 4c94432bd9..b2989cd81a 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarView.java @@ -368,23 +368,9 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar if (!(view.getTag() instanceof CollectionInfo)) { mActivityContext.getViewCache().recycleView(view.getSourceLayoutResId(), view); } - if (view instanceof FolderIcon fi) { - // We should clear FolderInfo's Folder and FolderIcon to avoid memory leak. - fi.removeListeners(); - } view.setTag(null); } - /** Loop through all {@link FolderIcon} as child views and clear listeners to avoid leak. */ - public void removeFolderIconListeners() { - final int childCount = getChildCount(); - for (int i = 0; i < childCount; i++) { - if (getChildAt(i) instanceof FolderIcon fi) { - fi.removeListeners(); - } - } - } - /** Inflates/binds the hotseat items and recent tasks to the view. */ protected void updateItems(ItemInfo[] hotseatItemInfos, List<GroupTask> recentTasks) { if (mActivityContext.isDestroyed()) return; @@ -445,7 +431,6 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar private void updateItemsWithLayoutTransition( ItemInfo[] hotseatItemInfos, List<GroupTask> recentTasks) { - if (mNumStaticViews == 0) { mNumStaticViews = addStaticViews(); } @@ -579,6 +564,9 @@ public class TaskbarView extends FrameLayout implements FolderIcon.FolderIconPar LayoutParams lp = new LayoutParams(mIconTouchSize, mIconTouchSize); hotseatView.setPadding(mItemPadding, mItemPadding, mItemPadding, mItemPadding); addView(hotseatView, mNextViewIndex, lp); + } else if (hotseatView instanceof FolderIcon fi) { + fi.onItemsChanged(false); + fi.getFolder().reapplyItemInfo(); } // Apply the Hotseat ItemInfos, or hide the view if there is none for a given index. diff --git a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java index 605171a7aa..6786aed445 100644 --- a/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java +++ b/quickstep/src/com/android/launcher3/taskbar/TaskbarViewController.java @@ -393,7 +393,6 @@ public class TaskbarViewController implements TaskbarControllers.LoggableTaskbar if (enableTaskbarPinning()) { mTaskbarView.removeOnLayoutChangeListener(mTaskbarViewLayoutChangeListener); } - mTaskbarView.removeFolderIconListeners(); LauncherAppState.getInstance(mActivity).getModel().removeCallbacks(mModelCallbacks); mActivity.removeOnDeviceProfileChangeListener(mDeviceProfileChangeListener); } diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 289f175aa9..5c9392d69d 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -1472,8 +1472,7 @@ public class Launcher extends StatefulActivity<LauncherState> // Adding a shortcut to a Folder. FolderIcon folderIcon = findFolderIcon(container); if (folderIcon != null) { - FolderInfo folderInfo = (FolderInfo) folderIcon.getTag(); - folderInfo.add(info, args.rank, false); + folderIcon.getFolder().addFolderContent(info, args.rank, false); } else { Log.e(TAG, "Could not find folder with id " + container + " to add shortcut."); } @@ -1792,7 +1791,6 @@ public class Launcher extends StatefulActivity<LauncherState> SettingsCache.INSTANCE.get(this).unregister(TOUCHPAD_NATURAL_SCROLLING, mNaturalScrollingChangedListener); ScreenOnTracker.INSTANCE.get(this).removeListener(mScreenOnListener); - mWorkspace.removeFolderListeners(); PluginManagerWrapper.INSTANCE.get(this).removePluginListener(this); mModel.removeCallbacks(this); @@ -2053,9 +2051,10 @@ public class Launcher extends StatefulActivity<LauncherState> @Nullable final String reason) { if (itemInfo instanceof WorkspaceItemInfo) { View collectionIcon = mWorkspace.getViewByItemId(itemInfo.container); - if (collectionIcon instanceof FolderIcon) { + if (collectionIcon instanceof FolderIcon folderIcon) { // Remove the shortcut from the folder before removing it from launcher - ((FolderInfo) collectionIcon.getTag()).remove((WorkspaceItemInfo) itemInfo, true); + Folder folder = folderIcon.getFolder(); + folder.removeFolderContent(true, itemInfo); } else if (collectionIcon instanceof AppPairIcon appPairIcon) { removeItem(appPairIcon, appPairIcon.getInfo(), deleteFromDb, "removing app pair because one of its member apps was removed"); @@ -2066,9 +2065,6 @@ public class Launcher extends StatefulActivity<LauncherState> getModelWriter().deleteItemFromDatabase(itemInfo, reason); } } else if (itemInfo instanceof CollectionInfo ci) { - if (v instanceof FolderIcon) { - ((FolderIcon) v).removeListeners(); - } mWorkspace.removeWorkspaceItem(v); if (deleteFromDb) { getModelWriter().deleteCollectionAndContentsFromDatabase(ci); diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 6ed183ab23..59f84ab891 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -137,7 +137,6 @@ import java.util.Iterator; import java.util.List; import java.util.function.Consumer; 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. @@ -659,7 +658,6 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T> } // Remove the pages and clear the screen models - removeFolderListeners(); removeAllViews(); mScreenOrder.clear(); mWorkspaceScreens.clear(); @@ -1914,7 +1912,7 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T> boolean aboveShortcut = Folder.willAccept(dropOverView.getTag()) && ((ItemInfo) dropOverView.getTag()).container != CONTAINER_HOTSEAT_PREDICTION; - boolean willBecomeShortcut = Folder.willAcceptItemType(info.itemType); + boolean willBecomeShortcut = FolderInfo.willAcceptItemType(info.itemType); return (aboveShortcut && willBecomeShortcut); } @@ -1994,8 +1992,8 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T> fi.performCreateAnimation(destInfo, v, sourceInfo, d, folderLocation, scale); } else { fi.prepareCreateAnimation(v); - fi.addItem(destInfo); - fi.addItem(sourceInfo); + fi.getFolder().addFolderContent(destInfo); + fi.getFolder().addFolderContent(sourceInfo); } return true; } @@ -3209,21 +3207,6 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T> }); } - /** - * Removes all folder listeners - */ - public void removeFolderListeners() { - mapOverItems(new ItemOperator() { - @Override - public boolean evaluate(ItemInfo info, View view) { - if (view instanceof FolderIcon) { - ((FolderIcon) view).removeListeners(); - } - return false; - } - }); - } - public boolean isDropEnabled() { return true; } @@ -3349,15 +3332,15 @@ public class Workspace<T extends View & PageIndicator> extends PagedView<T> if (child instanceof DropTarget) { mDragController.removeDropTarget((DropTarget) child); } - } else if (child instanceof FolderIcon) { + } else if (child instanceof FolderIcon folderIcon) { FolderInfo folderInfo = (FolderInfo) info; - List<ItemInfo> matches = folderInfo.getContents().stream() + ItemInfo[] matches = folderInfo.getContents().stream() .filter(matcher) - .collect(Collectors.toList()); - if (!matches.isEmpty()) { - folderInfo.removeAll(matches, false); - if (((FolderIcon) child).getFolder().isOpen()) { - ((FolderIcon) child).getFolder().close(false /* animate */); + .toArray(ItemInfo[]::new); + if (matches.length > 0) { + folderIcon.getFolder().removeFolderContent(false, matches); + if (folderIcon.getFolder().isOpen()) { + folderIcon.getFolder().close(false /* animate */); } } } else if (info instanceof AppPairInfo api) { diff --git a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java index cd91f8e00b..df34ccf090 100644 --- a/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java +++ b/src/com/android/launcher3/accessibility/LauncherAccessibilityDelegate.java @@ -519,7 +519,7 @@ public class LauncherAccessibilityDelegate extends BaseAccessibilityDelegate<Lau Folder folder = Folder.getOpen(mContext); folder.close(true); WorkspaceItemInfo info = (WorkspaceItemInfo) item; - folder.getInfo().remove(info, false); + folder.removeFolderContent(false, info); final int[] coordinates = new int[2]; final int screenId = findSpaceOnWorkspace(item, coordinates); diff --git a/src/com/android/launcher3/dot/FolderDotInfo.java b/src/com/android/launcher3/dot/FolderDotInfo.java index 54800a07a8..cb91db7654 100644 --- a/src/com/android/launcher3/dot/FolderDotInfo.java +++ b/src/com/android/launcher3/dot/FolderDotInfo.java @@ -30,6 +30,10 @@ public class FolderDotInfo extends DotInfo { private int mNumNotifications; + public void reset() { + mNumNotifications = 0; + } + public void addDotInfo(DotInfo dotToAdd) { if (dotToAdd == null) { return; @@ -39,15 +43,6 @@ public class FolderDotInfo extends DotInfo { mNumNotifications, MIN_COUNT, DotInfo.MAX_COUNT); } - public void subtractDotInfo(DotInfo dotToSubtract) { - if (dotToSubtract == null) { - return; - } - mNumNotifications -= dotToSubtract.getNotificationKeys().size(); - mNumNotifications = Utilities.boundToRange( - mNumNotifications, MIN_COUNT, DotInfo.MAX_COUNT); - } - @Override public int getNotificationCount() { return mNumNotifications; diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 0ae95196fd..967af053fb 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -19,9 +19,6 @@ package com.android.launcher3.folder; import static android.text.TextUtils.isEmpty; import static com.android.launcher3.LauncherAnimUtils.SPRING_LOADED_EXIT_DELAY; -import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; -import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR; -import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.LauncherState.EDIT_MODE; import static com.android.launcher3.LauncherState.NORMAL; import static com.android.launcher3.compat.AccessibilityManagerCompat.sendCustomAccessibilityEvent; @@ -29,6 +26,7 @@ import static com.android.launcher3.config.FeatureFlags.ALWAYS_USE_HARDWARE_OPTI import static com.android.launcher3.folder.FolderGridOrganizer.createFolderGridOrganizer; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_LABEL_UPDATED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_ITEM_DROP_COMPLETED; +import static com.android.launcher3.model.data.FolderInfo.willAcceptItemType; import static com.android.launcher3.testing.shared.TestProtocol.FOLDER_OPENED_MESSAGE; import static com.android.launcher3.util.window.RefreshRateTracker.getSingleFrameMs; @@ -95,7 +93,6 @@ import com.android.launcher3.logger.LauncherAtom.ToState; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.logging.StatsLogManager.StatsLogger; import com.android.launcher3.model.data.FolderInfo; -import com.android.launcher3.model.data.FolderInfo.FolderListener; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemFactory; import com.android.launcher3.model.data.WorkspaceItemInfo; @@ -111,6 +108,7 @@ import com.android.launcher3.widget.PendingAddShortcutInfo; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; +import java.util.Arrays; import java.util.Comparator; import java.util.List; import java.util.Objects; @@ -122,7 +120,7 @@ import java.util.stream.Stream; * Represents a set of icons chosen by the user or generated by the system. */ public class Folder extends AbstractFloatingView implements ClipPathView, DragSource, - View.OnLongClickListener, DropTarget, FolderListener, TextView.OnEditorActionListener, + View.OnLongClickListener, DropTarget, TextView.OnEditorActionListener, View.OnFocusChangeListener, DragListener, ExtendedEditText.OnBackKeyListener, LauncherBindableItemsContainer { private static final String TAG = "Launcher.Folder"; @@ -179,15 +177,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo return o instanceof ItemInfo info && willAcceptItemType(info.itemType); } - /** - * Checks if {@code itemType} is a type that can be placed in folders. - */ - public static boolean willAcceptItemType(int itemType) { - return itemType == ITEM_TYPE_APPLICATION - || itemType == ITEM_TYPE_DEEP_SHORTCUT - || itemType == ITEM_TYPE_APP_PAIR; - } - private Alarm mReorderAlarm = new Alarm(Looper.getMainLooper()); private Alarm mOnExitAlarm = new Alarm(Looper.getMainLooper()); private Alarm mOnScrollHintAlarm = new Alarm(Looper.getMainLooper()); @@ -243,7 +232,10 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo private boolean mIsExternalDrag; private boolean mIsDragInProgress = false; private boolean mDeleteFolderOnDropCompleted = false; + private boolean mSuppressFolderDeletion = false; + private boolean mSuppressContentUpdate = false; + private boolean mItemAddedBackToSelfViaIcon = false; private boolean mIsEditingName = false; @@ -385,9 +377,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo // We do not want to get events for the item being removed, as they will get handled // when the drop completes - try (SuppressInfoChanges s = new SuppressInfoChanges()) { - mInfo.remove(dragObject.dragInfo, true); - } + executeWithContentUpdateSuppressed(() -> removeFolderContent(true, dragObject.dragInfo)); + mIsDragInProgress = true; mItemAddedBackToSelfViaIcon = false; } @@ -532,8 +523,17 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo lp.customPosition = true; setLayoutParams(lp); } + reapplyItemInfo(); + // In case any children didn't come across during loading, clean up the folder accordingly + mFolderIcon.post(() -> { + if (getItemCount() <= 1) { + replaceFolderWithFinalItem(); + } + }); + } + + public void reapplyItemInfo() { mItemsInvalidated = true; - mInfo.addListener(this); if (!isEmpty(mInfo.title)) { mFolderName.setText(mInfo.title); @@ -542,15 +542,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mFolderName.setText(""); mFolderName.setHint(R.string.folder_hint_text); } - // In case any children didn't come across during loading, clean up the folder accordingly - mFolderIcon.post(() -> { - if (getItemCount() <= 1) { - replaceFolderWithFinalItem(); - } - }); } - /** * Show suggested folder title in FolderEditText if the first suggestion is non-empty, push * rest of the suggestions to InputMethodManager. @@ -680,7 +673,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo if (!shouldAnimateOpen(items)) { return; } - Folder openFolder = getOpen(mActivityContext); closeOpenFolder(openFolder); @@ -954,9 +946,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo @Override public boolean acceptDrop(DragObject d) { - final ItemInfo item = d.dragInfo; - final int itemType = item.itemType; - return Folder.willAcceptItemType(itemType); + return willAcceptItemType(d.dragInfo.itemType); } public void onDragEnter(DragObject d) { @@ -1121,9 +1111,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mContent.arrangeChildren(views); mItemsInvalidated = true; - try (SuppressInfoChanges s = new SuppressInfoChanges()) { - mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */); - } + executeWithContentUpdateSuppressed( + () -> mFolderIcon.onDrop(d, true /* itemReturnedOnFailedDrop */)); } } @@ -1417,9 +1406,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo rearrangeChildren(); // Temporarily suppress the listener, as we did all the work already here. - try (SuppressInfoChanges s = new SuppressInfoChanges()) { - mInfo.add(si, mEmptyCellRank, false); - } + executeWithContentUpdateSuppressed(() -> addFolderContent(si, mEmptyCellRank, false)); // We only need to update the locations if it doesn't get handled in // #onDropCompleted. @@ -1465,37 +1452,66 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo } } - @Override - public void onAdd(ItemInfo item, int rank) { - FolderGridOrganizer verifier = createFolderGridOrganizer( - mActivityContext.getDeviceProfile()).setFolderInfo(mInfo); - verifier.updateRankAndPos(item, rank); - mLauncherDelegate.getModelWriter().addOrMoveItemInDatabase(item, mInfo.id, 0, item.cellX, - item.cellY); - updateItemLocationsInDatabaseBatch(false); + /** Add an app or shortcut */ + public void addFolderContent(ItemInfo item) { + addFolderContent(item, mInfo.getContents().size(), true); + } - if (mContent.areViewsBound()) { - mContent.createAndAddViewForRank(item, rank); + /** Add an app or shortcut for a specified rank */ + public void addFolderContent(ItemInfo item, int rank, boolean animate) { + if (!willAcceptItemType(item.itemType)) { + throw new RuntimeException("tried to add an illegal type into a folder"); } - mItemsInvalidated = true; + + rank = Utilities.boundToRange(rank, 0, mInfo.getContents().size()); + mInfo.getContents().add(rank, item); + + if (!mSuppressContentUpdate) { + FolderGridOrganizer verifier = createFolderGridOrganizer( + mActivityContext.getDeviceProfile()).setFolderInfo(mInfo); + verifier.updateRankAndPos(item, rank); + mLauncherDelegate.getModelWriter().addOrMoveItemInDatabase(item, mInfo.id, 0, + item.cellX, + item.cellY); + updateItemLocationsInDatabaseBatch(false); + + if (mContent.areViewsBound()) { + mContent.createAndAddViewForRank(item, rank); + } + mItemsInvalidated = true; + updateTextViewFocus(); + } + + mLauncherDelegate.getModelWriter().notifyItemModified(mInfo); + mFolderIcon.onItemsChanged(animate); } - @Override - public void onRemove(List<ItemInfo> items) { - mItemsInvalidated = true; - items.stream().map(this::getViewForInfo).forEach(mContent::removeItem); - if (mState == STATE_ANIMATING) { - mRearrangeOnClose = true; - } else { - rearrangeChildren(); + /** Remove all matching app or shortcut. Does not change the DB. */ + public void removeFolderContent(boolean animate, ItemInfo... items) { + List<ItemInfo> itemArray = Arrays.asList(items); + if (mInfo.getContents().removeAll(itemArray)) { + mLauncherDelegate.getModelWriter().notifyItemModified(mInfo); } - if (getItemCount() <= 1) { - if (mIsOpen) { - close(true); + + if (!mSuppressContentUpdate) { + mItemsInvalidated = true; + itemArray.forEach(item -> mContent.removeItem(getViewForInfo(item))); + if (mState == STATE_ANIMATING) { + mRearrangeOnClose = true; } else { - replaceFolderWithFinalItem(); + rearrangeChildren(); + } + if (getItemCount() <= 1) { + if (mIsOpen) { + close(true); + } else { + replaceFolderWithFinalItem(); + } } + updateTextViewFocus(); } + + mFolderIcon.onItemsChanged(animate); } @VisibleForTesting @@ -1503,16 +1519,6 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo return mContent.iterateOverItems((info, view) -> info == item); } - @Override - public void onItemsChanged(boolean animate) { - updateTextViewFocus(); - } - - @Override - public void onTitleChanged(CharSequence title) { - mFolderName.setText(title); - } - /** * Utility methods to iterate over items of the view */ @@ -1666,18 +1672,14 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo } }; - /** - * Temporary resource held while we don't want to handle info changes - */ - private class SuppressInfoChanges implements AutoCloseable { - - SuppressInfoChanges() { - mInfo.removeListener(Folder.this); - } - - @Override - public void close() { - mInfo.addListener(Folder.this); + /** Executes the task while suppressing the content update for the folder */ + private void executeWithContentUpdateSuppressed(Runnable task) { + if (mSuppressContentUpdate) { + task.run(); + } else { + mSuppressContentUpdate = true; + task.run(); + mSuppressContentUpdate = false; updateTextViewFocus(); } } diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 0ed87871cc..1cd9bcc965 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -23,6 +23,7 @@ import static com.android.launcher3.folder.PreviewItemManager.INITIAL_ITEM_ANIMA import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_AUTO_LABELED; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_AUTO_LABELING_SKIPPED_EMPTY_PRIMARY; import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_AUTO_LABELING_SKIPPED_EMPTY_SUGGESTIONS; +import static com.android.launcher3.model.data.FolderInfo.willAcceptItemType; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; @@ -73,7 +74,6 @@ import com.android.launcher3.logging.InstanceId; import com.android.launcher3.logging.StatsLogManager; import com.android.launcher3.model.data.AppPairInfo; import com.android.launcher3.model.data.FolderInfo; -import com.android.launcher3.model.data.FolderInfo.FolderListener; import com.android.launcher3.model.data.FolderInfo.LabelState; import com.android.launcher3.model.data.ItemInfo; import com.android.launcher3.model.data.WorkspaceItemFactory; @@ -92,7 +92,7 @@ import java.util.function.Predicate; /** * An icon that can appear on in the workspace representing an {@link Folder}. */ -public class FolderIcon extends FrameLayout implements FolderListener, FloatingIconViewCompanion, +public class FolderIcon extends FrameLayout implements FloatingIconViewCompanion, DraggableView, Reorderable { private final MultiTranslateDelegate mTranslateDelegate = new MultiTranslateDelegate(this); @@ -127,7 +127,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI private boolean mForceHideDot; @ViewDebug.ExportedProperty(category = "launcher", deepExport = true) - private FolderDotInfo mDotInfo = new FolderDotInfo(); + private final FolderDotInfo mDotInfo = new FolderDotInfo(); private DotRenderer mDotRenderer; @ViewDebug.ExportedProperty(category = "launcher", deepExport = true) private DotRenderer.DrawParams mDotParams; @@ -178,7 +178,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI folder.bind(folderInfo); icon.setFolder(folder); - folderInfo.addListener(icon); return icon; } @@ -217,13 +216,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI icon.mDotRenderer = grid.mDotRendererWorkSpace; icon.setContentDescription(icon.getAccessiblityTitle(folderInfo.title)); - - // Keep the notification dot up to date with the sum of all the content's dots. - FolderDotInfo folderDotInfo = new FolderDotInfo(); - for (ItemInfo si : folderInfo.getContents()) { - folderDotInfo.addDotInfo(activity.getDotInfoForItem(si)); - } - icon.setDotInfo(folderDotInfo); + icon.updateDotInfo(); icon.setAccessibilityDelegate(activity.getAccessibilityDelegate()); @@ -264,22 +257,13 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI } private boolean willAcceptItem(ItemInfo item) { - final int itemType = item.itemType; - return (Folder.willAcceptItemType(itemType) && item != mInfo && !mFolder.isOpen()); + return (willAcceptItemType(item.itemType) && item != mInfo && !mFolder.isOpen()); } public boolean acceptDrop(ItemInfo dragInfo) { return !mFolder.isDestroyed() && willAcceptItem(dragInfo); } - public void addItem(ItemInfo item) { - mInfo.add(item, true); - } - - public void removeItem(ItemInfo item, boolean animate) { - mInfo.remove(item, animate); - } - public void onDragEnter(ItemInfo dragInfo) { if (mFolder.isDestroyed() || !willAcceptItem(dragInfo)) return; CellLayoutLayoutParams lp = (CellLayoutLayoutParams) getLayoutParams(); @@ -308,9 +292,8 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI public void performCreateAnimation(final ItemInfo destInfo, final View destView, final ItemInfo srcInfo, final DragObject d, Rect dstRect, float scaleRelativeToDragLayer) { - final DragView srcView = d.dragView; prepareCreateAnimation(destView); - addItem(destInfo); + getFolder().addFolderContent(destInfo); // This will animate the first item from it's position as an icon into its // position as the first item in the preview mPreviewItemManager.createFirstItemAnimation(false /* reverse */, null) @@ -364,7 +347,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI boolean itemAdded = false; if (itemReturnedOnFailedDrop || index >= MAX_NUM_ITEMS_IN_PREVIEW) { List<ItemInfo> oldPreviewItems = new ArrayList<>(mCurrentPreviewItems); - mInfo.add(item, index, false); + getFolder().addFolderContent(item, index, false); mCurrentPreviewItems.clear(); mCurrentPreviewItems.addAll(getPreviewItemsOnPage(0)); @@ -380,12 +363,12 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI mPreviewItemManager.onDrop(oldPreviewItems, mCurrentPreviewItems, item); itemAdded = true; } else { - removeItem(item, false); + getFolder().removeFolderContent(false, item); } } if (!itemAdded) { - mInfo.add(item, index, true); + getFolder().addFolderContent(item, index, true); } int[] center = new int[2]; @@ -431,7 +414,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI }, DROP_IN_ANIMATION_DURATION); }); } else { - addItem(item); + getFolder().addFolderContent(item); } } @@ -500,9 +483,23 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI ); } - public void setDotInfo(FolderDotInfo dotInfo) { - updateDotScale(mDotInfo.hasDot(), dotInfo.hasDot()); - mDotInfo = dotInfo; + /** Keep the notification dot up to date with the sum of all the content's dots. */ + public void updateDotInfo() { + boolean hadDot = mDotInfo.hasDot(); + mDotInfo.reset(); + for (ItemInfo si : mInfo.getContents()) { + mDotInfo.addDotInfo(mActivity.getDotInfoForItem(si)); + } + boolean isDotted = mDotInfo.hasDot(); + float newDotScale = isDotted ? 1f : 0f; + // Animate when a dot is first added or when it is removed. + if ((hadDot ^ isDotted) && isShown()) { + animateDotScale(newDotScale); + } else { + cancelDotScaleAnim(); + mDotScale = newDotScale; + invalidate(); + } } public ClippedFolderIconLayoutRule getLayoutRule() { @@ -523,22 +520,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI } } - /** - * Sets mDotScale to 1 or 0, animating if wasDotted or isDotted is false - * (the dot is being added or removed). - */ - private void updateDotScale(boolean wasDotted, boolean isDotted) { - float newDotScale = isDotted ? 1f : 0f; - // Animate when a dot is first added or when it is removed. - if ((wasDotted ^ isDotted) && isShown()) { - animateDotScale(newDotScale); - } else { - cancelDotScaleAnim(); - mDotScale = newDotScale; - invalidate(); - } - } - private void cancelDotScaleAnim() { if (mDotScaleAnim != null) { mDotScaleAnim.cancel(); @@ -682,13 +663,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI return mPreviewItemManager.verifyDrawable(who) || super.verifyDrawable(who); } - @Override - public void onItemsChanged(boolean animate) { - updatePreviewItems(animate); - invalidate(); - requestLayout(); - } - private void updatePreviewItems(boolean animate) { mPreviewItemManager.updatePreviewItems(animate); mCurrentPreviewItems.clear(); @@ -702,31 +676,15 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI mPreviewItemManager.updatePreviewItems(itemCheck); } - @Override - public void onAdd(ItemInfo item, int rank) { - updatePreviewItems(false); - boolean wasDotted = mDotInfo.hasDot(); - mDotInfo.addDotInfo(mActivity.getDotInfoForItem(item)); - boolean isDotted = mDotInfo.hasDot(); - updateDotScale(wasDotted, isDotted); - setContentDescription(getAccessiblityTitle(mInfo.title)); - invalidate(); - requestLayout(); - } - - @Override - public void onRemove(List<ItemInfo> items) { + public void onItemsChanged(boolean animate) { updatePreviewItems(false); - boolean wasDotted = mDotInfo.hasDot(); - items.stream().map(mActivity::getDotInfoForItem).forEach(mDotInfo::subtractDotInfo); - boolean isDotted = mDotInfo.hasDot(); - updateDotScale(wasDotted, isDotted); + updateDotInfo(); setContentDescription(getAccessiblityTitle(mInfo.title)); + updatePreviewItems(animate); invalidate(); requestLayout(); } - @Override public void onTitleChanged(CharSequence title) { mFolderName.setText(title); setContentDescription(getAccessiblityTitle(title)); @@ -762,11 +720,6 @@ public class FolderIcon extends FrameLayout implements FolderListener, FloatingI mLongPressHelper.cancelLongPress(); } - public void removeListeners() { - mInfo.removeListener(this); - mInfo.removeListener(mFolder); - } - private boolean isInHotseat() { return mInfo.container == LauncherSettings.Favorites.CONTAINER_HOTSEAT; } diff --git a/src/com/android/launcher3/model/ModelWriter.java b/src/com/android/launcher3/model/ModelWriter.java index 0332775224..dc103a6a3d 100644 --- a/src/com/android/launcher3/model/ModelWriter.java +++ b/src/com/android/launcher3/model/ModelWriter.java @@ -229,7 +229,7 @@ public class ModelWriter { }).executeOnModelThread(); } - private void notifyItemModified(ItemInfo item) { + public void notifyItemModified(ItemInfo item) { notifyOtherCallbacks(c -> c.bindItemsModified(Collections.singletonList(item))); } diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java index 9656ac10b2..4c792a7672 100644 --- a/src/com/android/launcher3/model/data/FolderInfo.java +++ b/src/com/android/launcher3/model/data/FolderInfo.java @@ -20,6 +20,9 @@ import static android.text.TextUtils.isEmpty; import static androidx.core.util.Preconditions.checkNotNull; +import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APPLICATION; +import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_APP_PAIR; +import static com.android.launcher3.LauncherSettings.Favorites.ITEM_TYPE_DEEP_SHORTCUT; import static com.android.launcher3.logger.LauncherAtom.Attribute.EMPTY_LABEL; import static com.android.launcher3.logger.LauncherAtom.Attribute.MANUAL_LABEL; import static com.android.launcher3.logger.LauncherAtom.Attribute.SUGGESTED_LABEL; @@ -30,8 +33,6 @@ import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.android.launcher3.LauncherSettings; -import com.android.launcher3.Utilities; -import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderNameInfos; import com.android.launcher3.logger.LauncherAtom; import com.android.launcher3.logger.LauncherAtom.Attribute; @@ -42,8 +43,6 @@ 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; @@ -52,18 +51,6 @@ import java.util.stream.IntStream; */ public class FolderInfo extends CollectionInfo { - public static final int NO_FLAGS = 0x00000000; - - /** - * The folder is locked in sorted mode - */ - public static final int FLAG_ITEMS_SORTED = 0x00000001; - - /** - * It is a work folder - */ - public static final int FLAG_WORK_FOLDER = 0x00000002; - /** * The multi-page animation has run for this folder */ @@ -95,8 +82,6 @@ public class FolderInfo extends CollectionInfo { } } - public static final String EXTRA_FOLDER_SUGGESTIONS = "suggest"; - public int options; public FolderNameInfos suggestedFolderNames; @@ -106,61 +91,16 @@ public class FolderInfo extends CollectionInfo { */ private final ArrayList<ItemInfo> contents = new ArrayList<>(); - private ArrayList<FolderListener> mListeners = new ArrayList<>(); - public FolderInfo() { itemType = LauncherSettings.Favorites.ITEM_TYPE_FOLDER; } - /** Adds a app or shortcut to the contents ArrayList without animation. */ @Override public void add(@NonNull ItemInfo item) { - add(item, false /* animate */); - } - - /** - * Add an app or shortcut - * - * @param item - */ - public void add(ItemInfo item, boolean animate) { - add(item, getContents().size(), animate); - } - - /** - * Add an app or shortcut for a specified rank. - */ - public void add(ItemInfo item, int rank, boolean animate) { - if (!Folder.willAccept(item)) { + if (!willAcceptItemType(item.itemType)) { throw new RuntimeException("tried to add an illegal type into a folder"); } - - rank = Utilities.boundToRange(rank, 0, getContents().size()); - getContents().add(rank, item); - for (int i = 0; i < mListeners.size(); i++) { - mListeners.get(i).onAdd(item, rank); - } - itemsChanged(animate); - } - - /** - * Remove an app or shortcut. Does not change the DB. - * - * @param item - */ - public void remove(ItemInfo item, boolean animate) { - removeAll(Collections.singletonList(item), animate); - } - - /** - * Remove all matching app or shortcut. Does not change the DB. - */ - public void removeAll(List<ItemInfo> items, boolean animate) { - contents.removeAll(items); - for (int i = 0; i < mListeners.size(); i++) { - mListeners.get(i).onRemove(items); - } - itemsChanged(animate); + getContents().add(item); } /** @@ -197,28 +137,6 @@ public class FolderInfo extends CollectionInfo { writer.put(LauncherSettings.Favorites.OPTIONS, options); } - public void addListener(FolderListener listener) { - mListeners.add(listener); - } - - public void removeListener(FolderListener listener) { - mListeners.remove(listener); - } - - public void itemsChanged(boolean animate) { - for (int i = 0; i < mListeners.size(); i++) { - mListeners.get(i).onItemsChanged(animate); - } - } - - public interface FolderListener { - void onAdd(ItemInfo item, int rank); - void onRemove(List<ItemInfo> item); - void onItemsChanged(boolean animate); - void onTitleChanged(CharSequence title); - - } - public boolean hasOption(int optionFlag) { return (options & optionFlag) != 0; } @@ -261,7 +179,6 @@ public class FolderInfo extends CollectionInfo { .build(); } - @Override public void setTitle(@Nullable CharSequence title, ModelWriter modelWriter) { // Updating label from null to empty is considered as false touch. // Retaining null title(ie., UNLABELED state) allows auto-labeling when new items added. @@ -289,10 +206,6 @@ public class FolderInfo extends CollectionInfo { if (modelWriter != null) { modelWriter.updateItemInDatabase(this); } - - for (int i = 0; i < mListeners.size(); i++) { - mListeners.get(i).onTitleChanged(title); - } } /** @@ -401,4 +314,13 @@ public class FolderInfo extends CollectionInfo { } return LauncherAtom.ToState.TO_STATE_UNSPECIFIED; } + + /** + * Checks if {@code itemType} is a type that can be placed in folders. + */ + public static boolean willAcceptItemType(int itemType) { + return itemType == ITEM_TYPE_APPLICATION + || itemType == ITEM_TYPE_DEEP_SHORTCUT + || itemType == ITEM_TYPE_APP_PAIR; + } } diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java index 588e75959e..ad7696cd15 100644 --- a/src/com/android/launcher3/model/data/ItemInfo.java +++ b/src/com/android/launcher3/model/data/ItemInfo.java @@ -61,7 +61,6 @@ import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer; import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer; import com.android.launcher3.logger.LauncherAtom.WallpapersContainer; import com.android.launcher3.logger.LauncherAtomExtensions.ExtendedContainers; -import com.android.launcher3.model.ModelWriter; import com.android.launcher3.pm.UserCache; import com.android.launcher3.util.ComponentKey; import com.android.launcher3.util.ContentWriter; @@ -536,14 +535,6 @@ public class ItemInfo { } /** - * Sets the title of the item and writes to DB model if needed. - */ - public void setTitle(@Nullable final CharSequence title, - @Nullable final ModelWriter modelWriter) { - this.title = title; - } - - /** * Returns a string ID that is stable for a user session, but may not be persisted */ @Nullable diff --git a/src/com/android/launcher3/popup/PopupDataProvider.java b/src/com/android/launcher3/popup/PopupDataProvider.java index 5c1a7553a5..95110329d3 100644 --- a/src/com/android/launcher3/popup/PopupDataProvider.java +++ b/src/com/android/launcher3/popup/PopupDataProvider.java @@ -26,7 +26,6 @@ import androidx.annotation.Nullable; import com.android.launcher3.BubbleTextView; import com.android.launcher3.allapps.ActivityAllAppsContainerView; import com.android.launcher3.dot.DotInfo; -import com.android.launcher3.dot.FolderDotInfo; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderIcon; import com.android.launcher3.model.data.FolderInfo; @@ -76,11 +75,7 @@ public class PopupDataProvider implements NotificationListener.NotificationsChan ((BubbleTextView) v).applyDotState(info, true /* animate */); } else if (v instanceof FolderIcon icon && info instanceof FolderInfo fi && fi.anyMatch(matcher)) { - FolderDotInfo folderDotInfo = new FolderDotInfo(); - for (ItemInfo si : fi.getContents()) { - folderDotInfo.addDotInfo(getDotInfoForItem(si)); - } - icon.setDotInfo(folderDotInfo); + icon.updateDotInfo(); } // process all the shortcuts diff --git a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.kt b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.kt index 2e556e8d79..3405cae355 100644 --- a/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.kt +++ b/tests/multivalentTests/src/com/android/launcher3/celllayout/board/TestWorkspaceBuilder.kt @@ -44,7 +44,7 @@ class TestWorkspaceBuilder(private val mContext: Context) { private fun fillWithWidgets( widgetRect: WidgetRect, transaction: FavoriteItemsTransaction, - screenId: Int + screenId: Int, ): FavoriteItemsTransaction { val initX = widgetRect.cellX val initY = widgetRect.cellY @@ -76,7 +76,7 @@ class TestWorkspaceBuilder(private val mContext: Context) { appComponentName = ComponentName( InstrumentationRegistry.getInstrumentation().context.packageName, - TEST_ACTIVITY_PACKAGE_PREFIX + testAppName + TEST_ACTIVITY_PACKAGE_PREFIX + testAppName, ) } @@ -92,7 +92,7 @@ class TestWorkspaceBuilder(private val mContext: Context) { private fun addCorrespondingWidgetRect( widgetRect: WidgetRect, transaction: FavoriteItemsTransaction, - screenId: Int + screenId: Int, ) { if (widgetRect.type == 'x') { fillWithWidgets(widgetRect, transaction, screenId) @@ -105,7 +105,7 @@ class TestWorkspaceBuilder(private val mContext: Context) { fun buildFromBoard( board: CellLayoutBoard, transaction: FavoriteItemsTransaction, - screenId: Int + screenId: Int, ): FavoriteItemsTransaction { board.widgets.forEach { addCorrespondingWidgetRect(it, transaction, screenId) } board.icons.forEach { transaction.addItem { createIconInCell(it, screenId) } } @@ -130,7 +130,7 @@ class TestWorkspaceBuilder(private val mContext: Context) { WidgetUtils.createWidgetInfo( TestViewHelpers.findWidgetProvider(false), ApplicationProvider.getApplicationContext(), - true + true, ) .apply { cellX = widgetRect.cellX @@ -154,7 +154,7 @@ class TestWorkspaceBuilder(private val mContext: Context) { minSpanY = 1 setOption(FolderInfo.FLAG_MULTI_PAGE_ANIMATION, true, null) for (i in 0 until folderPoint.numberIconsInside) { - add(getDefaultWorkspaceItem(paramScreenId), false) + add(getDefaultWorkspaceItem(paramScreenId)) } } diff --git a/tests/multivalentTests/src/com/android/launcher3/folder/FolderTest.kt b/tests/multivalentTests/src/com/android/launcher3/folder/FolderTest.kt index bcf5f0d817..e8259956fb 100644 --- a/tests/multivalentTests/src/com/android/launcher3/folder/FolderTest.kt +++ b/tests/multivalentTests/src/com/android/launcher3/folder/FolderTest.kt @@ -298,12 +298,13 @@ class FolderTest { val dragObject = DragObject(context) dragObject.dragInfo = Mockito.mock(ItemInfo::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) + folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) dragObject.dragSource = folder folder.onDragStart(dragObject, DragOptions()) verify(folder.mContent, times(1)).removeItem(folder.currentDragView) - verify(folder.mInfo, times(1)).remove(dragObject.dragInfo, true) + verify(folder, times(1)).removeFolderContent(true, dragObject.dragInfo) assertTrue(folder.itemsInvalidated) assertTrue(folder.isDragInProgress) assertFalse(folder.itemAddedBackToSelfViaIcon) @@ -827,19 +828,19 @@ class FolderTest { @Test fun `onRemove should call removeItem with the correct views`() { + val folderInfo = + workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) + val items = folderInfo.getContents().toTypedArray() + folder.mInfo = folderInfo + folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) - val items = - arrayListOf<ItemInfo>( - Mockito.mock(ItemInfo::class.java), - Mockito.mock(ItemInfo::class.java), - ) val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) doReturn(view2).whenever(folder).getViewForInfo(items[1]) doReturn(2).whenever(folder).itemCount - folder.onRemove(items) + folder.removeFolderContent(false, *items) verify(folder.mContent, times(1)).removeItem(view1) verify(folder.mContent, times(1)).removeItem(view2) @@ -847,20 +848,20 @@ class FolderTest { @Test fun `onRemove should set mRearrangeOnClose to true and not call rearrangeChildren if animating`() { + val folderInfo = + workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) + val items = folderInfo.getContents().toTypedArray() + folder.mInfo = folderInfo + folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.state = STATE_ANIMATING - val items = - arrayListOf<ItemInfo>( - Mockito.mock(ItemInfo::class.java), - Mockito.mock(ItemInfo::class.java), - ) val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) doReturn(view2).whenever(folder).getViewForInfo(items[1]) doReturn(2).whenever(folder).itemCount - folder.onRemove(items) + folder.removeFolderContent(true, *items) assertTrue(folder.rearrangeOnClose) verify(folder, times(0)).rearrangeChildren() @@ -868,21 +869,21 @@ class FolderTest { @Test fun `onRemove should set not change mRearrangeOnClose and not call rearrangeChildren if not animating`() { + val folderInfo = + workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) + val items = folderInfo.getContents().toTypedArray() + folder.mInfo = folderInfo + folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) folder.state = STATE_CLOSED folder.rearrangeOnClose = false - val items = - arrayListOf<ItemInfo>( - Mockito.mock(ItemInfo::class.java), - Mockito.mock(ItemInfo::class.java), - ) val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) doReturn(view2).whenever(folder).getViewForInfo(items[1]) doReturn(2).whenever(folder).itemCount - folder.onRemove(items) + folder.removeFolderContent(false, *items) assertFalse(folder.rearrangeOnClose) verify(folder, times(1)).rearrangeChildren() @@ -890,12 +891,12 @@ class FolderTest { @Test fun `onRemove should call close if mIsOpen is true and item count is less than or equal to one`() { + val folderInfo = + workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) + val items = folderInfo.getContents().toTypedArray() + folder.mInfo = folderInfo + folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) - val items = - arrayListOf<ItemInfo>( - Mockito.mock(ItemInfo::class.java), - Mockito.mock(ItemInfo::class.java), - ) val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) @@ -904,19 +905,19 @@ class FolderTest { folder.setIsOpen(true) doNothing().`when`(folder).close(true) - folder.onRemove(items) + folder.removeFolderContent(false, *items) verify(folder, times(1)).close(true) } @Test fun `onRemove should call replaceFolderWithFinalItem if mIsOpen is false and item count is less than or equal to one`() { + val folderInfo = + workspaceBuilder.createFolderInCell(FolderPoint(Point(1, 0), TWO_ICON_FOLDER_TYPE), 0) + val items = folderInfo.getContents().toTypedArray() + folder.mInfo = folderInfo + folder.mFolderIcon = Mockito.mock(FolderIcon::class.java) folder.mContent = Mockito.mock(FolderPagedView::class.java) - val items = - arrayListOf<ItemInfo>( - Mockito.mock(ItemInfo::class.java), - Mockito.mock(ItemInfo::class.java), - ) val view1 = Mockito.mock(View::class.java) val view2 = Mockito.mock(View::class.java) doReturn(view1).whenever(folder).getViewForInfo(items[0]) @@ -924,7 +925,7 @@ class FolderTest { doReturn(1).whenever(folder).itemCount folder.setIsOpen(false) - folder.onRemove(items) + folder.removeFolderContent(false, *items) verify(folder, times(1)).replaceFolderWithFinalItem() } |