Use our own existing implementation

This commit is contained in:
topjohnwu 2019-03-13 01:37:35 -04:00
parent 217564963d
commit 1e24c72c11
5 changed files with 268 additions and 344 deletions

View File

@ -29,7 +29,6 @@ dependencies {
implementation 'com.caverock:androidsvg-aar:1.3' implementation 'com.caverock:androidsvg-aar:1.3'
implementation 'org.kamranzafar:jtar:2.3' implementation 'org.kamranzafar:jtar:2.3'
implementation 'net.sourceforge.streamsupport:android-retrostreams:1.7.0' implementation 'net.sourceforge.streamsupport:android-retrostreams:1.7.0'
implementation 'me.drakeet.multitype:multitype:3.5.0'
implementation 'com.github.sevar83:indeterminate-checkbox:1.0.5' implementation 'com.github.sevar83:indeterminate-checkbox:1.0.5'
def androidXVersion = "1.0.0" def androidXVersion = "1.0.0"

View File

@ -1,170 +0,0 @@
package com.topjohnwu.magisk.adapters;
import android.content.res.Resources;
import android.graphics.drawable.Drawable;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import com.buildware.widget.indeterm.IndeterminateCheckBox;
import com.topjohnwu.magisk.R;
import com.topjohnwu.superuser.Shell;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import butterknife.BindView;
import java9.util.Comparators;
import me.drakeet.multitype.ItemViewBinder;
public class AppViewBinder extends ItemViewBinder<AppViewBinder.App, AppViewBinder.ViewHolder> {
private final List<Object> items;
AppViewBinder(List<Object> items) {
this.items = items;
}
@Override
protected @NonNull
ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {
return new ViewHolder(inflater.inflate(R.layout.list_item_hide_app, parent, false));
}
@Override
protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull App app) {
IndeterminateCheckBox.OnStateChangedListener listener =
(IndeterminateCheckBox indeterminateCheckBox, @Nullable Boolean stat) -> {
if (stat != null && stat) {
for (ProcessViewBinder.Process process : app.processes) {
Shell.su("magiskhide --add " + process.fullname).submit();
process.hidden = true;
}
} else if (stat != null) {
for (ProcessViewBinder.Process process : app.processes) {
Shell.su("magiskhide --rm " + process.fullname).submit();
process.hidden = false;
}
}
app.getStatBool(true);
};
holder.app_name.setText(app.name);
holder.app_icon.setImageDrawable(app.icon);
holder.package_name.setText(app.packageName);
holder.checkBox.setOnStateChangedListener(null);
holder.checkBox.setState(app.getStatBool(false));
holder.checkBox.setOnStateChangedListener(listener);
if (app.expand) {
holder.checkBox.setVisibility(View.GONE);
setBottomMargin(holder.itemView, 0);
} else {
holder.checkBox.setVisibility(View.VISIBLE);
setBottomMargin(holder.itemView, 2);
}
holder.itemView.setOnClickListener((v) -> {
int index = getPosition(holder);
if (app.expand) {
app.expand = false;
items.removeAll(app.processes);
getAdapter().notifyItemRangeRemoved(index + 1, app.processes.size());
setBottomMargin(holder.itemView, 2);
holder.checkBox.setOnStateChangedListener(null);
holder.checkBox.setVisibility(View.VISIBLE);
holder.checkBox.setState(app.getStatBool(true));
holder.checkBox.setOnStateChangedListener(listener);
} else {
holder.checkBox.setVisibility(View.GONE);
setBottomMargin(holder.itemView, 0);
app.expand = true;
items.addAll(index + 1, app.processes);
getAdapter().notifyItemRangeInserted(index + 1, app.processes.size());
}
});
}
private void setBottomMargin(View view, int dp) {
ViewGroup.LayoutParams params = view.getLayoutParams();
ViewGroup.MarginLayoutParams marginParams;
if (params instanceof ViewGroup.MarginLayoutParams) {
marginParams = (ViewGroup.MarginLayoutParams) params;
} else {
marginParams = new ViewGroup.MarginLayoutParams(params);
}
int px = (int) (0.5f + dp * Resources.getSystem().getDisplayMetrics().density);
marginParams.bottomMargin = px;
view.setLayoutParams(marginParams);
}
static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.app_icon) ImageView app_icon;
@BindView(R.id.app_name) TextView app_name;
@BindView(R.id.package_name) TextView package_name;
@BindView(R.id.checkbox) IndeterminateCheckBox checkBox;
ViewHolder(View itemView) {
super(itemView);
new AppViewBinder$ViewHolder_ViewBinding(this, itemView);
}
}
public static class App implements Comparable<App> {
Drawable icon;
String name;
String packageName;
int flags;
List<ProcessViewBinder.Process> processes;
boolean expand = false;
int stat = -1;
App(Drawable icon, String name, String packageName, int flags) {
this.icon = icon;
this.name = name;
this.packageName = packageName;
this.flags=flags;
this.processes = new ArrayList<>();
}
int getStat(boolean update) {
if (stat > 1 && !update) return stat;
int n = 0;
for (ProcessViewBinder.Process process : processes) {
if (process.hidden) n++;
}
if (n == processes.size()) stat = 2;
else if (n > 0) stat = 1;
else stat = 0;
return stat;
}
Boolean getStatBool(boolean update) {
int stat = getStat(update);
switch (stat) {
case 2:
return true;
case 1:
return null;
case 0:
default:
return false;
}
}
@Override
public int compareTo(App o) {
Comparator<App> c;
c = Comparators.comparing((App t) -> t.stat);
c = Comparators.reversed(c);
c = Comparators.thenComparing(c, t -> t.name, String::compareToIgnoreCase);
return c.compare(this, o);
}
}
}

View File

@ -6,31 +6,43 @@ import android.content.pm.ComponentInfo;
import android.content.pm.PackageInfo; import android.content.pm.PackageInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.WorkerThread; import androidx.annotation.WorkerThread;
import androidx.collection.ArraySet; import androidx.collection.ArraySet;
import androidx.recyclerview.widget.RecyclerView;
import com.buildware.widget.indeterm.IndeterminateCheckBox;
import com.topjohnwu.magisk.App; import com.topjohnwu.magisk.App;
import com.topjohnwu.magisk.Config; import com.topjohnwu.magisk.Config;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Topic; import com.topjohnwu.magisk.utils.Topic;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell; import com.topjohnwu.superuser.Shell;
import com.topjohnwu.superuser.internal.UiThreadHandler; import com.topjohnwu.superuser.internal.UiThreadHandler;
import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.Comparator;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import butterknife.BindView;
import java9.util.Comparators;
import java9.util.Objects;
import java9.util.stream.Collectors; import java9.util.stream.Collectors;
import java9.util.stream.Stream; import java9.util.stream.Stream;
import java9.util.stream.StreamSupport; import java9.util.stream.StreamSupport;
import me.drakeet.multitype.MultiTypeAdapter;
import static com.topjohnwu.magisk.utils.Utils.getAppLabel; public class ApplicationAdapter extends SectionedAdapter
<ApplicationAdapter.AppViewHolder, ApplicationAdapter.ProcessViewHolder> {
public class ApplicationAdapter {
/* A list of apps that should not be shown as hide-able */ /* A list of apps that should not be shown as hide-able */
private static final List<String> HIDE_BLACKLIST = Arrays.asList( private static final List<String> HIDE_BLACKLIST = Arrays.asList(
@ -46,24 +58,137 @@ public class ApplicationAdapter {
private static final String SAFETYNET_PROCESS = "com.google.android.gms.unstable"; private static final String SAFETYNET_PROCESS = "com.google.android.gms.unstable";
private static final String GMS_PACKAGE = "com.google.android.gms"; private static final String GMS_PACKAGE = "com.google.android.gms";
private List<AppViewBinder.App> fullList; private List<HideAppInfo> fullList, showList;
private List<HideTarget> hideList; private List<HideTarget> hideList;
private List<Object> showList;
private MultiTypeAdapter adapter;
private PackageManager pm; private PackageManager pm;
private boolean showSystem; private boolean showSystem;
public ApplicationAdapter(Context context, MultiTypeAdapter adapter) { public ApplicationAdapter(Context context) {
fullList = showList = Collections.emptyList();
hideList = Collections.emptyList(); hideList = Collections.emptyList();
fullList = new ArrayList<>();
showList = new ArrayList<>();
this.adapter = adapter;
this.adapter.setItems(showList);
pm = context.getPackageManager(); pm = context.getPackageManager();
showSystem = Config.get(Config.Key.SHOW_SYSTEM_APP); showSystem = Config.get(Config.Key.SHOW_SYSTEM_APP);
AsyncTask.SERIAL_EXECUTOR.execute(this::loadApps); AsyncTask.SERIAL_EXECUTOR.execute(this::loadApps);
adapter.register(AppViewBinder.App.class, new AppViewBinder(showList)); }
adapter.register(ProcessViewBinder.Process.class, new ProcessViewBinder());
@Override
public int getSectionCount() {
return showList.size();
}
@Override
public int getItemCount(int section) {
return showList.get(section).expanded ? showList.get(section).processes.size() : 0;
}
@Override
public AppViewHolder onCreateSectionViewHolder(ViewGroup parent) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_hide_app, parent, false);
return new AppViewHolder(v);
}
@Override
public ProcessViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_hide_process, parent, false);
return new ProcessViewHolder(v);
}
@Override
public void onBindSectionViewHolder(AppViewHolder holder, int section) {
HideAppInfo app = showList.get(section);
IndeterminateCheckBox.OnStateChangedListener listener =
(IndeterminateCheckBox indeterminateCheckBox, @Nullable Boolean stat) -> {
if (stat != null) {
for (HideProcessInfo p : app.processes) {
String cmd = Utils.fmt("magiskhide --%s %s %s",
stat ? "add" : "rm", app.info.packageName, p.name);
Shell.su(cmd).submit();
p.hidden = stat;
}
}
};
holder.app_name.setText(app.name);
holder.app_icon.setImageDrawable(app.info.loadIcon(pm));
holder.package_name.setText(app.info.packageName);
holder.checkBox.setOnStateChangedListener(null);
holder.checkBox.setOnStateChangedListener(listener);
holder.checkBox.setState(app.getState());
if (app.expanded) {
holder.checkBox.setVisibility(View.GONE);
setBottomMargin(holder.itemView, 0);
} else {
holder.checkBox.setVisibility(View.VISIBLE);
setBottomMargin(holder.itemView, 2);
}
holder.itemView.setOnClickListener((v) -> {
int index = getItemPosition(section, 0);
if (app.expanded) {
app.expanded = false;
notifyItemRangeRemoved(index, app.processes.size());
setBottomMargin(holder.itemView, 2);
holder.checkBox.setOnStateChangedListener(null);
holder.checkBox.setVisibility(View.VISIBLE);
holder.checkBox.setState(app.getState());
holder.checkBox.setOnStateChangedListener(listener);
} else {
holder.checkBox.setVisibility(View.GONE);
setBottomMargin(holder.itemView, 0);
app.expanded = true;
notifyItemRangeInserted(index, app.processes.size());
}
});
}
@Override
public void onBindItemViewHolder(ProcessViewHolder holder, int section, int position) {
HideAppInfo hideApp = showList.get(section);
HideProcessInfo target = hideApp.processes.get(position);
holder.process.setText(target.name);
holder.checkbox.setOnCheckedChangeListener(null);
holder.checkbox.setChecked(target.hidden);
holder.checkbox.setOnCheckedChangeListener((v, isChecked) -> {
String pair = Utils.fmt("%s %s", hideApp.info.packageName, target.name);
if (isChecked) {
Shell.su("magiskhide --add " + pair).submit();
target.hidden = true;
} else {
Shell.su("magiskhide --rm " + pair).submit();
target.hidden = false;
}
});
}
public void filter(String constraint) {
AsyncTask.SERIAL_EXECUTOR.execute(() -> {
Stream<HideAppInfo> s = StreamSupport.stream(fullList)
.filter(this::systemFilter)
.filter(t -> nameFilter(t, constraint));
UiThreadHandler.run(() -> {
showList = s.collect(Collectors.toList());
notifyDataSetChanged();
});
});
}
public void setShowSystem(boolean b) {
showSystem = b;
}
public void refresh() {
AsyncTask.SERIAL_EXECUTOR.execute(this::loadApps);
}
private void setBottomMargin(View view, int dp) {
ViewGroup.LayoutParams params = view.getLayoutParams();
ViewGroup.MarginLayoutParams marginParams;
if (params instanceof ViewGroup.MarginLayoutParams) {
marginParams = (ViewGroup.MarginLayoutParams) params;
} else {
marginParams = new ViewGroup.MarginLayoutParams(params);
}
marginParams.bottomMargin = Utils.dpInPx(dp);
view.setLayoutParams(marginParams);
} }
private void addProcesses(Set<String> set, ComponentInfo[] infos) { private void addProcesses(Set<String> set, ComponentInfo[] infos) {
@ -93,93 +218,120 @@ public class ApplicationAdapter {
@WorkerThread @WorkerThread
private void loadApps() { private void loadApps() {
List<ApplicationInfo> installed = pm.getInstalledApplications(0);
hideList = StreamSupport.stream(Shell.su("magiskhide --ls").exec().getOut()) hideList = StreamSupport.stream(Shell.su("magiskhide --ls").exec().getOut())
.map(HideTarget::new).collect(Collectors.toList()); .map(HideTarget::new)
.collect(Collectors.toList());
fullList.clear(); fullList = StreamSupport.stream(pm.getInstalledApplications(0))
.filter(info -> !HIDE_BLACKLIST.contains(info.packageName) && info.enabled)
for (ApplicationInfo info : installed) { .map(info -> {
// Do not show black-listed and disabled apps Set<String> set = new ArraySet<>();
if (!HIDE_BLACKLIST.contains(info.packageName) && info.enabled) { PackageInfo pkg = getPackageInfo(info.packageName);
AppViewBinder.App app = new AppViewBinder.App(info.loadIcon(pm), if (pkg != null) {
getAppLabel(info, pm), info.packageName, info.flags); addProcesses(set, pkg.activities);
fullList.add(app); addProcesses(set, pkg.services);
addProcesses(set, pkg.receivers);
Set<String> set = new ArraySet<>(); addProcesses(set, pkg.providers);
PackageInfo pkg = getPackageInfo(info.packageName);
if (pkg != null) {
addProcesses(set, pkg.activities);
addProcesses(set, pkg.services);
addProcesses(set, pkg.receivers);
addProcesses(set, pkg.providers);
} else {
set.add(info.packageName);
}
if (set.isEmpty()) fullList.remove(app);
for (String proc : set) {
boolean hidden = false;
for (HideTarget tgt : hideList) {
if (info.packageName.equals(tgt.pkg) && proc.equals(tgt.process))
hidden = true;
} }
app.processes.add(new ProcessViewBinder.Process(proc, hidden, info.packageName)); if (set.isEmpty())
} return null;
app.getStat(true); return new HideAppInfo(info, set);
Collections.sort(app.processes); }).filter(Objects::nonNull).sorted()
} .collect(Collectors.toList());
}
Collections.sort(fullList);
Topic.publish(false, Topic.MAGISK_HIDE_DONE); Topic.publish(false, Topic.MAGISK_HIDE_DONE);
} }
public void setShowSystem(boolean b) { // True if not system app or user already hidden it
showSystem = b; private boolean systemFilter(HideAppInfo target) {
} return showSystem || target.haveHidden() ||
(target.info.flags & ApplicationInfo.FLAG_SYSTEM) == 0;
// True if not system app and have launch intent, or user already hidden it
private boolean systemFilter(AppViewBinder.App target) {
return showSystem || target.stat != 0 ||
((target.flags & ApplicationInfo.FLAG_SYSTEM) == 0 &&
pm.getLaunchIntentForPackage(target.packageName) != null);
} }
private boolean contains(String s, String filter) { private boolean contains(String s, String filter) {
return s.toLowerCase().contains(filter); return s.toLowerCase().contains(filter);
} }
private boolean nameFilter(AppViewBinder.App target, String filter) { private boolean nameFilter(HideAppInfo target, String filter) {
if (filter == null || filter.isEmpty()) if (filter == null || filter.isEmpty())
return true; return true;
filter = filter.toLowerCase(); filter = filter.toLowerCase();
return contains(target.name, filter) || if (contains(target.name, filter))
contains(target.packageName, filter); return true;
for (HideProcessInfo p : target.processes) {
if (contains(p.name, filter))
return true;
}
return contains(target.info.packageName, filter);
} }
public void filter(String constraint) { class HideAppInfo implements Comparable<HideAppInfo> {
AsyncTask.SERIAL_EXECUTOR.execute(() -> { String name;
Stream<AppViewBinder.App> s = StreamSupport.stream(fullList) ApplicationInfo info;
.filter(this::systemFilter) List<HideProcessInfo> processes;
.filter(t -> nameFilter(t, constraint)); boolean expanded;
UiThreadHandler.run(() -> {
showList.clear(); HideAppInfo(ApplicationInfo appInfo, Set<String> set) {
for (AppViewBinder.App target : s.collect(Collectors.toList())) { info = appInfo;
if (target.expand) { name = Utils.getAppLabel(info, pm);
showList.add(target); expanded = false;
showList.addAll(target.processes); processes = StreamSupport.stream(set)
} else showList.add(target); .map(process -> new HideProcessInfo(info.packageName, process))
.sorted().collect(Collectors.toList());
}
@Override
public int compareTo(HideAppInfo o) {
Comparator<HideAppInfo> c;
c = Comparators.comparing(HideAppInfo::haveHidden);
c = Comparators.reversed(c);
c = Comparators.thenComparing(c, t -> t.name, String::compareToIgnoreCase);
c = Comparators.thenComparing(c, t -> t.info.packageName);
return c.compare(this, o);
}
Boolean getState() {
boolean all = true;
boolean hidden = false;
for (HideProcessInfo p : processes) {
if (!p.hidden)
all = false;
else
hidden = true;
}
if (all)
return true;
return hidden ? null : false;
}
boolean haveHidden() {
Boolean c = getState();
return c == null ? true : c;
}
}
class HideProcessInfo implements Comparable<HideProcessInfo> {
String name;
boolean hidden;
HideProcessInfo(String pkg, String process) {
this.name = process;
for (HideTarget t : hideList) {
if (t.pkg.equals(pkg) && t.process.equals(process)) {
hidden = true;
break;
} }
adapter.notifyDataSetChanged(); }
}); }
});
}
public void refresh() { @Override
Collections.sort(fullList); public int compareTo(HideProcessInfo o) {
Topic.publish(false, Topic.MAGISK_HIDE_DONE); Comparator<HideProcessInfo> c;
c = Comparators.comparing((HideProcessInfo t) -> t.hidden);
c = Comparators.reversed(c);
c = Comparators.thenComparing(c, t -> t.name);
return c.compare(this, o);
}
} }
class HideTarget { class HideTarget {
@ -197,4 +349,29 @@ public class ApplicationAdapter {
} }
} }
} }
class AppViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.app_icon) ImageView app_icon;
@BindView(R.id.app_name) TextView app_name;
@BindView(R.id.package_name) TextView package_name;
@BindView(R.id.checkbox) IndeterminateCheckBox checkBox;
public AppViewHolder(@NonNull View itemView) {
super(itemView);
new ApplicationAdapter$AppViewHolder_ViewBinding(this, itemView);
}
}
class ProcessViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.process) TextView process;
@BindView(R.id.checkbox) CheckBox checkbox;
public ProcessViewHolder(@NonNull View itemView) {
super(itemView);
new ApplicationAdapter$ProcessViewHolder_ViewBinding(this, itemView);
}
}
} }

View File

@ -1,80 +0,0 @@
package com.topjohnwu.magisk.adapters;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.utils.Utils;
import com.topjohnwu.superuser.Shell;
import java.util.Comparator;
import butterknife.BindView;
import java9.util.Comparators;
import me.drakeet.multitype.ItemViewBinder;
public class ProcessViewBinder extends ItemViewBinder<ProcessViewBinder.Process, ProcessViewBinder.ViewHolder> {
@Override
protected @NonNull
ViewHolder onCreateViewHolder(@NonNull LayoutInflater inflater, @NonNull ViewGroup parent) {
return new ViewHolder(inflater.inflate(R.layout.list_item_hide_process, parent, false));
}
@Override
protected void onBindViewHolder(@NonNull ViewHolder holder, @NonNull Process process) {
holder.process.setText(process.name);
holder.checkbox.setOnCheckedChangeListener(null);
holder.checkbox.setChecked(process.hidden);
holder.checkbox.setOnCheckedChangeListener((v, isChecked) -> {
if (isChecked) {
Shell.su("magiskhide --add " + process.fullname).submit();
process.hidden = true;
} else {
Shell.su("magiskhide --rm " + process.fullname).submit();
process.hidden = false;
}
});
}
static class ViewHolder extends RecyclerView.ViewHolder {
@BindView(R.id.process) TextView process;
@BindView(R.id.checkbox) CheckBox checkbox;
ViewHolder(View itemView) {
super(itemView);
new ProcessViewBinder$ViewHolder_ViewBinding(this, itemView);
}
}
public static class Process implements Comparable<Process> {
String name;
boolean hidden;
String fullname;
String packageName;
Process(String name, boolean hidden, String packageName) {
this.name = name;
this.hidden = hidden;
this.packageName=packageName;
this.fullname = Utils.fmt("%s %s", packageName, name);
}
@Override
public int compareTo(Process o) {
Comparator<Process> c;
c = Comparators.comparing((Process t) -> !t.name.startsWith(t.packageName));
c = Comparators.thenComparing(c, t -> t.name, String::compareToIgnoreCase);
return c.compare(this, o);
}
}
}

View File

@ -21,7 +21,6 @@ import com.topjohnwu.magisk.components.BaseFragment;
import com.topjohnwu.magisk.utils.Topic; import com.topjohnwu.magisk.utils.Topic;
import butterknife.BindView; import butterknife.BindView;
import me.drakeet.multitype.MultiTypeAdapter;
public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber { public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber {
@ -29,7 +28,7 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
@BindView(R.id.recyclerView) RecyclerView recyclerView; @BindView(R.id.recyclerView) RecyclerView recyclerView;
private SearchView search; private SearchView search;
private ApplicationAdapter applicationAdapter; private ApplicationAdapter adapter;
private SearchView.OnQueryTextListener searchListener; private SearchView.OnQueryTextListener searchListener;
@Override @Override
@ -44,23 +43,22 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false); View view = inflater.inflate(R.layout.fragment_magisk_hide, container, false);
unbinder = new MagiskHideFragment_ViewBinding(this, view); unbinder = new MagiskHideFragment_ViewBinding(this, view);
MultiTypeAdapter adapter = new MultiTypeAdapter(); adapter = new ApplicationAdapter(requireActivity());
applicationAdapter = new ApplicationAdapter(requireActivity(), adapter);
recyclerView.setAdapter(adapter); recyclerView.setAdapter(adapter);
mSwipeRefreshLayout.setRefreshing(true); mSwipeRefreshLayout.setRefreshing(true);
mSwipeRefreshLayout.setOnRefreshListener(applicationAdapter::refresh); mSwipeRefreshLayout.setOnRefreshListener(adapter::refresh);
searchListener = new SearchView.OnQueryTextListener() { searchListener = new SearchView.OnQueryTextListener() {
@Override @Override
public boolean onQueryTextSubmit(String query) { public boolean onQueryTextSubmit(String query) {
applicationAdapter.filter(query); adapter.filter(query);
return false; return false;
} }
@Override @Override
public boolean onQueryTextChange(String newText) { public boolean onQueryTextChange(String newText) {
applicationAdapter.filter(newText); adapter.filter(newText);
return false; return false;
} }
}; };
@ -84,8 +82,8 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
boolean showSystem = !item.isChecked(); boolean showSystem = !item.isChecked();
item.setChecked(showSystem); item.setChecked(showSystem);
Config.set(Config.Key.SHOW_SYSTEM_APP, showSystem); Config.set(Config.Key.SHOW_SYSTEM_APP, showSystem);
applicationAdapter.setShowSystem(showSystem); adapter.setShowSystem(showSystem);
applicationAdapter.filter(search.getQuery().toString()); adapter.filter(search.getQuery().toString());
} }
return true; return true;
} }
@ -98,6 +96,6 @@ public class MagiskHideFragment extends BaseFragment implements Topic.Subscriber
@Override @Override
public void onPublish(int topic, Object[] result) { public void onPublish(int topic, Object[] result) {
mSwipeRefreshLayout.setRefreshing(false); mSwipeRefreshLayout.setRefreshing(false);
applicationAdapter.filter(search.getQuery().toString()); adapter.filter(search.getQuery().toString());
} }
} }