Skip to content

Commit 886ad90

Browse files
committed
Fix highlighting filtered items
Signed-off-by: Muntashir Al-Islam <muntashirakon@riseup.net>
1 parent 69b28cb commit 886ad90

16 files changed

Lines changed: 369 additions & 53 deletions

app/src/main/java/io/github/muntashirakon/AppManager/debloat/DebloaterActivity.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -103,7 +103,7 @@ protected void onAuthenticated(@Nullable Bundle savedInstanceState) {
103103

104104
viewModel.getDebloatObjectListLiveData().observe(this, debloatObjects -> {
105105
mProgressIndicator.hide();
106-
mAdapter.submitList(debloatObjects);
106+
mAdapter.setDefaultList(debloatObjects);
107107
});
108108
viewModel.loadPackages();
109109
}

app/src/main/java/io/github/muntashirakon/AppManager/debloat/DebloaterRecyclerViewAdapter.java

Lines changed: 43 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
package io.github.muntashirakon.AppManager.debloat;
44

55
import static io.github.muntashirakon.AppManager.utils.UIUtils.getColoredText;
6+
import static io.github.muntashirakon.util.AdapterUtils.PAYLOAD_HIGHLIGHT_CHANGED;
67

78
import android.content.Context;
89
import android.graphics.drawable.Drawable;
@@ -14,6 +15,7 @@
1415

1516
import androidx.annotation.ColorInt;
1617
import androidx.annotation.NonNull;
18+
import androidx.annotation.Nullable;
1719
import androidx.annotation.StringRes;
1820
import androidx.appcompat.widget.AppCompatImageView;
1921
import androidx.fragment.app.FragmentActivity;
@@ -24,9 +26,13 @@
2426
import com.google.android.material.color.MaterialColors;
2527
import com.google.android.material.textview.MaterialTextView;
2628

29+
import java.util.ArrayList;
30+
import java.util.List;
31+
import java.util.Locale;
2732
import java.util.Objects;
2833

2934
import io.github.muntashirakon.AppManager.R;
35+
import io.github.muntashirakon.AppManager.utils.UIUtils;
3036
import io.github.muntashirakon.AppManager.utils.appearance.ColorCodes;
3137
import io.github.muntashirakon.util.AccessibilityUtils;
3238
import io.github.muntashirakon.widget.MultiSelectionView;
@@ -43,10 +49,13 @@ public class DebloaterRecyclerViewAdapter extends MultiSelectionView.Adapter<Deb
4349
private final int mRemovalCautionColor;
4450
@ColorInt
4551
private final int mColorSurface;
52+
private final int mQueryStringHighlightColor;
4653
@NonNull
4754
private final DebloaterViewModel mViewModel;
4855
@NonNull
4956
private final Drawable mDefaultIcon;
57+
@Nullable
58+
private String mSearchQuery;
5059

5160
private static final DiffUtil.ItemCallback<DebloatObject> DIFF_CALLBACK = new DiffUtil.ItemCallback<DebloatObject>() {
5261
@Override
@@ -73,17 +82,49 @@ public DebloaterRecyclerViewAdapter(DebloaterActivity activity) {
7382
mRemovalUnsafeColor = ColorCodes.getRemovalUnsafeIndicatorColor(activity);
7483
mColorSurface = MaterialColors.getColor(activity, com.google.android.material.R.attr.colorSurface,
7584
DebloaterRecyclerViewAdapter.class.getCanonicalName());
85+
mQueryStringHighlightColor = ColorCodes.getQueryStringHighlightColor(activity);
7686
mViewModel = activity.viewModel;
7787
mDefaultIcon = activity.getPackageManager().getDefaultActivityIcon();
7888
}
7989

90+
public void setDefaultList(List<DebloatObject> debloatObjects) {
91+
String oldSearchQuery = mSearchQuery;
92+
mSearchQuery = mViewModel.getQueryString();
93+
if (mSearchQuery != null) {
94+
mSearchQuery = mSearchQuery.toLowerCase(Locale.ROOT);
95+
}
96+
submitList(new ArrayList<>(debloatObjects));
97+
if (!Objects.equals(oldSearchQuery, mSearchQuery)) {
98+
notifyItemRangeChanged(0, getItemCount(), PAYLOAD_HIGHLIGHT_CHANGED);
99+
}
100+
notifySelectionChange();
101+
}
102+
80103
@NonNull
81104
@Override
82105
public ViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
83106
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.item_debloater, parent, false);
84107
return new ViewHolder(v);
85108
}
86109

110+
@Override
111+
public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) {
112+
if (!payloads.isEmpty()) {
113+
for (Object payload : payloads) {
114+
if (Objects.equals(payload, PAYLOAD_HIGHLIGHT_CHANGED)) {
115+
updateTextHighlights(holder, getItem(position));
116+
}
117+
}
118+
}
119+
// Handle other stuff
120+
super.onBindViewHolder(holder, position, payloads);
121+
}
122+
123+
private void updateTextHighlights(@NonNull ViewHolder holder, @NonNull DebloatObject debloatObject) {
124+
holder.labelView.setText(UIUtils.getHighlightedText(debloatObject.getLabelOrPackageName().toString(), mSearchQuery, mQueryStringHighlightColor));
125+
holder.packageNameView.setText(UIUtils.getHighlightedText(debloatObject.packageName, mSearchQuery, mQueryStringHighlightColor));
126+
}
127+
87128
@Override
88129
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
89130
DebloatObject debloatObject = getItem(position);
@@ -117,13 +158,12 @@ public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
117158
if (!TextUtils.isEmpty(warning)) {
118159
sb.append(" — ").append(warning);
119160
}
120-
CharSequence label = debloatObject.getLabelOrPackageName();
121161
holder.iconView.setImageDrawable(icon);
122162
holder.listTypeView.setText(debloatObject.type);
123-
holder.packageNameView.setText(debloatObject.packageName);
163+
holder.labelView.setText(UIUtils.getHighlightedText(debloatObject.getLabelOrPackageName().toString(), mSearchQuery, mQueryStringHighlightColor));
164+
holder.packageNameView.setText(UIUtils.getHighlightedText(debloatObject.packageName, mSearchQuery, mQueryStringHighlightColor));
124165
holder.descriptionView.setText(sb);
125166
holder.itemView.setStrokeColor(removalColor);
126-
holder.labelView.setText(label);
127167
holder.itemView.setOnLongClickListener(v -> {
128168
int currentPos = holder.getBindingAdapterPosition();
129169
if (currentPos != RecyclerView.NO_POSITION) {

app/src/main/java/io/github/muntashirakon/AppManager/debloat/DebloaterViewModel.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,10 @@ public void setQuery(String queryString, @AdvancedSearchView.SearchType int sear
7070
loadPackages();
7171
}
7272

73+
public String getQueryString() {
74+
return mQueryString;
75+
}
76+
7377
public LiveData<List<DebloatObject>> getDebloatObjectListLiveData() {
7478
return mDebloatObjectListLiveData;
7579
}

app/src/main/java/io/github/muntashirakon/AppManager/details/AppDetailsComponentsFragment.java

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
package io.github.muntashirakon.AppManager.details;
44

5+
import static io.github.muntashirakon.util.AdapterUtils.PAYLOAD_HIGHLIGHT_CHANGED;
6+
57
import android.content.ComponentName;
68
import android.content.Intent;
79
import android.content.pm.ActivityInfo;
@@ -339,6 +341,7 @@ void setDefaultList(@NonNull List<AppDetailsItem<?>> list) {
339341
ThreadUtils.postOnBackgroundThread(() -> {
340342
mRequestedProperty = mNeededProperty;
341343
mCanStartAnyActivity = SelfPermissions.checkSelfOrRemotePermission(ManifestCompat.permission.START_ANY_ACTIVITY);
344+
String oldConstraint = mConstraint;
342345
if (viewModel != null) {
343346
mCanModifyComponentStates = !mIsExternalApk && SelfPermissions.canModifyAppComponentStates(mUserId, viewModel.getPackageName(), viewModel.isTestOnlyApp());
344347
mConstraint = viewModel.getSearchQuery();
@@ -356,6 +359,9 @@ void setDefaultList(@NonNull List<AppDetailsItem<?>> list) {
356359
if (isDetached()) return;
357360
ProgressIndicatorCompat.setVisibility(progressIndicator, false);
358361
submitList(items);
362+
if (!Objects.equals(oldConstraint, mConstraint)) {
363+
notifyItemRangeChanged(0, getItemCount(), PAYLOAD_HIGHLIGHT_CHANGED);
364+
}
359365
});
360366
});
361367
}
@@ -432,7 +438,31 @@ public AppDetailsRecyclerAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGrou
432438
}
433439

434440
@Override
435-
public void onBindViewHolder(@NonNull AppDetailsRecyclerAdapter.ViewHolder holder, int position) {
441+
public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) {
442+
if (!payloads.isEmpty()) {
443+
for (Object payload : payloads) {
444+
if (Objects.equals(payload, PAYLOAD_HIGHLIGHT_CHANGED)) {
445+
updateTextHighlights(holder, position);
446+
return;
447+
}
448+
}
449+
}
450+
super.onBindViewHolder(holder, position, payloads);
451+
}
452+
453+
public void updateTextHighlights(@NonNull ViewHolder holder, int position) {
454+
AppDetailsComponentItem item = getItem(position);
455+
if (mConstraint != null && item.name.toLowerCase(Locale.ROOT).contains(mConstraint)) {
456+
// Highlight searched query
457+
holder.nameView.setText(UIUtils.getHighlightedText(item.name, mConstraint, colorQueryStringHighlight));
458+
} else {
459+
holder.nameView.setText(item.name.startsWith(mPackageName) ?
460+
item.name.replaceFirst(mPackageName, "") : item.name);
461+
}
462+
}
463+
464+
@Override
465+
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
436466
if (mRequestedProperty == SERVICES) {
437467
getServicesView(holder, position);
438468
} else if (mRequestedProperty == RECEIVERS) {

app/src/main/java/io/github/muntashirakon/AppManager/details/AppDetailsOverlaysFragment.java

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
package io.github.muntashirakon.AppManager.details;
22

3+
import static io.github.muntashirakon.util.AdapterUtils.PAYLOAD_HIGHLIGHT_CHANGED;
4+
35
import android.content.om.IOverlayManager;
46
import android.graphics.Color;
57
import android.os.Build;
@@ -23,7 +25,6 @@
2325

2426
import java.util.ArrayList;
2527
import java.util.List;
26-
import java.util.Locale;
2728
import java.util.Objects;
2829

2930
import io.github.muntashirakon.AppManager.R;
@@ -169,6 +170,7 @@ class AppDetailsRecyclerAdapter extends RecyclerView.ListAdapter<AppDetailsOverl
169170
@UiThread
170171
void setDefaultList(List<AppDetailsItem<?>> list) {
171172
ThreadUtils.postOnBackgroundThread(() -> {
173+
String oldConstraint = mConstraint;
172174
mConstraint = viewModel == null ? null : viewModel.getSearchQuery();
173175
ArrayList<AppDetailsOverlayItem> items = new ArrayList<>(list.size());
174176
for (AppDetailsItem<?> item : list) {
@@ -178,6 +180,9 @@ void setDefaultList(List<AppDetailsItem<?>> list) {
178180
if (isDetached()) return;
179181
ProgressIndicatorCompat.setVisibility(progressIndicator, false);
180182
submitList(items);
183+
if (!Objects.equals(oldConstraint, mConstraint)) {
184+
notifyItemRangeChanged(0, getItemCount(), PAYLOAD_HIGHLIGHT_CHANGED);
185+
}
181186
});
182187
});
183188
}
@@ -191,16 +196,31 @@ public ViewHolder onCreateViewHolder(@NonNull ViewGroup viewGroup, int i) {
191196
);
192197
}
193198

199+
@Override
200+
public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) {
201+
if (!payloads.isEmpty()) {
202+
for (Object payload : payloads) {
203+
if (Objects.equals(payload, PAYLOAD_HIGHLIGHT_CHANGED)) {
204+
updateTextHighlights(holder, getItem(position));
205+
return;
206+
}
207+
}
208+
}
209+
super.onBindViewHolder(holder, position, payloads);
210+
}
211+
212+
private void updateTextHighlights(@NonNull ViewHolder holder, @NonNull AppDetailsOverlayItem item) {
213+
// Highlight searched query
214+
holder.overlayName.setText(UIUtils.getHighlightedText(item.name, mConstraint, colorQueryStringHighlight));
215+
}
216+
194217
@Override
195218
@RequiresApi(Build.VERSION_CODES.O)
196219
public void onBindViewHolder(@NonNull ViewHolder holder, int index) {
197220
AppDetailsOverlayItem overlayItem = getItem(index);
198221
String overlayName = overlayItem.name;
199-
200-
if (mConstraint != null && overlayName.toLowerCase(Locale.ROOT).contains(mConstraint)) {
201-
// Highlight searched query
202-
holder.overlayName.setText(UIUtils.getHighlightedText(overlayName, mConstraint, colorQueryStringHighlight));
203-
} else holder.overlayName.setText(overlayName);
222+
// Highlight searched query
223+
holder.overlayName.setText(UIUtils.getHighlightedText(overlayName, mConstraint, colorQueryStringHighlight));
204224
holder.packageName.setText(overlayItem.getPackageName());
205225
if (overlayItem.getCategory() != null) {
206226
holder.overlayCategory.setVisibility(View.VISIBLE);

app/src/main/java/io/github/muntashirakon/AppManager/details/AppDetailsPermissionsFragment.java

Lines changed: 60 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import static io.github.muntashirakon.AppManager.utils.PackageUtils.getAppOpModeNames;
66
import static io.github.muntashirakon.AppManager.utils.PackageUtils.getAppOpNames;
7+
import static io.github.muntashirakon.util.AdapterUtils.PAYLOAD_HIGHLIGHT_CHANGED;
78

89
import android.annotation.SuppressLint;
910
import android.content.Context;
@@ -412,6 +413,7 @@ class AppDetailsRecyclerAdapter extends RecyclerView.ListAdapter<AppDetailsItem<
412413
void setDefaultList(@NonNull List<AppDetailsItem<?>> list) {
413414
ThreadUtils.postOnBackgroundThread(() -> {
414415
int neededProperty = mNeededProperty;
416+
String oldConstraint = mConstraint;
415417
String query = viewModel == null ? null : viewModel.getSearchQuery();
416418
boolean canModify = SelfPermissions.canModifyAppOpMode();
417419
ThreadUtils.postOnMainThread(() -> {
@@ -421,6 +423,9 @@ void setDefaultList(@NonNull List<AppDetailsItem<?>> list) {
421423
mConstraint = query;
422424
mCanModifyAppOpMode = canModify;
423425
submitList(new ArrayList<>(list));
426+
if (!Objects.equals(oldConstraint, mConstraint)) {
427+
notifyItemRangeChanged(0, getItemCount(), PAYLOAD_HIGHLIGHT_CHANGED);
428+
}
424429
});
425430
});
426431
}
@@ -507,6 +512,58 @@ public AppDetailsRecyclerAdapter.ViewHolder onCreateViewHolder(@NonNull ViewGrou
507512
return new AppDetailsRecyclerAdapter.ViewHolder(view);
508513
}
509514

515+
@Override
516+
public void onBindViewHolder(@NonNull ViewHolder holder, int position, @NonNull List<Object> payloads) {
517+
if (!payloads.isEmpty()) {
518+
for (Object payload : payloads) {
519+
if (Objects.equals(payload, PAYLOAD_HIGHLIGHT_CHANGED)) {
520+
updateTextHighlights(holder, position);
521+
return;
522+
}
523+
}
524+
}
525+
super.onBindViewHolder(holder, position, payloads);
526+
}
527+
528+
public void updateTextHighlights(@NonNull AppDetailsRecyclerAdapter.ViewHolder holder, int position) {
529+
switch (mRequestedProperty) {
530+
case APP_OPS: {
531+
AppDetailsAppOpItem item = (AppDetailsAppOpItem) getItem(position);
532+
// Set op name
533+
SpannableStringBuilder opName = new SpannableStringBuilder(item.getOp() + " - ");
534+
if (item.name.equals(String.valueOf(item.getOp()))) {
535+
opName.append(getString(R.string.unknown_op));
536+
} else {
537+
// Highlight searched query
538+
opName.append(UIUtils.getHighlightedText(item.name, mConstraint, colorQueryStringHighlight));
539+
}
540+
holder.textView1.setText(opName);
541+
break;
542+
}
543+
case USES_PERMISSIONS: {
544+
AppDetailsPermissionItem item = (AppDetailsPermissionItem) getItem(position);
545+
holder.textView1.setText(UIUtils.getHighlightedText(item.name, mConstraint, colorQueryStringHighlight));
546+
break;
547+
}
548+
case PERMISSIONS: {
549+
AppDetailsDefinedPermissionItem permissionItem = (AppDetailsDefinedPermissionItem) getItem(position);
550+
PermissionInfo permissionInfo = permissionItem.item;
551+
// Name
552+
if (mConstraint != null && permissionInfo.name.toLowerCase(Locale.ROOT).contains(mConstraint)) {
553+
// Highlight searched query
554+
holder.textView2.setText(UIUtils.getHighlightedText(permissionInfo.name, mConstraint, colorQueryStringHighlight));
555+
} else {
556+
holder.textView2.setText(permissionInfo.name.startsWith(mPackageName) ?
557+
permissionInfo.name.replaceFirst(mPackageName, "") : permissionInfo.name);
558+
}
559+
break;
560+
}
561+
default:
562+
break;
563+
}
564+
}
565+
566+
510567
@Override
511568
public void onBindViewHolder(@NonNull AppDetailsRecyclerAdapter.ViewHolder holder, int position) {
512569
Context context = holder.itemView.getContext();
@@ -533,10 +590,10 @@ private void getAppOpsView(@NonNull Context context, @NonNull ViewHolder holder,
533590
SpannableStringBuilder opName = new SpannableStringBuilder(item.getOp() + " - ");
534591
if (item.name.equals(String.valueOf(item.getOp()))) {
535592
opName.append(getString(R.string.unknown_op));
536-
} else if (mConstraint != null && opStr.toLowerCase(Locale.ROOT).contains(mConstraint)) {
593+
} else {
537594
// Highlight searched query
538595
opName.append(UIUtils.getHighlightedText(opStr, mConstraint, colorQueryStringHighlight));
539-
} else opName.append(opStr);
596+
}
540597
holder.textView1.setText(opName);
541598
// Set op mode, running and duration
542599
StringBuilder opRunningInfo = new StringBuilder()
@@ -669,10 +726,7 @@ private void getUsesPermissionsView(@NonNull Context context, @NonNull ViewHolde
669726
@NonNull PermissionInfo permissionInfo = permissionItem.item;
670727
final String permName = permissionInfo.name;
671728
// Set permission name
672-
if (mConstraint != null && permName.toLowerCase(Locale.ROOT).contains(mConstraint)) {
673-
// Highlight searched query
674-
holder.textView1.setText(UIUtils.getHighlightedText(permName, mConstraint, colorQueryStringHighlight));
675-
} else holder.textView1.setText(permName);
729+
holder.textView1.setText(UIUtils.getHighlightedText(permName, mConstraint, colorQueryStringHighlight));
676730
// Set others
677731
// Description
678732
CharSequence description = permissionInfo.loadDescription(packageManager);

0 commit comments

Comments
 (0)