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
This commit is contained in:
thiruram 2020-06-19 20:10:58 -07:00
parent 5c9a1ef5cd
commit ec75cbd85a
6 changed files with 94 additions and 26 deletions

View File

@ -96,8 +96,21 @@ enum Attribute {
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

View File

@ -114,9 +114,9 @@ public class HotseatEduController {
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);

View File

@ -26,7 +26,6 @@ import static com.android.launcher3.config.FeatureFlags.ALWAYS_USE_HARDWARE_OPTI
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 @@ public class Folder extends AbstractFloatingView implements ClipPathView, DragSo
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);

View File

@ -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.logging.StatsLogManager;
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 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
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 @@ public class FolderIcon extends FrameLayout implements FolderListener, IconLabel
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()

View File

@ -22,6 +22,7 @@ import static androidx.core.util.Preconditions.checkNotNull;
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 static com.android.launcher3.userevent.LauncherLogProto.Target.FromFolder
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 class FolderInfo extends ItemInfo {
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 @@ public class FolderInfo extends ItemInfo {
@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 @@ public class FolderInfo extends ItemInfo {
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 @@ public class FolderInfo extends ItemInfo {
* 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;
}
}
/**

View File

@ -52,6 +52,7 @@ import com.android.launcher3.logger.LauncherAtom.SearchResultContainer;
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 @@ public class ItemInfo {
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;
}
}