diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 0016b94f..89011554 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -22,9 +22,6 @@ - diff --git a/app/src/main/java/org/meowcat/edxposed/manager/BlackListActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/BlackListActivity.java index bc1e3337..52a7def1 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/BlackListActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/BlackListActivity.java @@ -19,11 +19,12 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder; import org.meowcat.edxposed.manager.adapters.AppAdapter; import org.meowcat.edxposed.manager.adapters.AppHelper; import org.meowcat.edxposed.manager.adapters.BlackListAdapter; +import org.meowcat.edxposed.manager.adapters.CompatListAdapter; import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding; public class BlackListActivity extends BaseActivity implements AppAdapter.Callback { private SearchView searchView; - private BlackListAdapter appAdapter; + private AppAdapter appAdapter; private SearchView.OnQueryTextListener searchListener; private ActivityBlackListBinding binding; @@ -34,10 +35,12 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba } }; private Handler handler = new Handler(); + private boolean isCompat; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); + isCompat = getIntent().getBooleanExtra("compat_list", false); binding = ActivityBlackListBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); @@ -47,10 +50,11 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba bar.setDisplayHomeAsUpEnabled(true); } setupWindowInsets(binding.snackbar, binding.recyclerView); - binding.recyclerView.setLayoutManager(new LinearLayoutManager(this)); final boolean isWhiteListMode = isWhiteListMode(); - appAdapter = new BlackListAdapter(this, isWhiteListMode, binding); + appAdapter = isCompat ? new CompatListAdapter(this, binding) : new BlackListAdapter(this, isWhiteListMode, binding); + appAdapter.setHasStableIds(true); binding.recyclerView.setAdapter(appAdapter); + binding.recyclerView.setLayoutManager(new LinearLayoutManager(this)); if (!XposedApp.getPreferences().getBoolean("md2", false)) { DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, DividerItemDecoration.VERTICAL); @@ -60,7 +64,6 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba handler.postDelayed(runnable, 300); binding.swipeRefreshLayout.setOnRefreshListener(appAdapter::refresh); - searchListener = new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { @@ -87,7 +90,7 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba @Override public void onResume() { super.onResume(); - if (!AppHelper.isBlackListMode()) { + if (!isCompat && !AppHelper.isBlackListMode()) { new MaterialAlertDialogBuilder(this) .setMessage(R.string.warning_list_not_enabled) .setPositiveButton(R.string.Settings, (dialog, which) -> { @@ -104,7 +107,9 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba private void changeTitle(boolean isBlackListMode, boolean isWhiteListMode) { - if (isBlackListMode) { + if (isCompat) { + setTitle(R.string.nav_title_compat_list); + } else if (isBlackListMode) { setTitle(isWhiteListMode ? R.string.title_white_list : R.string.title_black_list); } else { setTitle(R.string.nav_title_black_list); @@ -124,12 +129,16 @@ public class BlackListActivity extends BaseActivity implements AppAdapter.Callba handler.removeCallbacks(runnable); binding.swipeRefreshLayout.setRefreshing(false); String queryStr = searchView != null ? searchView.getQuery().toString() : ""; - appAdapter.filter(queryStr); + runOnUiThread(new Runnable() { + @Override + public void run() { + appAdapter.getFilter().filter(queryStr); + } + }); } @Override public void onItemClick(View v, ApplicationInfo info) { - getSupportFragmentManager(); AppHelper.showMenu(this, getSupportFragmentManager(), v, info); } diff --git a/app/src/main/java/org/meowcat/edxposed/manager/CompatListActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/CompatListActivity.java deleted file mode 100644 index 5dcf221f..00000000 --- a/app/src/main/java/org/meowcat/edxposed/manager/CompatListActivity.java +++ /dev/null @@ -1,102 +0,0 @@ -package org.meowcat.edxposed.manager; - -import android.content.pm.ApplicationInfo; -import android.os.Bundle; -import android.view.Menu; -import android.view.View; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; -import androidx.appcompat.app.ActionBar; -import androidx.appcompat.widget.SearchView; -import androidx.recyclerview.widget.DividerItemDecoration; -import androidx.recyclerview.widget.LinearLayoutManager; - -import org.meowcat.edxposed.manager.adapters.AppAdapter; -import org.meowcat.edxposed.manager.adapters.AppHelper; -import org.meowcat.edxposed.manager.adapters.CompatListAdapter; -import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding; - -public class CompatListActivity extends BaseActivity implements AppAdapter.Callback { - - private SearchView searchView; - private CompatListAdapter appAdapter; - - private SearchView.OnQueryTextListener searchListener; - private ActivityBlackListBinding binding; - - @Override - public void onCreate(@Nullable Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - binding = ActivityBlackListBinding.inflate(getLayoutInflater()); - setContentView(binding.getRoot()); - setSupportActionBar(binding.toolbar); - binding.toolbar.setNavigationOnClickListener(view -> finish()); - ActionBar bar = getSupportActionBar(); - if (bar != null) { - bar.setDisplayHomeAsUpEnabled(true); - } - setupWindowInsets(binding.snackbar, binding.recyclerView); - binding.recyclerView.setLayoutManager(new LinearLayoutManager(this)); - appAdapter = new CompatListAdapter(this, binding); - binding.recyclerView.setAdapter(appAdapter); - if (!XposedApp.getPreferences().getBoolean("md2", false)) { - DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(this, - DividerItemDecoration.VERTICAL); - binding.recyclerView.addItemDecoration(dividerItemDecoration); - } - appAdapter.setCallback(this); - - binding.swipeRefreshLayout.setRefreshing(true); - binding.swipeRefreshLayout.setOnRefreshListener(appAdapter::refresh); - - searchListener = new SearchView.OnQueryTextListener() { - @Override - public boolean onQueryTextSubmit(String query) { - appAdapter.filter(query); - return false; - } - - @Override - public boolean onQueryTextChange(String newText) { - appAdapter.filter(newText); - return false; - } - }; - } - - @Override - public boolean onCreateOptionsMenu(@NonNull Menu menu) { - getMenuInflater().inflate(R.menu.menu_app_list, menu); - searchView = (SearchView) menu.findItem(R.id.menu_search).getActionView(); - searchView.setOnQueryTextListener(searchListener); - return super.onCreateOptionsMenu(menu); - } - - @Override - public void onDataReady() { - binding.swipeRefreshLayout.setRefreshing(false); - String queryStr = searchView != null ? searchView.getQuery().toString() : ""; - appAdapter.filter(queryStr); - } - - @Override - public void onItemClick(View v, ApplicationInfo info) { - AppHelper.showMenu(this, getSupportFragmentManager(), v, info); - - } - - @Override - public void onBackPressed() { - if (searchView.isIconified()) { - super.onBackPressed(); - } else { - searchView.setIconified(true); - } - } - - @Override - public void onPointerCaptureChanged(boolean hasCapture) { - - } -} diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java index 48470b38..d08fb183 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ModulesActivity.java @@ -196,6 +196,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi }).show(); } adapter = new ModuleAdapter(); + adapter.setHasStableIds(true); moduleUtil.addListener(this); binding.recyclerView.setAdapter(adapter); binding.recyclerView.setLayoutManager(new LinearLayoutManager(this)); @@ -561,7 +562,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi boolean changed = moduleUtil.isModuleEnabled(packageName) ^ isChecked; if (changed) { moduleUtil.setModuleEnabled(packageName, isChecked); - moduleUtil.updateModulesList(true); + moduleUtil.updateModulesList(true, binding); } }); mSwitch.setChecked(moduleUtil.isModuleEnabled(item.packageName)); @@ -617,6 +618,11 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi } } + @Override + public long getItemId(int position) { + return items.get(position).hashCode(); + } + class ViewHolder extends RecyclerView.ViewHolder { ImageView appIcon; TextView appName; diff --git a/app/src/main/java/org/meowcat/edxposed/manager/SettingsActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/SettingsActivity.java index 3ec2781c..cf567bd4 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/SettingsActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/SettingsActivity.java @@ -415,7 +415,8 @@ public class SettingsActivity extends BaseActivity { Activity activity = getActivity(); if (activity != null) { Intent intent = new Intent(); - intent.setClass(activity, CompatListActivity.class); + intent.putExtra("compat_list",true); + intent.setClass(activity, BlackListActivity.class); activity.startActivity(intent); } return true; diff --git a/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppAdapter.java b/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppAdapter.java index 92c199c1..393e84a0 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppAdapter.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppAdapter.java @@ -10,6 +10,7 @@ import android.view.View; import android.view.ViewGroup; import android.widget.CompoundButton; import android.widget.Filter; +import android.widget.Filterable; import android.widget.ImageView; import android.widget.TextView; @@ -32,7 +33,7 @@ import java.util.Date; import java.util.List; import java.util.Locale; -public class AppAdapter extends RecyclerView.Adapter { +public class AppAdapter extends RecyclerView.Adapter implements Filterable { protected final Context context; private final ApplicationInfo.DisplayNameComparator displayNameComparator; @@ -84,6 +85,7 @@ public class AppAdapter extends RecyclerView.Adapter { AppHelper.makeSurePath(); checkedList = generateCheckedList(); sortApps(); + showList = fullList; if (callback != null) { callback.onDataReady(); } @@ -195,6 +197,16 @@ public class AppAdapter extends RecyclerView.Adapter { }); } + @Override + public long getItemId(int position) { + return showList.get(position).packageName.hashCode(); + } + + @Override + public Filter getFilter() { + return new ApplicationFilter(); + } + @Override public int getItemCount() { return showList.size(); @@ -246,17 +258,18 @@ public class AppAdapter extends RecyclerView.Adapter { @Override protected FilterResults performFiltering(CharSequence constraint) { - if (constraint == null || constraint.length() == 0) { + if (constraint.toString().isEmpty()) { showList = fullList; } else { - showList = new ArrayList<>(); + ArrayList filtered = new ArrayList<>(); String filter = constraint.toString().toLowerCase(); for (ApplicationInfo info : fullList) { if (lowercaseContains(InstallApkUtil.getAppLabel(info, pm), filter) || lowercaseContains(info.packageName, filter)) { - showList.add(info); + filtered.add(info); } } + showList = filtered; } return null; } diff --git a/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java b/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java index d107356a..5a72b3ee 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/util/ModuleUtil.java @@ -16,8 +16,11 @@ import android.widget.Toast; import androidx.annotation.NonNull; +import com.google.android.material.snackbar.Snackbar; + import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.XposedApp; +import org.meowcat.edxposed.manager.databinding.ActivityModulesBinding; import org.meowcat.edxposed.manager.repo.ModuleVersion; import org.meowcat.edxposed.manager.repo.RepoDb; @@ -207,11 +210,19 @@ public final class ModuleUtil { } public synchronized void updateModulesList(boolean showToast) { + updateModulesList(showToast, null); + } + + public synchronized void updateModulesList(boolean showToast, ActivityModulesBinding binding) { try { Log.i(XposedApp.TAG, "ModuleUtil -> updating modules.list"); int installedXposedVersion = XposedApp.getXposedVersion(); if (!XposedApp.getPreferences().getBoolean("skip_xposedminversion_check", false) && installedXposedVersion <= 0 && showToast) { - Toast.makeText(XposedApp.getInstance(), R.string.notinstalled, Toast.LENGTH_SHORT).show(); + if (binding != null) { + Snackbar.make(binding.snackbar, R.string.notinstalled, Snackbar.LENGTH_SHORT).show(); + } else { + showToast(R.string.notinstalled); + } return; } @@ -221,7 +232,11 @@ public final class ModuleUtil { for (InstalledModule module : enabledModules) { if (!XposedApp.getPreferences().getBoolean("skip_xposedminversion_check", false) && (module.minVersion > installedXposedVersion || module.minVersion < MIN_MODULE_VERSION) && showToast) { - Toast.makeText(XposedApp.getInstance(), R.string.notinstalled, Toast.LENGTH_SHORT).show(); + if (binding != null) { + Snackbar.make(binding.snackbar, R.string.notinstalled, Snackbar.LENGTH_SHORT).show(); + } else { + showToast(R.string.notinstalled); + } continue; } @@ -241,11 +256,19 @@ public final class ModuleUtil { FileUtils.setPermissions(XposedApp.ENABLED_MODULES_LIST_FILE, 00664, -1, -1); if (showToast) { - showToast(R.string.xposed_module_list_updated); + if (binding != null) { + Snackbar.make(binding.snackbar, R.string.xposed_module_list_updated, Snackbar.LENGTH_SHORT).show(); + } else { + showToast(R.string.xposed_module_list_updated); + } } } catch (IOException e) { Log.e(XposedApp.TAG, "ModuleUtil -> cannot write " + MODULES_LIST_FILE, e); - Toast.makeText(XposedApp.getInstance(), "cannot write " + MODULES_LIST_FILE + e, Toast.LENGTH_SHORT).show(); + if (binding != null) { + Snackbar.make(binding.snackbar, "cannot write " + MODULES_LIST_FILE + e, Snackbar.LENGTH_SHORT).show(); + } else { + Toast.makeText(XposedApp.getInstance(), "cannot write " + MODULES_LIST_FILE + e, Toast.LENGTH_SHORT).show(); + } } } diff --git a/build.gradle b/build.gradle index 591879ac..a124535b 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { } dependencies { - classpath 'com.android.tools.build:gradle:4.0.0-beta02' + classpath 'com.android.tools.build:gradle:4.0.0-beta03' classpath 'com.google.android.gms:oss-licenses-plugin:0.10.2' // NOTE: Do not place your application dependencies here; they belong