From 54d1f88ae60bafe197f71d92080cf065fba6cb09 Mon Sep 17 00:00:00 2001 From: Hyunyoung Song Date: Fri, 10 Jan 2020 23:37:16 -0800 Subject: [PATCH] Show suggestion when user taps on folder's edit text Also, enabled preloading of the folder name db Bug: 147523650 Bug: 147359653 Change-Id: Ia77e12d2b2bc428263c2b2821a96894a6004d82e --- .../android/launcher3/ExtendedEditText.java | 2 +- src/com/android/launcher3/folder/Folder.java | 44 ++++++++++++++----- .../launcher3/folder/FolderNameProvider.java | 40 ++++++++++++++--- 3 files changed, 68 insertions(+), 18 deletions(-) diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java index 8b6d2091b6..5b453c3a4c 100644 --- a/src/com/android/launcher3/ExtendedEditText.java +++ b/src/com/android/launcher3/ExtendedEditText.java @@ -44,7 +44,7 @@ public class ExtendedEditText extends EditText { * Implemented by listeners of the back key. */ public interface OnBackKeyListener { - public boolean onBackKey(); + boolean onBackKey(); } private OnBackKeyListener mBackKeyListener; diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java index 52d8f7fb40..844189fc70 100644 --- a/src/com/android/launcher3/folder/Folder.java +++ b/src/com/android/launcher3/folder/Folder.java @@ -297,16 +297,22 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo } public void startEditingFolderName() { - post(new Runnable() { - @Override - public void run() { - mFolderName.setHint(""); - mIsEditingName = true; + 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); + mFolderName.setText(suggestedNames[0]); + mFolderName.displayCompletions(Arrays.asList(suggestedNames).subList(1, + suggestedNames.length)); + } } + mFolderName.setHint(""); + mIsEditingName = true; }); } - @Override public boolean onBackKey() { // Convert to a string here to ensure that no other state associated with the text field @@ -316,10 +322,18 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mFolderIcon.onTitleChanged(newTitle); mLauncher.getModelWriter().updateItemInDatabase(mInfo); - if (TextUtils.isEmpty(mInfo.title)) { - mFolderName.setHint(R.string.folder_hint_text); + if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { + mFolderName.setText(mInfo.title); + // TODO: depending on whether the title was manually edited or automatically + // suggested, apply different hint. + mFolderName.setHint(""); } else { - mFolderName.setHint(null); + if (TextUtils.isEmpty(mInfo.title)) { + mFolderName.setHint(R.string.folder_hint_text); + mFolderName.setText(""); + } else { + mFolderName.setHint(null); + } } sendCustomAccessibilityEvent( @@ -403,7 +417,11 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo mFolderName.setHint(null); } else { mFolderName.setText(""); - mFolderName.setHint(R.string.folder_hint_text); + if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { + mFolderName.setHint(""); + } else { + mFolderName.setHint(R.string.folder_hint_text); + } } // In case any children didn't come across during loading, clean up the folder accordingly mFolderIcon.post(() -> { @@ -420,7 +438,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo if (FeatureFlags.FOLDER_NAME_SUGGEST.get() && TextUtils.isEmpty(mFolderName.getText().toString())) { if (suggestName.length > 0 && !TextUtils.isEmpty(suggestName[0])) { - mFolderName.setHint(suggestName[0]); + mFolderName.setHint(""); mFolderName.setText(suggestName[0]); mInfo.title = suggestName[0]; animateOpen(mInfo.contents, 0, true); @@ -534,6 +552,9 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo openFolder.close(true); } + if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) { + mLauncher.getFolderNameProvider().load(getContext()); + } mContent.bindItems(items); centerAboutIcon(); mItemsInvalidated = true; @@ -1350,6 +1371,7 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo return itemsOnCurrentPage; } + @Override public void onFocusChange(View v, boolean hasFocus) { if (v == mFolderName) { if (hasFocus) { diff --git a/src/com/android/launcher3/folder/FolderNameProvider.java b/src/com/android/launcher3/folder/FolderNameProvider.java index e58d4848a5..d76b73f7ee 100644 --- a/src/com/android/launcher3/folder/FolderNameProvider.java +++ b/src/com/android/launcher3/folder/FolderNameProvider.java @@ -18,13 +18,16 @@ package com.android.launcher3.folder; import android.content.Context; import android.os.Process; import android.text.TextUtils; +import android.util.Log; import com.android.launcher3.AppInfo; import com.android.launcher3.LauncherAppState; import com.android.launcher3.R; import com.android.launcher3.WorkspaceItemInfo; +import com.android.launcher3.config.FeatureFlags; import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.Optional; @@ -38,16 +41,26 @@ import java.util.stream.Collectors; */ public class FolderNameProvider { + private static final String TAG = FeatureFlags.FOLDER_NAME_SUGGEST.getKey(); + private static final boolean DEBUG = FeatureFlags.FOLDER_NAME_SUGGEST.get(); + /** * IME usually has up to 3 suggest slots. In total, there are 4 suggest slots as the folder * name edit box can also be used to provide suggestion. */ public static final int SUGGEST_MAX = 4; + /** + * When inheriting class requires precaching, override this method. + */ + public void load(Context context) {} + public CharSequence getSuggestedFolderName(Context context, ArrayList workspaceItemInfos, CharSequence[] candidates) { - CharSequence suggest; + if (DEBUG) { + Log.d(TAG, "getSuggestedFolderName:" + Arrays.toString(candidates)); + } // If all the icons are from work profile, // Then, suggest "Work" as the folder name List distinctItemInfos = workspaceItemInfos.stream() @@ -75,19 +88,28 @@ public class FolderNameProvider { // Place it as first viable suggestion and shift everything else info.ifPresent(i -> setAsFirstSuggestion(candidates, i.title.toString())); } + if (DEBUG) { + Log.d(TAG, "getSuggestedFolderName:" + Arrays.toString(candidates)); + } return candidates[0]; } private void setAsFirstSuggestion(CharSequence[] candidatesOut, CharSequence candidate) { - for (int i = candidatesOut.length - 1; i > 0; i--) { - if (TextUtils.isEmpty(candidatesOut[i])) { - candidatesOut[i - 1] = candidatesOut[i]; - } - candidatesOut[0] = candidate; + if (contains(candidatesOut, candidate)) { + return; } + for (int i = candidatesOut.length - 1; i > 0; i--) { + if (!TextUtils.isEmpty(candidatesOut[i - 1])) { + candidatesOut[i] = candidatesOut[i - 1]; + } + } + candidatesOut[0] = candidate; } private void setAsLastSuggestion(CharSequence[] candidatesOut, CharSequence candidate) { + if (contains(candidatesOut, candidate)) { + return; + } for (int i = 0; i < candidate.length(); i++) { if (TextUtils.isEmpty(candidatesOut[i])) { candidatesOut[i] = candidate; @@ -95,6 +117,12 @@ public class FolderNameProvider { } } + private boolean contains(CharSequence[] list, CharSequence key) { + return Arrays.asList(list).stream() + .filter(s -> s != null) + .anyMatch(s -> s.toString().equalsIgnoreCase(key.toString())); + } + // This method can be moved to some Utility class location. private static Predicate distinctByKey(Function keyExtractor) { Map map = new ConcurrentHashMap<>();