Adds additional folder label states (UNLABELED & EMPTY_LABEL)
UNLABELED -> title==null and EMPTY_LABEL -> title=="". When adding new items for the folder if the folder is in UNLABELED state, auto-labeling will be enabled.
This change also addresses auto-labeling issue due to false edit from UNLABELED to EMPTY.
Bug: 159164315
Change-Id: Ia17cd27b4afb60420dc15c544f544061fc46ad33
diff --git a/protos/launcher_atom.proto b/protos/launcher_atom.proto
index d1185bd..98ce9af 100644
--- a/protos/launcher_atom.proto
+++ b/protos/launcher_atom.proto
@@ -96,8 +96,21 @@
ADD_TO_HOMESCREEN = 6; // play install + launcher home setting
ALLAPPS_PREDICTION = 7; // from prediction bar in all apps container
HOTSEAT_PREDICTION = 8; // from prediction bar in hotseat container
- SUGGESTED_LABEL = 9; // folder icon's label was suggested
- MANUAL_LABEL = 10; // folder icon's label was manually edited
+
+ // Folder's label is one of the non-empty suggested values.
+ SUGGESTED_LABEL = 9;
+
+ // Folder's label is non-empty, manually entered by the user
+ // and different from any of suggested values.
+ MANUAL_LABEL = 10;
+
+ // Folder's label is not yet assigned( i.e., title == null).
+ // Eligible for auto-labeling.
+ UNLABELED = 11;
+
+ // Folder's label is empty(i.e., title == "").
+ // Not eligible for auto-labeling.
+ EMPTY_LABEL = 12;
}
// Main app icons
diff --git a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
index c1bf2fd..a1218ae 100644
--- a/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
+++ b/quickstep/recents_ui_overrides/src/com/android/launcher3/hybridhotseat/HotseatEduController.java
@@ -114,9 +114,9 @@
if (!putIntoFolder.isEmpty()) {
ItemInfo firstItem = putIntoFolder.get(0);
FolderInfo folderInfo = new FolderInfo();
- folderInfo.setTitle("");
mLauncher.getModelWriter().addItemToDatabase(folderInfo, firstItem.container,
firstItem.screenId, firstItem.cellX, firstItem.cellY);
+ folderInfo.setTitle("", mLauncher.getModelWriter());
folderInfo.contents.addAll(putIntoFolder);
for (int i = 0; i < folderInfo.contents.size(); i++) {
ItemInfo item = folderInfo.contents.get(i);
diff --git a/src/com/android/launcher3/folder/Folder.java b/src/com/android/launcher3/folder/Folder.java
index 4af3544..d01e189 100644
--- a/src/com/android/launcher3/folder/Folder.java
+++ b/src/com/android/launcher3/folder/Folder.java
@@ -26,7 +26,6 @@
import static com.android.launcher3.logging.LoggerUtils.newContainerTarget;
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.FLAG_MANUAL_FOLDER_NAME;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
@@ -339,11 +338,8 @@
if (DEBUG) {
Log.d(TAG, "onBackKey newTitle=" + newTitle);
}
- mInfo.setTitle(newTitle);
- mInfo.setOption(FLAG_MANUAL_FOLDER_NAME, !mInfo.getAcceptedSuggestionIndex().isPresent(),
- mLauncher.getModelWriter());
+ mInfo.setTitle(newTitle, mLauncher.getModelWriter());
mFolderIcon.onTitleChanged(newTitle);
- mLauncher.getModelWriter().updateItemInDatabase(mInfo);
if (TextUtils.isEmpty(mInfo.title)) {
mFolderName.setHint(R.string.folder_hint_text);
diff --git a/src/com/android/launcher3/folder/FolderIcon.java b/src/com/android/launcher3/folder/FolderIcon.java
index 152fd37..75275b2 100644
--- a/src/com/android/launcher3/folder/FolderIcon.java
+++ b/src/com/android/launcher3/folder/FolderIcon.java
@@ -16,8 +16,6 @@
package com.android.launcher3.folder;
-import static android.text.TextUtils.isEmpty;
-
import static com.android.launcher3.folder.ClippedFolderIconLayoutRule.MAX_NUM_ITEMS_IN_PREVIEW;
import static com.android.launcher3.folder.PreviewItemManager.INITIAL_ITEM_ANIMATION_DURATION;
import static com.android.launcher3.logging.StatsLogManager.LauncherEvent.LAUNCHER_FOLDER_AUTO_LABELED;
@@ -72,6 +70,7 @@
import com.android.launcher3.model.data.AppInfo;
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.WorkspaceItemInfo;
import com.android.launcher3.touch.ItemClickHandler;
@@ -443,8 +442,7 @@
if (!FeatureFlags.FOLDER_NAME_SUGGEST.get()) {
return;
}
- if (!isEmpty(mFolderName.getText().toString())
- || mInfo.hasOption(FolderInfo.FLAG_MANUAL_FOLDER_NAME)) {
+ if (!mInfo.getLabelState().equals(LabelState.UNLABELED)) {
return;
}
if (nameInfos == null || !nameInfos.hasSuggestions()) {
@@ -464,10 +462,9 @@
CharSequence newTitle = nameInfos.getLabels()[0];
FromState fromState = mInfo.getFromLabelState();
- mInfo.setTitle(newTitle);
+ mInfo.setTitle(newTitle, mFolder.mLauncher.getModelWriter());
onTitleChanged(mInfo.title);
mFolder.mFolderName.setText(mInfo.title);
- mFolder.mLauncher.getModelWriter().updateItemInDatabase(mInfo);
// Logging for folder creation flow
StatsLogManager.newInstance(getContext()).logger()
diff --git a/src/com/android/launcher3/model/data/FolderInfo.java b/src/com/android/launcher3/model/data/FolderInfo.java
index ecd18ce..05ce06a 100644
--- a/src/com/android/launcher3/model/data/FolderInfo.java
+++ b/src/com/android/launcher3/model/data/FolderInfo.java
@@ -22,6 +22,7 @@
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_DESKTOP;
import static com.android.launcher3.LauncherSettings.Favorites.CONTAINER_HOTSEAT;
+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;
import static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolderLabelState.FROM_CUSTOM;
@@ -31,11 +32,14 @@
import android.os.Process;
+import androidx.annotation.Nullable;
+
import com.android.launcher3.LauncherSettings;
import com.android.launcher3.Utilities;
import com.android.launcher3.config.FeatureFlags;
import com.android.launcher3.folder.FolderNameInfos;
import com.android.launcher3.logger.LauncherAtom;
+import com.android.launcher3.logger.LauncherAtom.Attribute;
import com.android.launcher3.logger.LauncherAtom.FromState;
import com.android.launcher3.logger.LauncherAtom.ToState;
import com.android.launcher3.model.ModelWriter;
@@ -74,6 +78,30 @@
public static final int FLAG_MANUAL_FOLDER_NAME = 0x00000008;
+ /**
+ * Different states of folder label.
+ */
+ public enum LabelState {
+ // Folder's label is not yet assigned( i.e., title == null). Eligible for auto-labeling.
+ UNLABELED(Attribute.UNLABELED),
+
+ // Folder's label is empty(i.e., title == ""). Not eligible for auto-labeling.
+ EMPTY(EMPTY_LABEL),
+
+ // Folder's label is one of the non-empty suggested values.
+ SUGGESTED(SUGGESTED_LABEL),
+
+ // Folder's label is non-empty, manually entered by the user
+ // and different from any of suggested values.
+ MANUAL(MANUAL_LABEL);
+
+ private final LauncherAtom.Attribute mLogAttribute;
+
+ LabelState(Attribute logAttribute) {
+ this.mLogAttribute = logAttribute;
+ }
+ }
+
public static final String EXTRA_FOLDER_SUGGESTIONS = "suggest";
public int options;
@@ -176,8 +204,7 @@
@Override
protected String dumpProperties() {
- return super.dumpProperties()
- + " manuallyTypedTitle=" + hasOption(FLAG_MANUAL_FOLDER_NAME);
+ return String.format("%s; labelState=%s", super.dumpProperties(), getLabelState());
}
@Override
@@ -185,14 +212,41 @@
return getDefaultItemInfoBuilder()
.setFolderIcon(LauncherAtom.FolderIcon.newBuilder().setCardinality(contents.size()))
.setRank(rank)
- .setAttribute(hasOption(FLAG_MANUAL_FOLDER_NAME) ? MANUAL_LABEL : SUGGESTED_LABEL)
+ .setAttribute(getLabelState().mLogAttribute)
.setContainerInfo(getContainerInfo())
.build();
}
@Override
- public void setTitle(CharSequence title) {
+ 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.
+ if (isEmpty(title) && this.title == null) {
+ return;
+ }
+
+ // Updating title to same value does not change any states.
+ if (title != null && title == this.title) {
+ return;
+ }
+
this.title = title;
+ LabelState newLabelState =
+ title == null ? LabelState.UNLABELED
+ : title.length() == 0 ? LabelState.EMPTY :
+ getAcceptedSuggestionIndex().isPresent() ? LabelState.SUGGESTED
+ : LabelState.MANUAL;
+ setOption(FLAG_MANUAL_FOLDER_NAME, newLabelState.equals(LabelState.MANUAL), modelWriter);
+ }
+
+ /**
+ * Returns current state of the current folder label.
+ */
+ public LabelState getLabelState() {
+ return title == null ? LabelState.UNLABELED
+ : title.length() == 0 ? LabelState.EMPTY :
+ hasOption(FLAG_MANUAL_FOLDER_NAME) ? LabelState.MANUAL
+ : LabelState.SUGGESTED;
}
@Override
@@ -233,13 +287,17 @@
* Returns {@link FromState} based on current {@link #title}.
*/
public LauncherAtom.FromState getFromLabelState() {
- return title == null
- ? LauncherAtom.FromState.FROM_STATE_UNSPECIFIED
- : title.length() == 0
- ? LauncherAtom.FromState.FROM_EMPTY
- : hasOption(FLAG_MANUAL_FOLDER_NAME)
- ? LauncherAtom.FromState.FROM_CUSTOM
- : LauncherAtom.FromState.FROM_SUGGESTED;
+ switch (getLabelState()){
+ case EMPTY:
+ return LauncherAtom.FromState.FROM_EMPTY;
+ case MANUAL:
+ return LauncherAtom.FromState.FROM_CUSTOM;
+ case SUGGESTED:
+ return LauncherAtom.FromState.FROM_SUGGESTED;
+ case UNLABELED:
+ default:
+ return LauncherAtom.FromState.FROM_STATE_UNSPECIFIED;
+ }
}
/**
diff --git a/src/com/android/launcher3/model/data/ItemInfo.java b/src/com/android/launcher3/model/data/ItemInfo.java
index 66c3cbb..3082b6e 100644
--- a/src/com/android/launcher3/model/data/ItemInfo.java
+++ b/src/com/android/launcher3/model/data/ItemInfo.java
@@ -52,6 +52,7 @@
import com.android.launcher3.logger.LauncherAtom.SettingsContainer;
import com.android.launcher3.logger.LauncherAtom.ShortcutsContainer;
import com.android.launcher3.logger.LauncherAtom.TaskSwitcherContainer;
+import com.android.launcher3.model.ModelWriter;
import com.android.launcher3.util.ContentWriter;
import java.util.Optional;
@@ -405,7 +406,10 @@
return itemInfo;
}
- public void setTitle(CharSequence title) {
+ /**
+ * Sets the title of the item and writes to DB model if needed.
+ */
+ public void setTitle(CharSequence title, ModelWriter modelWriter) {
this.title = title;
}
}