diff --git a/res/values/attrs.xml b/res/values/attrs.xml index 20e708982a..8d84c90f40 100644 --- a/res/values/attrs.xml +++ b/res/values/attrs.xml @@ -164,7 +164,19 @@ + + + + + + + + + + + + diff --git a/src/com/android/launcher3/DeviceProfile.java b/src/com/android/launcher3/DeviceProfile.java index 8aa8c1e267..b6e8ec3628 100644 --- a/src/com/android/launcher3/DeviceProfile.java +++ b/src/com/android/launcher3/DeviceProfile.java @@ -182,6 +182,8 @@ public class DeviceProfile { public int cellYPaddingPx = -1; // Folder + public final int numFolderRows; + public final int numFolderColumns; public final float folderLabelTextScale; public int folderLabelTextSizePx; public int folderFooterHeightPx; @@ -439,6 +441,8 @@ public class DeviceProfile { } folderLabelTextScale = res.getFloat(R.dimen.folder_label_text_scale); + numFolderRows = inv.numFolderRows[mTypeIndex]; + numFolderColumns = inv.numFolderColumns[mTypeIndex]; if (mIsScalableGrid && inv.folderStyle != INVALID_RESOURCE_HANDLE) { TypedArray folderStyle = context.obtainStyledAttributes(inv.folderStyle, @@ -645,11 +649,11 @@ public class DeviceProfile { isTwoPanels ? inv.folderSpecsTwoPanelId : inv.folderSpecsId), ResponsiveSpecType.Folder); mResponsiveFolderWidthSpec = folderSpecs.getCalculatedSpec(responsiveAspectRatio, - DimensionType.WIDTH, inv.numFolderColumns, + DimensionType.WIDTH, numFolderColumns, mResponsiveWorkspaceWidthSpec.getAvailableSpace(), mResponsiveWorkspaceWidthSpec); mResponsiveFolderHeightSpec = folderSpecs.getCalculatedSpec(responsiveAspectRatio, - DimensionType.HEIGHT, inv.numFolderRows, + DimensionType.HEIGHT, numFolderRows, mResponsiveWorkspaceHeightSpec.getAvailableSpace(), mResponsiveWorkspaceHeightSpec); @@ -1406,16 +1410,16 @@ public class DeviceProfile { Point totalWorkspacePadding = getTotalWorkspacePadding(); // Check if the folder fit within the available height. - float contentUsedHeight = folderCellHeightPx * inv.numFolderRows - + ((inv.numFolderRows - 1) * folderCellLayoutBorderSpacePx.y) + float contentUsedHeight = folderCellHeightPx * numFolderRows + + ((numFolderRows - 1) * folderCellLayoutBorderSpacePx.y) + folderFooterHeightPx + folderContentPaddingTop; int contentMaxHeight = availableHeightPx - totalWorkspacePadding.y; float scaleY = contentMaxHeight / contentUsedHeight; // Check if the folder fit within the available width. - float contentUsedWidth = folderCellWidthPx * inv.numFolderColumns - + ((inv.numFolderColumns - 1) * folderCellLayoutBorderSpacePx.x) + float contentUsedWidth = folderCellWidthPx * numFolderColumns + + ((numFolderColumns - 1) * folderCellLayoutBorderSpacePx.x) + folderContentPaddingLeftRight * 2; int contentMaxWidth = availableWidthPx - totalWorkspacePadding.x; float scaleX = contentMaxWidth / contentUsedWidth; @@ -2045,8 +2049,8 @@ public class DeviceProfile { writer.println(prefix + pxToDpStr("iconTextSizePx", iconTextSizePx)); writer.println(prefix + pxToDpStr("iconDrawablePaddingPx", iconDrawablePaddingPx)); - writer.println(prefix + "\tinv.numFolderRows: " + inv.numFolderRows); - writer.println(prefix + "\tinv.numFolderColumns: " + inv.numFolderColumns); + writer.println(prefix + "\tnumFolderRows: " + numFolderRows); + writer.println(prefix + "\tnumFolderColumns: " + numFolderColumns); writer.println(prefix + pxToDpStr("folderCellWidthPx", folderCellWidthPx)); writer.println(prefix + pxToDpStr("folderCellHeightPx", folderCellHeightPx)); writer.println(prefix + pxToDpStr("folderChildIconSizePx", folderChildIconSizePx)); diff --git a/src/com/android/launcher3/InvariantDeviceProfile.java b/src/com/android/launcher3/InvariantDeviceProfile.java index 567d0c503f..dfbbcaabb4 100644 --- a/src/com/android/launcher3/InvariantDeviceProfile.java +++ b/src/com/android/launcher3/InvariantDeviceProfile.java @@ -122,8 +122,8 @@ public class InvariantDeviceProfile { /** * Number of icons per row and column in the folder. */ - public int numFolderRows; - public int numFolderColumns; + public int[] numFolderRows; + public int[] numFolderColumns; public float[] iconSize; public float[] iconTextSize; public int iconBitmapSize; @@ -810,8 +810,8 @@ public class InvariantDeviceProfile { public final int numSearchContainerColumns; public final int deviceCategory; - private final int numFolderRows; - private final int numFolderColumns; + private final int[] numFolderRows = new int[COUNT_SIZES]; + private final int[] numFolderColumns = new int[COUNT_SIZES]; private final @StyleRes int folderStyle; private final @StyleRes int cellStyle; @@ -888,11 +888,39 @@ public class InvariantDeviceProfile { a.getResourceId(R.styleable.GridDisplayOption_inlineNavButtonsEndSpacing, R.dimen.taskbar_button_margin_default); - numFolderRows = a.getInt( + numFolderRows[INDEX_DEFAULT] = a.getInt( R.styleable.GridDisplayOption_numFolderRows, numRows); - numFolderColumns = a.getInt( + numFolderColumns[INDEX_DEFAULT] = a.getInt( R.styleable.GridDisplayOption_numFolderColumns, numColumns); + if (FeatureFlags.enableResponsiveWorkspace()) { + numFolderRows[INDEX_LANDSCAPE] = a.getInt( + R.styleable.GridDisplayOption_numFolderRowsLandscape, + numFolderRows[INDEX_DEFAULT]); + numFolderColumns[INDEX_LANDSCAPE] = a.getInt( + R.styleable.GridDisplayOption_numFolderColumnsLandscape, + numFolderColumns[INDEX_DEFAULT]); + numFolderRows[INDEX_TWO_PANEL_PORTRAIT] = a.getInt( + R.styleable.GridDisplayOption_numFolderRowsTwoPanelPortrait, + numFolderRows[INDEX_DEFAULT]); + numFolderColumns[INDEX_TWO_PANEL_PORTRAIT] = a.getInt( + R.styleable.GridDisplayOption_numFolderColumnsTwoPanelPortrait, + numFolderColumns[INDEX_DEFAULT]); + numFolderRows[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt( + R.styleable.GridDisplayOption_numFolderRowsTwoPanelLandscape, + numFolderRows[INDEX_DEFAULT]); + numFolderColumns[INDEX_TWO_PANEL_LANDSCAPE] = a.getInt( + R.styleable.GridDisplayOption_numFolderColumnsTwoPanelLandscape, + numFolderColumns[INDEX_DEFAULT]); + } else { + numFolderRows[INDEX_LANDSCAPE] = numFolderRows[INDEX_DEFAULT]; + numFolderColumns[INDEX_LANDSCAPE] = numFolderColumns[INDEX_DEFAULT]; + numFolderRows[INDEX_TWO_PANEL_PORTRAIT] = numFolderRows[INDEX_DEFAULT]; + numFolderColumns[INDEX_TWO_PANEL_PORTRAIT] = numFolderColumns[INDEX_DEFAULT]; + numFolderRows[INDEX_TWO_PANEL_LANDSCAPE] = numFolderRows[INDEX_DEFAULT]; + numFolderColumns[INDEX_TWO_PANEL_LANDSCAPE] = numFolderColumns[INDEX_DEFAULT]; + } + folderStyle = a.getResourceId(R.styleable.GridDisplayOption_folderStyle, INVALID_RESOURCE_HANDLE); diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index e301bdb202..acb6c053b1 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -791,7 +791,7 @@ public class Launcher extends StatefulActivity if (info.container >= 0) { View folderIcon = getWorkspace().getHomescreenIconByItemId(info.container); if (folderIcon instanceof FolderIcon && folderIcon.getTag() instanceof FolderInfo) { - if (new FolderGridOrganizer(getDeviceProfile().inv) + if (new FolderGridOrganizer(getDeviceProfile()) .setFolderInfo((FolderInfo) folderIcon.getTag()) .isItemInPreview(info.rank)) { folderIcon.invalidate(); diff --git a/src/com/android/launcher3/ModelCallbacks.kt b/src/com/android/launcher3/ModelCallbacks.kt index c05158b2f9..f37a1ecea1 100644 --- a/src/com/android/launcher3/ModelCallbacks.kt +++ b/src/com/android/launcher3/ModelCallbacks.kt @@ -88,7 +88,7 @@ class ModelCallbacks(private var launcher: Launcher) : BgDataModel.Callbacks { // Cache one page worth of icons launcher.viewCache.setCacheSize( R.layout.folder_application, - deviceProfile.inv.numFolderColumns * deviceProfile.inv.numFolderRows + deviceProfile.numFolderColumns * deviceProfile.numFolderRows ) launcher.viewCache.setCacheSize(R.layout.folder_page, 2) TraceHelper.INSTANCE.endSection() diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 8bf7ec234e..e7a559ea09 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -1082,7 +1082,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo private void updateItemLocationsInDatabaseBatch(boolean isBind) { FolderGridOrganizer verifier = new FolderGridOrganizer( - mActivityContext.getDeviceProfile().inv).setFolderInfo(mInfo); + mActivityContext.getDeviceProfile()).setFolderInfo(mInfo); ArrayList items = new ArrayList<>(); int total = mInfo.contents.size(); @@ -1381,7 +1381,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo @Override public void onAdd(WorkspaceItemInfo item, int rank) { FolderGridOrganizer verifier = new FolderGridOrganizer( - mActivityContext.getDeviceProfile().inv).setFolderInfo(mInfo); + mActivityContext.getDeviceProfile()).setFolderInfo(mInfo); verifier.updateRankAndPos(item, rank); mLauncherDelegate.getModelWriter().addOrMoveItemInDatabase(item, mInfo.id, 0, item.cellX, item.cellY); diff --git a/src/com/android/launcher3/folder/FolderAnimationManager.java b/src/com/android/launcher3/folder/FolderAnimationManager.java index 9e2e2bf5fc..a91373ba49 100644 --- a/src/com/android/launcher3/folder/FolderAnimationManager.java +++ b/src/com/android/launcher3/folder/FolderAnimationManager.java @@ -96,7 +96,7 @@ public class FolderAnimationManager { mContext = folder.getContext(); mDeviceProfile = folder.mActivityContext.getDeviceProfile(); - mPreviewVerifier = new FolderGridOrganizer(mDeviceProfile.inv); + mPreviewVerifier = new FolderGridOrganizer(mDeviceProfile); mIsOpening = isOpening; diff --git a/src/com/android/launcher3/folder/FolderGridOrganizer.java b/src/com/android/launcher3/folder/FolderGridOrganizer.java index 4be82ed8d3..cc247619e4 100644 --- a/src/com/android/launcher3/folder/FolderGridOrganizer.java +++ b/src/com/android/launcher3/folder/FolderGridOrganizer.java @@ -20,7 +20,7 @@ import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_I import android.graphics.Point; -import com.android.launcher3.InvariantDeviceProfile; +import com.android.launcher3.DeviceProfile; import com.android.launcher3.model.data.FolderInfo; import com.android.launcher3.model.data.ItemInfo; @@ -41,11 +41,13 @@ public class FolderGridOrganizer { private int mCountX; private int mCountY; private boolean mDisplayingUpperLeftQuadrant = false; + private static final int PREVIEW_MAX_ROWS = 2; + private static final int PREVIEW_MAX_COLUMNS = 2; /** * Note: must call {@link #setFolderInfo(FolderInfo)} manually for verifier to work. */ - public FolderGridOrganizer(InvariantDeviceProfile profile) { + public FolderGridOrganizer(DeviceProfile profile) { mMaxCountX = profile.numFolderColumns; mMaxCountY = profile.numFolderRows; mMaxItemsPerPage = mMaxCountX * mMaxCountY; @@ -127,6 +129,7 @@ public class FolderGridOrganizer { /** * Updates the item's cellX, cellY and rank corresponding to the provided rank. + * * @return true if there was any change */ public boolean updateRankAndPos(ItemInfo item, int rank) { @@ -189,7 +192,7 @@ public class FolderGridOrganizer { if (page > 0 || mDisplayingUpperLeftQuadrant) { int col = rank % mCountX; int row = rank / mCountX; - return col < 2 && row < 2; + return col < PREVIEW_MAX_COLUMNS && row < PREVIEW_MAX_ROWS; } return rank < MAX_NUM_ITEMS_IN_PREVIEW; } diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index cb1dc4fb2a..c80fb8cb98 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -221,7 +221,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel icon.setAccessibilityDelegate(activity.getAccessibilityDelegate()); - icon.mPreviewVerifier = new FolderGridOrganizer(activity.getDeviceProfile().inv); + icon.mPreviewVerifier = new FolderGridOrganizer(activity.getDeviceProfile()); icon.mPreviewVerifier.setFolderInfo(folderInfo); icon.updatePreviewItems(false); diff --git a/src/com/android/launcher3/folder/FolderPagedView.java b/src/com/android/launcher3/folder/FolderPagedView.java index 36e5e1b106..f2bed925c1 100644 --- a/src/com/android/launcher3/folder/FolderPagedView.java +++ b/src/com/android/launcher3/folder/FolderPagedView.java @@ -37,8 +37,6 @@ import com.android.launcher3.AbstractFloatingView; import com.android.launcher3.BubbleTextView; import com.android.launcher3.CellLayout; import com.android.launcher3.DeviceProfile; -import com.android.launcher3.InvariantDeviceProfile; -import com.android.launcher3.LauncherAppState; import com.android.launcher3.PagedView; import com.android.launcher3.R; import com.android.launcher3.ShortcutAndWidgetContainer; @@ -101,14 +99,15 @@ public class FolderPagedView extends PagedView implements Cli public FolderPagedView(Context context, AttributeSet attrs) { super(context, attrs); - InvariantDeviceProfile profile = LauncherAppState.getIDP(context); + ActivityContext activityContext = ActivityContext.lookupContext(context); + DeviceProfile profile = activityContext.getDeviceProfile(); mOrganizer = new FolderGridOrganizer(profile); mIsRtl = Utilities.isRtl(getResources()); setImportantForAccessibility(IMPORTANT_FOR_ACCESSIBILITY_YES); mFocusIndicatorHelper = new ViewGroupFocusHelper(this); - mViewCache = ActivityContext.lookupContext(context).getViewCache(); + mViewCache = activityContext.getViewCache(); } public void setFolder(Folder folder) { diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index f4ce3607f7..6ea3e8ae5e 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -481,16 +481,17 @@ public class LoaderTask implements Runnable { mItemsDeleted = c.commitDeleted(); // Sort the folder items, update ranks, and make sure all preview items are high res. - FolderGridOrganizer verifier = - new FolderGridOrganizer(mApp.getInvariantDeviceProfile()); + List verifiers = + mApp.getInvariantDeviceProfile().supportedProfiles.stream().map( + FolderGridOrganizer::new).toList(); for (FolderInfo folder : mBgDataModel.folders) { Collections.sort(folder.contents, Folder.ITEM_POS_COMPARATOR); - verifier.setFolderInfo(folder); + verifiers.forEach(verifier -> verifier.setFolderInfo(folder)); int size = folder.contents.size(); // Update ranks here to ensure there are no gaps caused by removed folder items. - // Ranks are the source of truth for folder items, so cellX and cellY can be ignored - // for now. Database will be updated once user manually modifies folder. + // Ranks are the source of truth for folder items, so cellX and cellY can be + // ignored for now. Database will be updated once user manually modifies folder. for (int rank = 0; rank < size; ++rank) { WorkspaceItemInfo info = folder.contents.get(rank); // rank is used differently in app pairs, so don't reset @@ -498,9 +499,9 @@ public class LoaderTask implements Runnable { info.rank = rank; } - if (info.usingLowResIcon() - && info.itemType == Favorites.ITEM_TYPE_APPLICATION - && verifier.isItemInPreview(info.rank)) { + if (info.usingLowResIcon() && info.itemType == Favorites.ITEM_TYPE_APPLICATION + && verifiers.stream().anyMatch( + verifier -> verifier.isItemInPreview(info.rank))) { mIconCache.getTitleAndIcon(info, false); } } diff --git a/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt b/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt index a42100626a..30b5663a1e 100644 --- a/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt +++ b/tests/src/com/android/launcher3/FakeInvariantDeviceProfileTest.kt @@ -121,8 +121,8 @@ abstract class FakeInvariantDeviceProfileTest { listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 16f)) .toTypedArray() - numFolderRows = 3 - numFolderColumns = 3 + numFolderRows = intArrayOf(3, 3, 3, 3) + numFolderColumns = intArrayOf(3, 3, 3, 3) folderStyle = R.style.FolderStyleDefault inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split @@ -204,8 +204,8 @@ abstract class FakeInvariantDeviceProfileTest { listOf(PointF(16f, 64f), PointF(64f, 16f), PointF(16f, 64f), PointF(16f, 64f)) .toTypedArray() - numFolderRows = 3 - numFolderColumns = 3 + numFolderRows = intArrayOf(3, 3, 3, 3) + numFolderColumns = intArrayOf(3, 3, 3, 3) folderStyle = R.style.FolderStyleDefault inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_6_5 @@ -288,8 +288,8 @@ abstract class FakeInvariantDeviceProfileTest { listOf(PointF(16f, 16f), PointF(16f, 16f), PointF(16f, 20f), PointF(20f, 20f)) .toTypedArray() - numFolderRows = 3 - numFolderColumns = 3 + numFolderRows = intArrayOf(3, 3, 3, 3) + numFolderColumns = intArrayOf(3, 3, 3, 3) folderStyle = R.style.FolderStyleDefault inlineNavButtonsEndSpacing = R.dimen.taskbar_button_margin_split diff --git a/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt b/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt index 21bd90053d..60a4d2d667 100644 --- a/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt +++ b/tests/src/com/android/launcher3/model/FolderIconLoadTest.kt @@ -24,9 +24,10 @@ import com.android.launcher3.util.LauncherLayoutBuilder import com.android.launcher3.util.LauncherModelHelper import com.android.launcher3.util.LauncherModelHelper.* import com.android.launcher3.util.TestUtil +import com.google.common.truth.Truth.assertThat +import com.google.common.truth.Truth.assertWithMessage import java.util.concurrent.CountDownLatch import org.junit.After -import org.junit.Assert import org.junit.Before import org.junit.Test import org.junit.runner.RunWith @@ -71,7 +72,7 @@ class FolderIconLoadTest { @Throws(Exception::class) fun folderLoadedWithHighRes_2x2() { val items = setupAndLoadFolder(4) - Assert.assertEquals(4, items.size.toLong()) + assertThat(items.size).isEqualTo(4) verifyHighRes(items, 0, 1, 2, 3) } @@ -79,7 +80,7 @@ class FolderIconLoadTest { @Throws(Exception::class) fun folderLoadedWithHighRes_3x2() { val items = setupAndLoadFolder(6) - Assert.assertEquals(6, items.size.toLong()) + assertThat(items.size).isEqualTo(6) verifyHighRes(items, 0, 1, 3, 4) verifyLowRes(items, 2, 5) } @@ -88,8 +89,10 @@ class FolderIconLoadTest { @Throws(Exception::class) fun folderLoadedWithHighRes_max_3x3() { val idp = LauncherAppState.getIDP(modelHelper.sandboxContext) - idp.numFolderColumns = 3 - idp.numFolderRows = 3 + idp.numFolderColumns = intArrayOf(3, 3, 3, 3) + idp.numFolderRows = intArrayOf(3, 3, 3, 3) + recreateSupportedDeviceProfiles() + val items = setupAndLoadFolder(14) verifyHighRes(items, 0, 1, 3, 4) verifyLowRes(items, 2, 5, 6, 7, 8, 9, 10, 11, 12, 13) @@ -99,13 +102,28 @@ class FolderIconLoadTest { @Throws(Exception::class) fun folderLoadedWithHighRes_max_4x4() { val idp = LauncherAppState.getIDP(modelHelper.sandboxContext) - idp.numFolderColumns = 4 - idp.numFolderRows = 4 + idp.numFolderColumns = intArrayOf(4, 4, 4, 4) + idp.numFolderRows = intArrayOf(4, 4, 4, 4) + recreateSupportedDeviceProfiles() + val items = setupAndLoadFolder(14) verifyHighRes(items, 0, 1, 4, 5) verifyLowRes(items, 2, 3, 6, 7, 8, 9, 10, 11, 12, 13) } + @Test + @Throws(Exception::class) + fun folderLoadedWithHighRes_differentFolderConfigurations() { + val idp = LauncherAppState.getIDP(modelHelper.sandboxContext) + idp.numFolderColumns = intArrayOf(4, 3, 4, 4) + idp.numFolderRows = intArrayOf(4, 3, 4, 4) + recreateSupportedDeviceProfiles() + + val items = setupAndLoadFolder(14) + verifyHighRes(items, 0, 1, 3, 4, 5) + verifyLowRes(items, 2, 6, 7, 8, 9, 10, 11, 12, 13) + } + @Throws(Exception::class) private fun setupAndLoadFolder(itemCount: Int): ArrayList { val builder = @@ -113,9 +131,7 @@ class FolderIconLoadTest { .atWorkspace(0, 0, 1) .putFolder("Sample") .apply { - for (i in 0..itemCount - 1) { - this.addApp(TEST_PACKAGE, uniqueActivities[i]) - } + for (i in 0..itemCount - 1) this.addApp(TEST_PACKAGE, uniqueActivities[i]) } .build() @@ -136,20 +152,33 @@ class FolderIconLoadTest { app.model.forceReload() modelHelper.loadModelSync() val folders = modelHelper.getBgDataModel().folders - Assert.assertEquals(1, folders.size()) - Assert.assertEquals(itemCount, folders.valueAt(0).contents.size) + + assertThat(folders.size()).isEqualTo(1) + assertThat(folders.valueAt(0).contents.size).isEqualTo(itemCount) return folders.valueAt(0).contents } private fun verifyHighRes(items: ArrayList, vararg indices: Int) { for (index in indices) { - Assert.assertFalse("Index $index was not highRes", items[index].bitmap.isNullOrLowRes) + assertWithMessage("Index $index was not highRes") + .that(items[index].bitmap.isNullOrLowRes) + .isFalse() } } private fun verifyLowRes(items: ArrayList, vararg indices: Int) { for (index in indices) { - Assert.assertTrue("Index $index was not lowRes", items[index].bitmap.isNullOrLowRes) + assertWithMessage("Index $index was not lowRes") + .that(items[index].bitmap.isNullOrLowRes) + .isTrue() } } + + /** Recreate DeviceProfiles after changing InvariantDeviceProfile */ + private fun recreateSupportedDeviceProfiles() { + LauncherAppState.getIDP(modelHelper.sandboxContext).supportedProfiles = + LauncherAppState.getIDP(modelHelper.sandboxContext).supportedProfiles.map { + it.copy(modelHelper.sandboxContext) + } + } }