diff --git a/res/values/config.xml b/res/values/config.xml index 0dfed97ce3..09456425c1 100644 --- a/res/values/config.xml +++ b/res/values/config.xml @@ -63,6 +63,7 @@ + diff --git a/src/com/android/launcher3/DropTarget.java b/src/com/android/launcher3/DropTarget.java index 763432df8f..a32fd1239f 100644 --- a/src/com/android/launcher3/DropTarget.java +++ b/src/com/android/launcher3/DropTarget.java @@ -16,11 +16,14 @@ package com.android.launcher3; +import android.content.Context; import android.graphics.Rect; import com.android.launcher3.accessibility.DragViewStateAnnouncer; +import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.dragndrop.DragOptions; import com.android.launcher3.dragndrop.DragView; +import com.android.launcher3.folder.FolderNameProvider; /** * Interface defining an object that can receive a drag. @@ -67,7 +70,12 @@ public interface DropTarget { public DragViewStateAnnouncer stateAnnouncer; - public DragObject() { + public FolderNameProvider folderNameProvider; + + public DragObject(Context context) { + if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { + folderNameProvider = FolderNameProvider.newInstance(context); + } } /** diff --git a/src/com/android/launcher3/FolderInfo.java b/src/com/android/launcher3/FolderInfo.java index 0fea0dcc63..787eee1483 100644 --- a/src/com/android/launcher3/FolderInfo.java +++ b/src/com/android/launcher3/FolderInfo.java @@ -16,6 +16,7 @@ package com.android.launcher3; +import android.content.Intent; import android.os.Process; import com.android.launcher3.model.ModelWriter; @@ -49,6 +50,8 @@ public class FolderInfo extends ItemInfo { public int options; + public Intent suggestedFolderNames; + /** * The apps and shortcuts */ diff --git a/src/com/android/launcher3/Launcher.java b/src/com/android/launcher3/Launcher.java index 2ccdd6f4a9..fe987bcb0f 100644 --- a/src/com/android/launcher3/Launcher.java +++ b/src/com/android/launcher3/Launcher.java @@ -103,7 +103,6 @@ import com.android.launcher3.dragndrop.DragLayer; import com.android.launcher3.dragndrop.DragView; import com.android.launcher3.folder.FolderGridOrganizer; import com.android.launcher3.folder.FolderIcon; -import com.android.launcher3.folder.FolderNameProvider; import com.android.launcher3.graphics.RotationMode; import com.android.launcher3.icons.IconCache; import com.android.launcher3.keyboard.CustomActionsPopup; @@ -616,10 +615,6 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, return mStateManager; } - public FolderNameProvider getFolderNameProvider() { - return new FolderNameProvider(); - } - @Override public T findViewById(int id) { return mLauncherView.findViewById(id); @@ -1259,13 +1254,13 @@ public class Launcher extends BaseDraggingActivity implements LauncherExterns, cellXY[1] = cellY; foundCellSpan = true; + DragObject dragObject = new DragObject(getApplicationContext()); + dragObject.dragInfo = info; // If appropriate, either create a folder or add to an existing folder if (mWorkspace.createUserFolderIfNecessary(view, container, layout, cellXY, 0, - true, null)) { + true, dragObject)) { return; } - DragObject dragObject = new DragObject(); - dragObject.dragInfo = info; if (mWorkspace.addToExistingFolderIfNecessary(view, layout, cellXY, 0, dragObject, true)) { return; diff --git a/src/com/android/launcher3/Workspace.java b/src/com/android/launcher3/Workspace.java index 670363efe2..beaafda301 100644 --- a/src/com/android/launcher3/Workspace.java +++ b/src/com/android/launcher3/Workspace.java @@ -1673,7 +1673,7 @@ public class Workspace extends PagedView } boolean createUserFolderIfNecessary(View newView, int container, CellLayout target, - int[] targetCell, float distance, boolean external, DragView dragView) { + int[] targetCell, float distance, boolean external, DragObject d) { if (distance > mMaxDistanceForFolderCreation) return false; View v = target.getChildAt(targetCell[0], targetCell[1]); @@ -1711,14 +1711,13 @@ public class Workspace extends PagedView sourceInfo.cellY = -1; // If the dragView is null, we can't animate - boolean animate = dragView != null; + boolean animate = d != null; if (animate) { // In order to keep everything continuous, we hand off the currently rendered // folder background to the newly created icon. This preserves animation state. fi.setFolderBackground(mFolderCreateBg); mFolderCreateBg = new PreviewBackground(); - fi.performCreateAnimation(destInfo, v, sourceInfo, dragView, folderLocation, scale - ); + fi.performCreateAnimation(destInfo, v, sourceInfo, d, folderLocation, scale); } else { fi.prepareCreateAnimation(v); fi.addItem(destInfo); @@ -1799,8 +1798,8 @@ public class Workspace extends PagedView // If the item being dropped is a shortcut and the nearest drop // cell also contains a shortcut, then create a folder with the two shortcuts. if (createUserFolderIfNecessary(cell, container, - dropTargetLayout, mTargetCell, distance, false, d.dragView) || - addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell, + dropTargetLayout, mTargetCell, distance, false, d) + || addToExistingFolderIfNecessary(cell, dropTargetLayout, mTargetCell, distance, d, false)) { mLauncher.getStateManager().goToState(NORMAL, SPRING_LOADED_EXIT_DELAY); return; @@ -2561,7 +2560,7 @@ public class Workspace extends PagedView float distance = cellLayout.getDistanceFromCell(mDragViewVisualCenter[0], mDragViewVisualCenter[1], mTargetCell); if (createUserFolderIfNecessary(view, container, cellLayout, mTargetCell, distance, - true, d.dragView)) { + true, d)) { return; } if (addToExistingFolderIfNecessary(view, cellLayout, mTargetCell, distance, d, diff --git a/src/com/android/launcher3/dragndrop/DragController.java b/src/com/android/launcher3/dragndrop/DragController.java index 8adec27541..54a44eed30 100644 --- a/src/com/android/launcher3/dragndrop/DragController.java +++ b/src/com/android/launcher3/dragndrop/DragController.java @@ -28,7 +28,6 @@ import android.graphics.Bitmap; import android.graphics.Point; import android.graphics.Rect; import android.os.IBinder; -import android.util.Log; import android.view.DragEvent; import android.view.HapticFeedbackConstants; import android.view.KeyEvent; @@ -43,7 +42,6 @@ import com.android.launcher3.Launcher; import com.android.launcher3.R; import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.accessibility.DragViewStateAnnouncer; -import com.android.launcher3.testing.TestProtocol; import com.android.launcher3.util.ItemInfoMatcher; import com.android.launcher3.util.Thunk; import com.android.launcher3.util.TouchController; @@ -174,7 +172,7 @@ public class DragController implements DragDriver.EventListener, TouchController mLastDropTarget = null; - mDragObject = new DropTarget.DragObject(); + mDragObject = new DropTarget.DragObject(mLauncher.getApplicationContext()); mIsInPreDrag = mOptions.preDragCondition != null && !mOptions.preDragCondition.shouldStartDrag(0); diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 90d812548a..024c7dd47b 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -26,6 +26,7 @@ import android.animation.AnimatorSet; import android.annotation.SuppressLint; import android.appwidget.AppWidgetHostView; import android.content.Context; +import android.content.Intent; import android.graphics.Canvas; import android.graphics.Path; import android.graphics.Rect; @@ -300,9 +301,8 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo post(() -> { if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { if (TextUtils.isEmpty(mFolderName.getText())) { - final String[] suggestedNames = new String[FolderNameProvider.SUGGEST_MAX]; - mLauncher.getFolderNameProvider().getSuggestedFolderName(getContext(), - mInfo.contents, suggestedNames); + String[] suggestedNames = + mInfo.suggestedFolderNames.getStringArrayExtra("suggest"); mFolderName.setText(suggestedNames[0]); mFolderName.displayCompletions(Arrays.asList(suggestedNames).subList(1, suggestedNames.length)); @@ -446,17 +446,19 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo * Show suggested folder title. */ public void showSuggestedTitle(String[] suggestName) { - if (FeatureFlags.FOLDER_NAME_SUGGEST.get() - && TextUtils.isEmpty(mFolderName.getText().toString()) - && !mInfo.hasOption(FolderInfo.FLAG_MANUAL_FOLDER_NAME)) { - if (suggestName.length > 0 && !TextUtils.isEmpty(suggestName[0])) { - mFolderName.setHint(""); - mFolderName.setText(suggestName[0]); - mInfo.title = suggestName[0]; - animateOpen(mInfo.contents, 0, true); - mFolderName.showKeyboard(); - mFolderName.displayCompletions( - Arrays.asList(suggestName).subList(1, suggestName.length)); + if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { + mInfo.suggestedFolderNames = new Intent().putExtra("suggest", suggestName); + if (TextUtils.isEmpty(mFolderName.getText().toString()) + && !mInfo.hasOption(FolderInfo.FLAG_MANUAL_FOLDER_NAME)) { + if (suggestName.length > 0 && !TextUtils.isEmpty(suggestName[0])) { + mFolderName.setHint(""); + mFolderName.setText(suggestName[0]); + mInfo.title = suggestName[0]; + animateOpen(mInfo.contents, 0, true); + mFolderName.showKeyboard(); + mFolderName.displayCompletions( + Arrays.asList(suggestName).subList(1, suggestName.length)); + } } } } diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java index 8c56823a4a..6a47b98af9 100644 --- a/src/com/android/launcher3/folder/FolderIcon.java +++ b/src/com/android/launcher3/folder/FolderIcon.java @@ -288,8 +288,9 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel } public void performCreateAnimation(final WorkspaceItemInfo destInfo, final View destView, - final WorkspaceItemInfo srcInfo, final DragView srcView, Rect dstRect, + final WorkspaceItemInfo srcInfo, final DragObject d, Rect dstRect, float scaleRelativeToDragLayer) { + final DragView srcView = d.dragView; prepareCreateAnimation(destView); addItem(destInfo); // This will animate the first item from it's position as an icon into its @@ -298,7 +299,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel .start(); // This will animate the dragView (srcView) into the new folder - onDrop(srcInfo, srcView, dstRect, scaleRelativeToDragLayer, 1, + onDrop(srcInfo, d, dstRect, scaleRelativeToDragLayer, 1, false /* itemReturnedOnFailedDrop */); } @@ -313,11 +314,11 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel mOpenAlarm.cancelAlarm(); } - private void onDrop(final WorkspaceItemInfo item, DragView animateView, Rect finalRect, + private void onDrop(final WorkspaceItemInfo item, DragObject d, Rect finalRect, float scaleRelativeToDragLayer, int index, boolean itemReturnedOnFailedDrop) { item.cellX = -1; item.cellY = -1; - + DragView animateView = d.dragView; // Typically, the animateView corresponds to the DragView; however, if this is being done // after a configuration activity (ie. for a Shortcut being dragged from AllApps) we // will not have a view to animate @@ -395,7 +396,7 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel String[] suggestedNameOut = new String[FolderNameProvider.SUGGEST_MAX]; if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { Executors.UI_HELPER_EXECUTOR.post(() -> { - launcher.getFolderNameProvider().getSuggestedFolderName( + d.folderNameProvider.getSuggestedFolderName( getContext(), mInfo.contents, suggestedNameOut); showFinalView(finalIndex, item, suggestedNameOut); }); @@ -429,9 +430,10 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel item = (WorkspaceItemInfo) d.dragInfo; } mFolder.notifyDrop(); - onDrop(item, d.dragView, null, 1.0f, + onDrop(item, d, null, 1.0f, itemReturnedOnFailedDrop ? item.rank : mInfo.contents.size(), - itemReturnedOnFailedDrop); + itemReturnedOnFailedDrop + ); } public void setDotInfo(FolderDotInfo dotInfo) { diff --git a/src/com/android/launcher3/folder/FolderNameEditText.java b/src/com/android/launcher3/folder/FolderNameEditText.java index 7e3f847052..7e11b18e98 100644 --- a/src/com/android/launcher3/folder/FolderNameEditText.java +++ b/src/com/android/launcher3/folder/FolderNameEditText.java @@ -61,6 +61,9 @@ public class FolderNameEditText extends ExtendedEditText { return connectionWrapper; } + /** + * Send strings in @param suggestList to the IME to show up as suggestions. + */ public void displayCompletions(List suggestList) { int cnt = Math.min(suggestList.size(), FolderNameProvider.SUGGEST_MAX); CompletionInfo[] cInfo = new CompletionInfo[cnt]; diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java index 9ea292c6f8..957e6361fe 100644 --- a/src/com/android/launcher3/folder/FolderNameProvider.java +++ b/src/com/android/launcher3/folder/FolderNameProvider.java @@ -24,6 +24,7 @@ import com.android.launcher3.AppInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.WorkspaceItemInfo; +import com.android.launcher3.util.ResourceBasedOverride; import java.util.ArrayList; import java.util.Arrays; @@ -38,10 +39,10 @@ import java.util.stream.Collectors; /** * Locates provider for the folder name. */ -public class FolderNameProvider { +public class FolderNameProvider implements ResourceBasedOverride { private static final String TAG = "FolderNameProvider"; - private static final boolean DEBUG = false; + private static final boolean DEBUG = true; /** * IME usually has up to 3 suggest slots. In total, there are 4 suggest slots as the folder @@ -50,9 +51,14 @@ public class FolderNameProvider { public static final int SUGGEST_MAX = 4; /** - * When inheriting class requires precaching, override this method. + * Retrieve instance of this object that can be overridden in runtime based on the build + * variant of the application. */ - public void load(Context context) {} + public static FolderNameProvider newInstance(Context context) { + FolderNameProvider fnp = Overrides.getObject(FolderNameProvider.class, + context.getApplicationContext(), R.string.folder_name_provider_class); + return fnp; + } public CharSequence getSuggestedFolderName(Context context, ArrayList workspaceItemInfos, CharSequence[] candidates) { diff --git a/src/com/android/launcher3/model/LoaderTask.java b/src/com/android/launcher3/model/LoaderTask.java index 571d41a54b..6faa22f55d 100644 --- a/src/com/android/launcher3/model/LoaderTask.java +++ b/src/com/android/launcher3/model/LoaderTask.java @@ -60,6 +60,7 @@ import com.android.launcher3.WorkspaceItemInfo; import com.android.launcher3.config.FeatureFlags; import com.android.launcher3.folder.Folder; import com.android.launcher3.folder.FolderGridOrganizer; +import com.android.launcher3.folder.FolderNameProvider; import com.android.launcher3.icons.ComponentWithLabel; import com.android.launcher3.icons.ComponentWithLabel.ComponentCachingLogic; import com.android.launcher3.icons.IconCache; @@ -256,6 +257,11 @@ public class LoaderTask implements Runnable { mApp.getContext(), true), mApp.getModel()::onWidgetLabelsUpdated); logger.addSplit("save widgets in icon cache"); + // fifth step + if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { + loadFolderNames(); + } + verifyNotStopped(); updateHandler.finish(); logger.addSplit("finish icon update"); @@ -898,6 +904,21 @@ public class LoaderTask implements Runnable { return allShortcuts; } + private void loadFolderNames() { + FolderNameProvider provider = FolderNameProvider.newInstance(mApp.getContext()); + + synchronized (mBgDataModel) { + for (int i = 0; i < mBgDataModel.folders.size(); i++) { + String[] suggestedOut = new String[FolderNameProvider.SUGGEST_MAX]; + FolderInfo info = mBgDataModel.folders.valueAt(i); + if (info.suggestedFolderNames == null) { + provider.getSuggestedFolderName(mApp.getContext(), info.contents, suggestedOut); + info.suggestedFolderNames = new Intent().putExtra("suggest", suggestedOut); + } + } + } + } + public static boolean isValidProvider(AppWidgetProviderInfo provider) { return (provider != null) && (provider.provider != null) && (provider.provider.getPackageName() != null);