mirror of
https://github.com/LawnchairLauncher/lawnchair.git
synced 2026-03-04 01:46:49 +00:00
Merge "Removing unnecessary search header duplication" into tm-qpr-dev
This commit is contained in:
@@ -19,7 +19,6 @@
|
||||
<item type="id" name="view_type_widgets_space" />
|
||||
<item type="id" name="view_type_widgets_list" />
|
||||
<item type="id" name="view_type_widgets_header" />
|
||||
<item type="id" name="view_type_widgets_search_header" />
|
||||
<!-- Used for A11y actions in staged split to identify each task uniquely -->
|
||||
<item type="id" name="split_topLeft_appInfo" />
|
||||
<item type="id" name="split_bottomRight_appInfo" />
|
||||
|
||||
@@ -59,27 +59,12 @@ public abstract class WidgetsListBaseEntry {
|
||||
@Rank
|
||||
public abstract int getRank();
|
||||
|
||||
/**
|
||||
* Marker interface for subclasses that are headers for widget list items.
|
||||
*
|
||||
* @param <T> The type of this class.
|
||||
*/
|
||||
public interface Header<T extends WidgetsListBaseEntry & Header<T>> {
|
||||
/** Returns whether the widget list is currently expanded. */
|
||||
boolean isWidgetListShown();
|
||||
|
||||
/** Returns a copy of the item with the widget list shown. */
|
||||
T withWidgetListShown();
|
||||
}
|
||||
|
||||
@Retention(SOURCE)
|
||||
@IntDef({RANK_WIDGETS_TOP_SPACE, RANK_WIDGETS_LIST_HEADER, RANK_WIDGETS_LIST_SEARCH_HEADER,
|
||||
RANK_WIDGETS_LIST_CONTENT})
|
||||
@IntDef({RANK_WIDGETS_TOP_SPACE, RANK_WIDGETS_LIST_HEADER, RANK_WIDGETS_LIST_CONTENT})
|
||||
public @interface Rank {
|
||||
}
|
||||
|
||||
public static final int RANK_WIDGETS_TOP_SPACE = 1;
|
||||
public static final int RANK_WIDGETS_LIST_HEADER = 2;
|
||||
public static final int RANK_WIDGETS_LIST_SEARCH_HEADER = 3;
|
||||
public static final int RANK_WIDGETS_LIST_CONTENT = 4;
|
||||
public static final int RANK_WIDGETS_LIST_CONTENT = 3;
|
||||
}
|
||||
|
||||
@@ -15,35 +15,67 @@
|
||||
*/
|
||||
package com.android.launcher3.widget.model;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.model.WidgetItem;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.util.PluralMessageFormat;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/** An information holder for an app which has widgets or/and shortcuts. */
|
||||
public final class WidgetsListHeaderEntry extends WidgetsListBaseEntry
|
||||
implements WidgetsListBaseEntry.Header<WidgetsListHeaderEntry> {
|
||||
public final class WidgetsListHeaderEntry extends WidgetsListBaseEntry {
|
||||
|
||||
public final int widgetsCount;
|
||||
public final int shortcutsCount;
|
||||
private static final BiFunction<Context, WidgetsListHeaderEntry, String> SUBTITLE_SEARCH =
|
||||
(context, entry) -> entry.mWidgets.stream()
|
||||
.map(item -> item.label).sorted().collect(Collectors.joining(", "));
|
||||
|
||||
private static final BiFunction<Context, WidgetsListHeaderEntry, String> SUBTITLE_DEFAULT =
|
||||
(context, entry) -> {
|
||||
List<WidgetItem> items = entry.mWidgets;
|
||||
int wc = (int) items.stream().filter(item -> item.widgetInfo != null).count();
|
||||
int sc = Math.max(0, items.size() - wc);
|
||||
|
||||
Resources resources = context.getResources();
|
||||
if (wc == 0 && sc == 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String subtitle;
|
||||
if (wc > 0 && sc > 0) {
|
||||
String widgetsCount = PluralMessageFormat.getIcuPluralString(context,
|
||||
R.string.widgets_count, wc);
|
||||
String shortcutsCount = PluralMessageFormat.getIcuPluralString(context,
|
||||
R.string.shortcuts_count, sc);
|
||||
subtitle = resources.getString(R.string.widgets_and_shortcuts_count,
|
||||
widgetsCount, shortcutsCount);
|
||||
} else if (wc > 0) {
|
||||
subtitle = PluralMessageFormat.getIcuPluralString(context,
|
||||
R.string.widgets_count, wc);
|
||||
} else {
|
||||
subtitle = PluralMessageFormat.getIcuPluralString(context,
|
||||
R.string.shortcuts_count, sc);
|
||||
}
|
||||
return subtitle;
|
||||
};
|
||||
|
||||
private final boolean mIsWidgetListShown;
|
||||
|
||||
public WidgetsListHeaderEntry(PackageItemInfo pkgItem, String titleSectionName,
|
||||
List<WidgetItem> items) {
|
||||
this(pkgItem, titleSectionName, items, /* isWidgetListShown= */ false);
|
||||
}
|
||||
private final boolean mIsSearchEntry;
|
||||
|
||||
private WidgetsListHeaderEntry(PackageItemInfo pkgItem, String titleSectionName,
|
||||
List<WidgetItem> items, boolean isWidgetListShown) {
|
||||
List<WidgetItem> items, boolean isSearchEntry, boolean isWidgetListShown) {
|
||||
super(pkgItem, titleSectionName, items);
|
||||
widgetsCount = (int) items.stream().filter(item -> item.widgetInfo != null).count();
|
||||
shortcutsCount = Math.max(0, items.size() - widgetsCount);
|
||||
mIsSearchEntry = isSearchEntry;
|
||||
mIsWidgetListShown = isWidgetListShown;
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the widgets list associated with this header is shown. */
|
||||
@Override
|
||||
public boolean isWidgetListShown() {
|
||||
return mIsWidgetListShown;
|
||||
}
|
||||
@@ -59,23 +91,54 @@ public final class WidgetsListHeaderEntry extends WidgetsListBaseEntry
|
||||
return RANK_WIDGETS_LIST_HEADER;
|
||||
}
|
||||
|
||||
public boolean isSearchEntry() {
|
||||
return mIsSearchEntry;
|
||||
}
|
||||
|
||||
@Nullable
|
||||
public String getSubtitle(Context context) {
|
||||
return mIsSearchEntry
|
||||
? SUBTITLE_SEARCH.apply(context, this) : SUBTITLE_DEFAULT.apply(context, this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof WidgetsListHeaderEntry)) return false;
|
||||
WidgetsListHeaderEntry otherEntry = (WidgetsListHeaderEntry) obj;
|
||||
return mWidgets.equals(otherEntry.mWidgets) && mPkgItem.equals(otherEntry.mPkgItem)
|
||||
&& mTitleSectionName.equals(otherEntry.mTitleSectionName)
|
||||
&& mIsWidgetListShown == otherEntry.mIsWidgetListShown;
|
||||
&& mIsWidgetListShown == otherEntry.mIsWidgetListShown
|
||||
&& mIsSearchEntry == otherEntry.mIsSearchEntry;
|
||||
}
|
||||
|
||||
/** Returns a copy of this {@link WidgetsListHeaderEntry} with the widget list shown. */
|
||||
@Override
|
||||
public WidgetsListHeaderEntry withWidgetListShown() {
|
||||
if (mIsWidgetListShown) return this;
|
||||
return new WidgetsListHeaderEntry(
|
||||
mPkgItem,
|
||||
mTitleSectionName,
|
||||
mWidgets,
|
||||
mIsSearchEntry,
|
||||
/* isWidgetListShown= */ true);
|
||||
}
|
||||
|
||||
public static WidgetsListHeaderEntry create(PackageItemInfo pkgItem, String titleSectionName,
|
||||
List<WidgetItem> items) {
|
||||
return new WidgetsListHeaderEntry(
|
||||
pkgItem,
|
||||
titleSectionName,
|
||||
items,
|
||||
/* forSearch */ false,
|
||||
/* isWidgetListShown= */ false);
|
||||
}
|
||||
|
||||
public static WidgetsListHeaderEntry createForSearch(PackageItemInfo pkgItem,
|
||||
String titleSectionName, List<WidgetItem> items) {
|
||||
return new WidgetsListHeaderEntry(
|
||||
pkgItem,
|
||||
titleSectionName,
|
||||
items,
|
||||
/* forSearch */ true,
|
||||
/* isWidgetListShown= */ false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.widget.model;
|
||||
|
||||
import com.android.launcher3.model.WidgetItem;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/** An information holder for an app which has widgets or/and shortcuts, to be shown in search. */
|
||||
public final class WidgetsListSearchHeaderEntry extends WidgetsListBaseEntry
|
||||
implements WidgetsListBaseEntry.Header<WidgetsListSearchHeaderEntry> {
|
||||
|
||||
private final boolean mIsWidgetListShown;
|
||||
|
||||
public WidgetsListSearchHeaderEntry(PackageItemInfo pkgItem, String titleSectionName,
|
||||
List<WidgetItem> items) {
|
||||
this(pkgItem, titleSectionName, items, /* isWidgetListShown= */ false);
|
||||
}
|
||||
|
||||
private WidgetsListSearchHeaderEntry(PackageItemInfo pkgItem, String titleSectionName,
|
||||
List<WidgetItem> items, boolean isWidgetListShown) {
|
||||
super(pkgItem, titleSectionName, items);
|
||||
mIsWidgetListShown = isWidgetListShown;
|
||||
}
|
||||
|
||||
/** Returns {@code true} if the widgets list associated with this header is shown. */
|
||||
@Override
|
||||
public boolean isWidgetListShown() {
|
||||
return mIsWidgetListShown;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SearchHeader:" + mPkgItem.packageName + ":" + mWidgets.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Rank
|
||||
public int getRank() {
|
||||
return RANK_WIDGETS_LIST_SEARCH_HEADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (!(obj instanceof WidgetsListSearchHeaderEntry)) return false;
|
||||
WidgetsListSearchHeaderEntry otherEntry = (WidgetsListSearchHeaderEntry) obj;
|
||||
return mWidgets.equals(otherEntry.mWidgets) && mPkgItem.equals(otherEntry.mPkgItem)
|
||||
&& mTitleSectionName.equals(otherEntry.mTitleSectionName)
|
||||
&& mIsWidgetListShown == otherEntry.mIsWidgetListShown;
|
||||
}
|
||||
|
||||
/** Returns a copy of this {@link WidgetsListSearchHeaderEntry} with the widget list shown. */
|
||||
@Override
|
||||
public WidgetsListSearchHeaderEntry withWidgetListShown() {
|
||||
if (mIsWidgetListShown) return this;
|
||||
return new WidgetsListSearchHeaderEntry(
|
||||
mPkgItem,
|
||||
mTitleSectionName,
|
||||
mWidgets,
|
||||
/* isWidgetListShown= */ true);
|
||||
}
|
||||
}
|
||||
@@ -25,7 +25,6 @@ import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListContentEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
|
||||
import com.android.launcher3.widget.picker.WidgetsListAdapter.WidgetListBaseRowEntryComparator;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -175,12 +174,8 @@ public class WidgetsDiffReporter {
|
||||
*/
|
||||
private boolean hasHeaderUpdated(WidgetsListBaseEntry curRow, WidgetsListBaseEntry newRow) {
|
||||
if (newRow instanceof WidgetsListHeaderEntry && curRow instanceof WidgetsListHeaderEntry) {
|
||||
return !curRow.equals(newRow);
|
||||
}
|
||||
if (newRow instanceof WidgetsListSearchHeaderEntry
|
||||
&& curRow instanceof WidgetsListSearchHeaderEntry) {
|
||||
// Always refresh search header entries to reset rounded corners in their view holder.
|
||||
return true;
|
||||
return !curRow.equals(newRow) || ((WidgetsListHeaderEntry) curRow).isSearchEntry();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -286,7 +286,7 @@ public class WidgetsFullSheet extends BaseWidgetSheet
|
||||
}
|
||||
};
|
||||
packageItemInfo.title = getContext().getString(R.string.suggested_widgets_header_title);
|
||||
WidgetsListHeaderEntry widgetsListHeaderEntry = new WidgetsListHeaderEntry(
|
||||
WidgetsListHeaderEntry widgetsListHeaderEntry = WidgetsListHeaderEntry.create(
|
||||
packageItemInfo,
|
||||
getContext().getString(R.string.suggested_widgets_header_title),
|
||||
mActivityContext.getPopupDataProvider().getRecommendedWidgets())
|
||||
|
||||
@@ -48,7 +48,6 @@ import com.android.launcher3.widget.model.WidgetListSpaceEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListContentEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
@@ -81,7 +80,6 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
public static final int VIEW_TYPE_WIDGETS_SPACE = R.id.view_type_widgets_space;
|
||||
public static final int VIEW_TYPE_WIDGETS_LIST = R.id.view_type_widgets_list;
|
||||
public static final int VIEW_TYPE_WIDGETS_HEADER = R.id.view_type_widgets_header;
|
||||
public static final int VIEW_TYPE_WIDGETS_SEARCH_HEADER = R.id.view_type_widgets_search_header;
|
||||
|
||||
private final Context mContext;
|
||||
private final WidgetsDiffReporter mDiffReporter;
|
||||
@@ -96,7 +94,6 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
|
||||
private Predicate<WidgetsListBaseEntry> mHeaderAndSelectedContentFilter = entry ->
|
||||
entry instanceof WidgetsListHeaderEntry
|
||||
|| entry instanceof WidgetsListSearchHeaderEntry
|
||||
|| PackageUserKey.fromPackageItemInfo(entry.mPkgItem)
|
||||
.equals(mWidgetsContentVisiblePackageUserKey);
|
||||
@Nullable private Predicate<WidgetsListBaseEntry> mFilter = null;
|
||||
@@ -124,12 +121,6 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
layoutInflater,
|
||||
/* onHeaderClickListener= */ this,
|
||||
listDrawableFactory));
|
||||
mViewHolderBinders.put(
|
||||
VIEW_TYPE_WIDGETS_SEARCH_HEADER,
|
||||
new WidgetsListSearchHeaderViewHolderBinder(
|
||||
layoutInflater,
|
||||
/* onHeaderClickListener= */ this,
|
||||
listDrawableFactory));
|
||||
mViewHolderBinders.put(
|
||||
VIEW_TYPE_WIDGETS_SPACE,
|
||||
new WidgetsSpaceViewHolderBinder(emptySpaceHeightProvider));
|
||||
@@ -205,10 +196,10 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
&& (mHeaderChangeListener == null
|
||||
|| !(entry instanceof WidgetsListContentEntry)))
|
||||
.map(entry -> {
|
||||
if (entry instanceof WidgetsListBaseEntry.Header<?>
|
||||
if (entry instanceof WidgetsListHeaderEntry
|
||||
&& matchesKey(entry, mWidgetsContentVisiblePackageUserKey)) {
|
||||
// Adjust the original entries to expand headers for the selected content.
|
||||
return ((WidgetsListBaseEntry.Header<?>) entry).withWidgetListShown();
|
||||
return ((WidgetsListHeaderEntry) entry).withWidgetListShown();
|
||||
} else if (entry instanceof WidgetsListContentEntry) {
|
||||
// Adjust the original content entries to accommodate for the current
|
||||
// maxSpanSize.
|
||||
@@ -233,7 +224,7 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
/** Returns whether {@code entry} matches {@code key}. */
|
||||
private static boolean isHeaderForPackageUserKey(
|
||||
@NonNull WidgetsListBaseEntry entry, @Nullable PackageUserKey key) {
|
||||
return entry instanceof WidgetsListBaseEntry.Header && matchesKey(entry, key);
|
||||
return entry instanceof WidgetsListHeaderEntry && matchesKey(entry, key);
|
||||
}
|
||||
|
||||
private static boolean matchesKey(@NonNull WidgetsListBaseEntry entry,
|
||||
@@ -276,16 +267,11 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
* first header in the new list that gets generated as we search.
|
||||
*/
|
||||
void selectFirstHeaderEntry() {
|
||||
WidgetsListSearchHeaderEntry firstEntry = null;
|
||||
for (WidgetsListBaseEntry entry: mVisibleEntries) {
|
||||
if (entry instanceof WidgetsListSearchHeaderEntry) {
|
||||
firstEntry = (WidgetsListSearchHeaderEntry) entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (firstEntry != null) {
|
||||
onHeaderClicked(true, PackageUserKey.fromPackageItemInfo(firstEntry.mPkgItem));
|
||||
}
|
||||
mVisibleEntries.stream()
|
||||
.filter(entry -> entry instanceof WidgetsListHeaderEntry)
|
||||
.findFirst()
|
||||
.ifPresent(entry ->
|
||||
onHeaderClicked(true, PackageUserKey.fromPackageItemInfo(entry.mPkgItem)));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -325,8 +311,6 @@ public class WidgetsListAdapter extends Adapter<ViewHolder> implements OnHeaderC
|
||||
return VIEW_TYPE_WIDGETS_LIST;
|
||||
} else if (entry instanceof WidgetsListHeaderEntry) {
|
||||
return VIEW_TYPE_WIDGETS_HEADER;
|
||||
} else if (entry instanceof WidgetsListSearchHeaderEntry) {
|
||||
return VIEW_TYPE_WIDGETS_SEARCH_HEADER;
|
||||
} else if (entry instanceof WidgetListSpaceEntry) {
|
||||
return VIEW_TYPE_WIDGETS_SPACE;
|
||||
}
|
||||
|
||||
@@ -18,12 +18,12 @@ package com.android.launcher3.widget.picker;
|
||||
import static com.android.launcher3.config.FeatureFlags.LARGE_SCREEN_WIDGET_PICKER;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Color;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.graphics.drawable.GradientDrawable;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.TypedValue;
|
||||
import android.view.View;
|
||||
@@ -45,13 +45,9 @@ import com.android.launcher3.icons.PlaceHolderIconDrawable;
|
||||
import com.android.launcher3.icons.cache.HandlerRunnable;
|
||||
import com.android.launcher3.model.data.ItemInfoWithIcon;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.util.PluralMessageFormat;
|
||||
import com.android.launcher3.util.Themes;
|
||||
import com.android.launcher3.views.ActivityContext;
|
||||
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
|
||||
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* A UI represents a header of an app shown in the full widgets tray.
|
||||
@@ -201,11 +197,6 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
|
||||
/** Apply app icon, labels and tag using a generic {@link WidgetsListHeaderEntry}. */
|
||||
@UiThread
|
||||
public void applyFromItemInfoWithIcon(WidgetsListHeaderEntry entry) {
|
||||
applyIconAndLabel(entry);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void applyIconAndLabel(WidgetsListHeaderEntry entry) {
|
||||
PackageItemInfo info = entry.mPkgItem;
|
||||
setIcon(info.newIcon(getContext()));
|
||||
setTitles(entry);
|
||||
@@ -247,55 +238,13 @@ public final class WidgetsListHeader extends LinearLayout implements ItemInfoUpd
|
||||
private void setTitles(WidgetsListHeaderEntry entry) {
|
||||
mTitle.setText(entry.mPkgItem.title);
|
||||
|
||||
Resources resources = getContext().getResources();
|
||||
if (entry.widgetsCount == 0 && entry.shortcutsCount == 0) {
|
||||
String subtitle = entry.getSubtitle(getContext());
|
||||
if (TextUtils.isEmpty(subtitle)) {
|
||||
mSubtitle.setVisibility(GONE);
|
||||
return;
|
||||
}
|
||||
|
||||
String subtitle;
|
||||
if (entry.widgetsCount > 0 && entry.shortcutsCount > 0) {
|
||||
String widgetsCount = PluralMessageFormat.getIcuPluralString(getContext(),
|
||||
R.string.widgets_count, entry.widgetsCount);
|
||||
String shortcutsCount = PluralMessageFormat.getIcuPluralString(getContext(),
|
||||
R.string.shortcuts_count, entry.shortcutsCount);
|
||||
subtitle = resources.getString(R.string.widgets_and_shortcuts_count, widgetsCount,
|
||||
shortcutsCount);
|
||||
} else if (entry.widgetsCount > 0) {
|
||||
subtitle = PluralMessageFormat.getIcuPluralString(getContext(),
|
||||
R.string.widgets_count, entry.widgetsCount);
|
||||
} else {
|
||||
subtitle = PluralMessageFormat.getIcuPluralString(getContext(),
|
||||
R.string.shortcuts_count, entry.shortcutsCount);
|
||||
mSubtitle.setText(subtitle);
|
||||
mSubtitle.setVisibility(VISIBLE);
|
||||
}
|
||||
mSubtitle.setText(subtitle);
|
||||
mSubtitle.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
/** Apply app icon, labels and tag using a generic {@link WidgetsListSearchHeaderEntry}. */
|
||||
@UiThread
|
||||
public void applyFromItemInfoWithIcon(WidgetsListSearchHeaderEntry entry) {
|
||||
applyIconAndLabel(entry);
|
||||
}
|
||||
|
||||
@UiThread
|
||||
private void applyIconAndLabel(WidgetsListSearchHeaderEntry entry) {
|
||||
PackageItemInfo info = entry.mPkgItem;
|
||||
setIcon(info.newIcon(getContext()));
|
||||
setTitles(entry);
|
||||
setExpanded(entry.isWidgetListShown());
|
||||
|
||||
super.setTag(info);
|
||||
|
||||
verifyHighRes();
|
||||
}
|
||||
|
||||
private void setTitles(WidgetsListSearchHeaderEntry entry) {
|
||||
mTitle.setText(entry.mPkgItem.title);
|
||||
|
||||
mSubtitle.setText(entry.mWidgets.stream()
|
||||
.map(item -> item.label).sorted().collect(Collectors.joining(", ")));
|
||||
mSubtitle.setVisibility(VISIBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,70 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.widget.picker;
|
||||
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.recyclerview.ViewHolderBinder;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Binds data from {@link WidgetsListHeaderEntry} to UI elements in {@link WidgetsListHeaderHolder}.
|
||||
*/
|
||||
public final class WidgetsListSearchHeaderViewHolderBinder implements
|
||||
ViewHolderBinder<WidgetsListSearchHeaderEntry, WidgetsListSearchHeaderHolder> {
|
||||
private final LayoutInflater mLayoutInflater;
|
||||
private final OnHeaderClickListener mOnHeaderClickListener;
|
||||
private final WidgetsListDrawableFactory mListDrawableFactory;
|
||||
|
||||
public WidgetsListSearchHeaderViewHolderBinder(LayoutInflater layoutInflater,
|
||||
OnHeaderClickListener onHeaderClickListener,
|
||||
WidgetsListDrawableFactory listDrawableFactory) {
|
||||
mLayoutInflater = layoutInflater;
|
||||
mOnHeaderClickListener = onHeaderClickListener;
|
||||
mListDrawableFactory = listDrawableFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WidgetsListSearchHeaderHolder newViewHolder(ViewGroup parent) {
|
||||
WidgetsListHeader header = (WidgetsListHeader) mLayoutInflater.inflate(
|
||||
R.layout.widgets_list_row_header, parent, false);
|
||||
header.setBackground(mListDrawableFactory.createHeaderBackgroundDrawable());
|
||||
return new WidgetsListSearchHeaderHolder(header);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindViewHolder(WidgetsListSearchHeaderHolder viewHolder,
|
||||
WidgetsListSearchHeaderEntry data, @ListPosition int position, List<Object> payloads) {
|
||||
WidgetsListHeader widgetsListHeader = viewHolder.mWidgetsListHeader;
|
||||
widgetsListHeader.applyFromItemInfoWithIcon(data);
|
||||
widgetsListHeader.setSelected(data.isWidgetListShown());
|
||||
widgetsListHeader.setExpanded(data.isWidgetListShown());
|
||||
widgetsListHeader.setListDrawableState(
|
||||
WidgetsListDrawableState.obtain(
|
||||
(position & POSITION_FIRST) != 0,
|
||||
(position & POSITION_LAST) != 0,
|
||||
/* isExpanded= */ data.isWidgetListShown()));
|
||||
widgetsListHeader.setOnExpandChangeListener(isExpanded ->
|
||||
mOnHeaderClickListener.onHeaderClicked(isExpanded,
|
||||
PackageUserKey.fromPackageItemInfo(data.mPkgItem)));
|
||||
}
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import com.android.launcher3.search.StringMatcherUtility.StringMatcher;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListContentEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -72,7 +71,7 @@ public final class SimpleWidgetsSearchAlgorithm implements SearchAlgorithm<Widge
|
||||
List<WidgetItem> matchedWidgetItems = filterWidgetItems(
|
||||
input, headerEntry.mPkgItem.title.toString(), headerEntry.mWidgets);
|
||||
if (matchedWidgetItems.size() > 0) {
|
||||
results.add(new WidgetsListSearchHeaderEntry(headerEntry.mPkgItem,
|
||||
results.add(WidgetsListHeaderEntry.createForSearch(headerEntry.mPkgItem,
|
||||
headerEntry.mTitleSectionName, matchedWidgetItems));
|
||||
results.add(new WidgetsListContentEntry(headerEntry.mPkgItem,
|
||||
headerEntry.mTitleSectionName, matchedWidgetItems));
|
||||
|
||||
@@ -87,7 +87,7 @@ public class WidgetsModel {
|
||||
List<WidgetItem> widgetItems = entry.getValue();
|
||||
String sectionName = (pkgItem.title == null) ? "" :
|
||||
indexer.computeSectionName(pkgItem.title);
|
||||
result.add(new WidgetsListHeaderEntry(pkgItem, sectionName, widgetItems));
|
||||
result.add(WidgetsListHeaderEntry.create(pkgItem, sectionName, widgetItems));
|
||||
result.add(new WidgetsListContentEntry(pkgItem, sectionName, widgetItems));
|
||||
}
|
||||
return result;
|
||||
|
||||
@@ -229,7 +229,7 @@ public final class WidgetsDiffReporterTest {
|
||||
List.of(mHeaderA, mHeaderB, mContentE));
|
||||
// GIVEN the new list has one of the headers widgets list modified.
|
||||
List<WidgetsListBaseEntry> newList = List.of(
|
||||
new WidgetsListHeaderEntry(
|
||||
WidgetsListHeaderEntry.create(
|
||||
mHeaderA.mPkgItem, mHeaderA.mTitleSectionName,
|
||||
mHeaderA.mWidgets.subList(0, 1)),
|
||||
mHeaderB, mContentE);
|
||||
@@ -274,7 +274,7 @@ public final class WidgetsDiffReporterTest {
|
||||
PackageItemInfo pInfo = createPackageItemInfo(packageName, appName,
|
||||
widgetItems.get(0).user);
|
||||
|
||||
return new WidgetsListHeaderEntry(pInfo, /* titleSectionName= */ "", widgetItems);
|
||||
return WidgetsListHeaderEntry.create(pInfo, /* titleSectionName= */ "", widgetItems);
|
||||
}
|
||||
|
||||
private WidgetsListContentEntry createWidgetsContentEntry(String packageName, String appName,
|
||||
|
||||
@@ -270,7 +270,8 @@ public final class WidgetsListAdapterTest {
|
||||
pInfo.title = pInfo.packageName;
|
||||
pInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
|
||||
|
||||
result.add(new WidgetsListHeaderEntry(pInfo, /* titleSectionName= */ "", widgetItems));
|
||||
result.add(WidgetsListHeaderEntry.create(
|
||||
pInfo, /* titleSectionName= */ "", widgetItems));
|
||||
result.add(new WidgetsListContentEntry(pInfo, /* titleSectionName= */ "", widgetItems));
|
||||
}
|
||||
|
||||
|
||||
@@ -134,7 +134,7 @@ public final class WidgetsListHeaderViewHolderBinderTest {
|
||||
appInfo.title = appName;
|
||||
appInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
|
||||
|
||||
return new WidgetsListHeaderEntry(appInfo,
|
||||
return WidgetsListHeaderEntry.create(appInfo,
|
||||
/* titleSectionName= */ "",
|
||||
generateWidgetItems(packageName, numOfWidgets));
|
||||
}
|
||||
|
||||
@@ -1,154 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2021 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.android.launcher3.widget.picker;
|
||||
|
||||
import static androidx.test.core.app.ApplicationProvider.getApplicationContext;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import static java.util.Collections.EMPTY_LIST;
|
||||
|
||||
import android.appwidget.AppWidgetProviderInfo;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.UserHandle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
import androidx.test.ext.junit.runners.AndroidJUnit4;
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import com.android.launcher3.InvariantDeviceProfile;
|
||||
import com.android.launcher3.R;
|
||||
import com.android.launcher3.icons.BitmapInfo;
|
||||
import com.android.launcher3.icons.ComponentWithLabel;
|
||||
import com.android.launcher3.icons.IconCache;
|
||||
import com.android.launcher3.model.WidgetItem;
|
||||
import com.android.launcher3.model.data.PackageItemInfo;
|
||||
import com.android.launcher3.util.ActivityContextWrapper;
|
||||
import com.android.launcher3.util.PackageUserKey;
|
||||
import com.android.launcher3.util.WidgetUtils;
|
||||
import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
@SmallTest
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
public final class WidgetsListSearchHeaderViewHolderBinderTest {
|
||||
private static final String TEST_PACKAGE = "com.google.test";
|
||||
private static final String APP_NAME = "Test app";
|
||||
|
||||
private Context mContext;
|
||||
private WidgetsListSearchHeaderViewHolderBinder mViewHolderBinder;
|
||||
private InvariantDeviceProfile mTestProfile;
|
||||
|
||||
@Mock
|
||||
private IconCache mIconCache;
|
||||
@Mock
|
||||
private OnHeaderClickListener mOnHeaderClickListener;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mContext = new ActivityContextWrapper(getApplicationContext());
|
||||
mTestProfile = new InvariantDeviceProfile();
|
||||
mTestProfile.numRows = 5;
|
||||
mTestProfile.numColumns = 5;
|
||||
|
||||
doAnswer(invocation -> {
|
||||
ComponentWithLabel componentWithLabel = (ComponentWithLabel) invocation.getArgument(0);
|
||||
return componentWithLabel.getComponent().getShortClassName();
|
||||
}).when(mIconCache).getTitleNoCache(any());
|
||||
mViewHolderBinder = new WidgetsListSearchHeaderViewHolderBinder(
|
||||
LayoutInflater.from(mContext),
|
||||
mOnHeaderClickListener,
|
||||
new WidgetsListDrawableFactory(mContext));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindViewHolder_appWith3Widgets_shouldShowTheCorrectAppNameAndSubtitle() {
|
||||
WidgetsListSearchHeaderHolder viewHolder = mViewHolderBinder.newViewHolder(
|
||||
new FrameLayout(mContext));
|
||||
WidgetsListHeader widgetsListHeader = viewHolder.mWidgetsListHeader;
|
||||
WidgetsListSearchHeaderEntry entry = generateSampleSearchHeader(
|
||||
APP_NAME,
|
||||
TEST_PACKAGE,
|
||||
/* numOfWidgets= */ 3);
|
||||
mViewHolderBinder.bindViewHolder(viewHolder, entry, /* position= */ 0, EMPTY_LIST);
|
||||
|
||||
TextView appTitle = widgetsListHeader.findViewById(R.id.app_title);
|
||||
TextView appSubtitle = widgetsListHeader.findViewById(R.id.app_subtitle);
|
||||
assertThat(appTitle.getText()).isEqualTo(APP_NAME);
|
||||
assertThat(appSubtitle.getText())
|
||||
.isEqualTo(".SampleWidget0, .SampleWidget1, .SampleWidget2");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindViewHolder_shouldAttachOnHeaderClickListener() {
|
||||
WidgetsListSearchHeaderHolder viewHolder = mViewHolderBinder.newViewHolder(
|
||||
new FrameLayout(mContext));
|
||||
WidgetsListHeader widgetsListHeader = viewHolder.mWidgetsListHeader;
|
||||
WidgetsListSearchHeaderEntry entry = generateSampleSearchHeader(
|
||||
APP_NAME,
|
||||
TEST_PACKAGE,
|
||||
/* numOfWidgets= */ 3);
|
||||
|
||||
mViewHolderBinder.bindViewHolder(viewHolder, entry, /* position= */ 0, EMPTY_LIST);
|
||||
widgetsListHeader.callOnClick();
|
||||
|
||||
verify(mOnHeaderClickListener).onHeaderClicked(eq(true),
|
||||
eq(PackageUserKey.fromPackageItemInfo(entry.mPkgItem)));
|
||||
}
|
||||
|
||||
private WidgetsListSearchHeaderEntry generateSampleSearchHeader(String appName,
|
||||
String packageName, int numOfWidgets) {
|
||||
PackageItemInfo appInfo = new PackageItemInfo(packageName, UserHandle.CURRENT);
|
||||
appInfo.title = appName;
|
||||
appInfo.bitmap = BitmapInfo.of(Bitmap.createBitmap(10, 10, Bitmap.Config.ALPHA_8), 0);
|
||||
|
||||
return new WidgetsListSearchHeaderEntry(appInfo,
|
||||
/* titleSectionName= */ "",
|
||||
generateWidgetItems(packageName, numOfWidgets));
|
||||
}
|
||||
|
||||
private List<WidgetItem> generateWidgetItems(String packageName, int numOfWidgets) {
|
||||
ArrayList<WidgetItem> widgetItems = new ArrayList<>();
|
||||
for (int i = 0; i < numOfWidgets; i++) {
|
||||
ComponentName cn = ComponentName.createRelative(packageName, ".SampleWidget" + i);
|
||||
AppWidgetProviderInfo widgetInfo = WidgetUtils.createAppWidgetProviderInfo(cn);
|
||||
|
||||
widgetItems.add(new WidgetItem(
|
||||
LauncherAppWidgetProviderInfo.fromProviderInfo(mContext, widgetInfo),
|
||||
mTestProfile, mIconCache));
|
||||
}
|
||||
return widgetItems;
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,6 @@ import com.android.launcher3.widget.LauncherAppWidgetProviderInfo;
|
||||
import com.android.launcher3.widget.model.WidgetsListBaseEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListContentEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListHeaderEntry;
|
||||
import com.android.launcher3.widget.model.WidgetsListSearchHeaderEntry;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -117,12 +116,12 @@ public class SimpleWidgetsSearchAlgorithmTest {
|
||||
.getAllWidgets();
|
||||
|
||||
assertEquals(List.of(
|
||||
new WidgetsListSearchHeaderEntry(
|
||||
WidgetsListHeaderEntry.createForSearch(
|
||||
mCalendarHeaderEntry.mPkgItem,
|
||||
mCalendarHeaderEntry.mTitleSectionName,
|
||||
mCalendarHeaderEntry.mWidgets),
|
||||
mCalendarContentEntry,
|
||||
new WidgetsListSearchHeaderEntry(
|
||||
WidgetsListHeaderEntry.createForSearch(
|
||||
mCameraHeaderEntry.mPkgItem,
|
||||
mCameraHeaderEntry.mTitleSectionName,
|
||||
mCameraHeaderEntry.mWidgets),
|
||||
@@ -138,7 +137,7 @@ public class SimpleWidgetsSearchAlgorithmTest {
|
||||
.getAllWidgets();
|
||||
|
||||
assertEquals(List.of(
|
||||
new WidgetsListSearchHeaderEntry(
|
||||
WidgetsListHeaderEntry.createForSearch(
|
||||
mCalendarHeaderEntry.mPkgItem,
|
||||
mCalendarHeaderEntry.mTitleSectionName,
|
||||
mCalendarHeaderEntry.mWidgets.subList(1, 2)),
|
||||
@@ -146,7 +145,7 @@ public class SimpleWidgetsSearchAlgorithmTest {
|
||||
mCalendarHeaderEntry.mPkgItem,
|
||||
mCalendarHeaderEntry.mTitleSectionName,
|
||||
mCalendarHeaderEntry.mWidgets.subList(1, 2)),
|
||||
new WidgetsListSearchHeaderEntry(
|
||||
WidgetsListHeaderEntry.createForSearch(
|
||||
mCameraHeaderEntry.mPkgItem,
|
||||
mCameraHeaderEntry.mTitleSectionName,
|
||||
mCameraHeaderEntry.mWidgets.subList(1, 3)),
|
||||
@@ -175,7 +174,7 @@ public class SimpleWidgetsSearchAlgorithmTest {
|
||||
PackageItemInfo pInfo = createPackageItemInfo(packageName, appName,
|
||||
widgetItems.get(0).user);
|
||||
|
||||
return new WidgetsListHeaderEntry(pInfo, /* titleSectionName= */ "", widgetItems);
|
||||
return WidgetsListHeaderEntry.create(pInfo, /* titleSectionName= */ "", widgetItems);
|
||||
}
|
||||
|
||||
private WidgetsListContentEntry createWidgetsContentEntry(String packageName, String appName,
|
||||
|
||||
Reference in New Issue
Block a user