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
diff --git a/src/com/android/launcher3/ExtendedEditText.java b/src/com/android/launcher3/ExtendedEditText.java
index 8b6d209..5b453c3 100644
--- a/src/com/android/launcher3/ExtendedEditText.java
+++ b/src/com/android/launcher3/ExtendedEditText.java
@@ -44,7 +44,7 @@
* 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 52d8f7f..844189f 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -297,16 +297,22 @@
}
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 @@
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 @@
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 @@
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 @@
openFolder.close(true);
}
+ if (FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
+ mLauncher.getFolderNameProvider().load(getContext());
+ }
mContent.bindItems(items);
centerAboutIcon();
mItemsInvalidated = true;
@@ -1350,6 +1371,7 @@
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 e58d484..d76b73f 100644
--- a/src/com/android/launcher3/folder/FolderNameProvider.java
+++ b/src/com/android/launcher3/folder/FolderNameProvider.java
@@ -18,13 +18,16 @@
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 @@
*/
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<WorkspaceItemInfo> 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<WorkspaceItemInfo> distinctItemInfos = workspaceItemInfos.stream()
@@ -75,19 +88,28 @@
// 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 @@
}
}
+ 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 <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> map = new ConcurrentHashMap<>();