UI improvements
This commit is contained in:
parent
9379ffbca5
commit
32136b62d7
|
|
@ -1,20 +1,12 @@
|
|||
package io.github.lsposed.manager.adapters;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.net.Uri;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.widget.PopupMenu;
|
||||
import androidx.fragment.app.FragmentManager;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
|
@ -28,62 +20,34 @@ import java.util.List;
|
|||
|
||||
import io.github.lsposed.manager.Constants;
|
||||
import io.github.lsposed.manager.R;
|
||||
import io.github.lsposed.manager.util.CompileUtil;
|
||||
|
||||
import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS;
|
||||
|
||||
public class AppHelper {
|
||||
|
||||
public static final String SETTINGS_CATEGORY = "de.robv.android.xposed.category.MODULE_SETTINGS";
|
||||
private static final String BASE_PATH = Constants.getBaseDir();
|
||||
private static final String SCOPE_LIST_PATH = "conf/%s.conf";
|
||||
|
||||
private static final HashMap<String, List<String>> scopeList = new HashMap<>();
|
||||
|
||||
public static void showMenu(@NonNull Context context,
|
||||
@NonNull FragmentManager fragmentManager,
|
||||
@NonNull View anchor,
|
||||
@NonNull ApplicationInfo info) {
|
||||
PopupMenu appMenu = new PopupMenu(context, anchor);
|
||||
appMenu.inflate(R.menu.menu_app_item);
|
||||
appMenu.setOnMenuItemClickListener(menuItem -> {
|
||||
int itemId = menuItem.getItemId();
|
||||
if (itemId == R.id.app_menu_launch) {
|
||||
Intent launchIntent = context.getPackageManager().getLaunchIntentForPackage(info.packageName);
|
||||
if (launchIntent != null) {
|
||||
context.startActivity(launchIntent);
|
||||
} else {
|
||||
Toast.makeText(context, context.getString(R.string.module_no_ui), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
} else if (itemId == R.id.app_menu_stop) {
|
||||
try {
|
||||
ActivityManager manager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
manager.killBackgroundProcesses(info.packageName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (itemId == R.id.app_menu_compile_speed) {
|
||||
CompileUtil.compileSpeed(context, fragmentManager, info);
|
||||
} else if (itemId == R.id.app_menu_compile_dexopt) {
|
||||
CompileUtil.compileDexopt(context, fragmentManager, info);
|
||||
} else if (itemId == R.id.app_menu_compile_reset) {
|
||||
CompileUtil.reset(context, fragmentManager, info);
|
||||
} else if (itemId == R.id.app_menu_store) {
|
||||
Uri uri = Uri.parse("market://details?id=" + info.packageName);
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (itemId == R.id.app_menu_info) {
|
||||
context.startActivity(new Intent(ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", info.packageName, null)));
|
||||
} else if (itemId == R.id.app_menu_uninstall) {
|
||||
context.startActivity(new Intent(Intent.ACTION_UNINSTALL_PACKAGE, Uri.fromParts("package", info.packageName, null)));
|
||||
}
|
||||
return true;
|
||||
});
|
||||
appMenu.show();
|
||||
public static Intent getSettingsIntent(String packageName, PackageManager packageManager) {
|
||||
// taken from
|
||||
// ApplicationPackageManager.getLaunchIntentForPackage(String)
|
||||
// first looks for an Xposed-specific category, falls back to
|
||||
// getLaunchIntentForPackage
|
||||
|
||||
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
|
||||
intentToResolve.addCategory(SETTINGS_CATEGORY);
|
||||
intentToResolve.setPackage(packageName);
|
||||
List<ResolveInfo> ris = packageManager.queryIntentActivities(intentToResolve, 0);
|
||||
|
||||
if (ris.size() <= 0) {
|
||||
return packageManager.getLaunchIntentForPackage(packageName);
|
||||
}
|
||||
|
||||
Intent intent = new Intent(intentToResolve);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setClassName(ris.get(0).activityInfo.packageName, ris.get(0).activityInfo.name);
|
||||
return intent;
|
||||
}
|
||||
|
||||
public static boolean onOptionsItemSelected(MenuItem item, SharedPreferences preferences) {
|
||||
|
|
@ -122,17 +86,17 @@ public class AppHelper {
|
|||
ApplicationInfo.DisplayNameComparator displayNameComparator = new ApplicationInfo.DisplayNameComparator(pm);
|
||||
switch (sort) {
|
||||
case 7:
|
||||
return Collections.reverseOrder((PackageInfo a, PackageInfo b) -> Long.compare(a.lastUpdateTime, b.lastUpdateTime));
|
||||
return Collections.reverseOrder(Comparator.comparingLong((PackageInfo a) -> a.lastUpdateTime));
|
||||
case 6:
|
||||
return (PackageInfo a, PackageInfo b) -> Long.compare(a.lastUpdateTime, b.lastUpdateTime);
|
||||
return Comparator.comparingLong((PackageInfo a) -> a.lastUpdateTime);
|
||||
case 5:
|
||||
return Collections.reverseOrder((PackageInfo a, PackageInfo b) -> Long.compare(a.firstInstallTime, b.firstInstallTime));
|
||||
return Collections.reverseOrder(Comparator.comparingLong((PackageInfo a) -> a.firstInstallTime));
|
||||
case 4:
|
||||
return (PackageInfo a, PackageInfo b) -> Long.compare(a.firstInstallTime, b.firstInstallTime);
|
||||
return Comparator.comparingLong((PackageInfo a) -> a.firstInstallTime);
|
||||
case 3:
|
||||
return Collections.reverseOrder((a, b) -> a.packageName.compareTo(b.packageName));
|
||||
return Collections.reverseOrder(Comparator.comparing(a -> a.packageName));
|
||||
case 2:
|
||||
return (a, b) -> a.packageName.compareTo(b.packageName);
|
||||
return Comparator.comparing(a -> a.packageName);
|
||||
case 1:
|
||||
return Collections.reverseOrder((PackageInfo a, PackageInfo b) -> displayNameComparator.compare(a.applicationInfo, b.applicationInfo));
|
||||
case 0:
|
||||
|
|
|
|||
|
|
@ -1,12 +1,17 @@
|
|||
package io.github.lsposed.manager.adapters;
|
||||
|
||||
import android.app.ActivityManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
|
|
@ -21,33 +26,31 @@ import android.widget.TextView;
|
|||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.bumptech.glide.request.target.CustomTarget;
|
||||
import com.bumptech.glide.request.transition.Transition;
|
||||
import com.google.android.material.checkbox.MaterialCheckBox;
|
||||
import com.google.android.material.snackbar.Snackbar;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
|
||||
import io.github.lsposed.manager.App;
|
||||
import io.github.lsposed.manager.R;
|
||||
import io.github.lsposed.manager.ui.activity.AppListActivity;
|
||||
import io.github.lsposed.manager.ui.widget.MasterSwitch;
|
||||
import io.github.lsposed.manager.util.CompileUtil;
|
||||
import io.github.lsposed.manager.util.GlideApp;
|
||||
import io.github.lsposed.manager.util.ModuleUtil;
|
||||
|
||||
import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS;
|
||||
|
||||
public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder> implements Filterable {
|
||||
|
||||
private final AppListActivity activity;
|
||||
private final DateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
||||
private final PackageManager pm;
|
||||
private final ApplicationFilter filter;
|
||||
private final SharedPreferences preferences;
|
||||
|
|
@ -56,6 +59,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
private List<PackageInfo> fullList, showList;
|
||||
private List<String> checkedList;
|
||||
private boolean enabled = true;
|
||||
private ApplicationInfo selectedInfo;
|
||||
|
||||
public ScopeAdapter(AppListActivity activity, String modulePackageName, MasterSwitch masterSwitch) {
|
||||
this.activity = activity;
|
||||
|
|
@ -74,6 +78,7 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
notifyDataSetChanged();
|
||||
}
|
||||
});
|
||||
enabled = ModuleUtil.getInstance().isModuleEnabled(modulePackageName);
|
||||
refresh();
|
||||
}
|
||||
|
||||
|
|
@ -85,7 +90,6 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
}
|
||||
|
||||
private void loadApps() {
|
||||
enabled = ModuleUtil.getInstance().isModuleEnabled(modulePackageName);
|
||||
activity.runOnUiThread(() -> masterSwitch.setChecked(enabled));
|
||||
checkedList = AppHelper.getScopeList(modulePackageName);
|
||||
fullList = pm.getInstalledPackages(PackageManager.GET_META_DATA);
|
||||
|
|
@ -161,6 +165,13 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
} else if (itemId == R.id.item_show_modules) {
|
||||
item.setChecked(!item.isChecked());
|
||||
preferences.edit().putBoolean("show_modules", item.isChecked()).apply();
|
||||
} else if (itemId == R.id.menu_launch) {
|
||||
Intent launchIntent = pm.getLaunchIntentForPackage(modulePackageName);
|
||||
if (launchIntent != null) {
|
||||
activity.startActivity(launchIntent);
|
||||
} else {
|
||||
activity.makeSnackBar(R.string.module_no_ui, Snackbar.LENGTH_LONG);
|
||||
}
|
||||
} else if (!AppHelper.onOptionsItemSelected(item, preferences)) {
|
||||
return false;
|
||||
}
|
||||
|
|
@ -168,8 +179,57 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
return true;
|
||||
}
|
||||
|
||||
public boolean onContextItemSelected(@NonNull MenuItem item) {
|
||||
ApplicationInfo info = selectedInfo;
|
||||
if (info == null) {
|
||||
return false;
|
||||
}
|
||||
int itemId = item.getItemId();
|
||||
if (itemId == R.id.app_menu_launch) {
|
||||
Intent launchIntent = pm.getLaunchIntentForPackage(info.packageName);
|
||||
if (launchIntent != null) {
|
||||
activity.startActivity(launchIntent);
|
||||
} else {
|
||||
activity.makeSnackBar(R.string.module_no_ui, Snackbar.LENGTH_LONG);
|
||||
}
|
||||
} else if (itemId == R.id.app_menu_stop) {
|
||||
try {
|
||||
ActivityManager manager = (ActivityManager) activity.getSystemService(Context.ACTIVITY_SERVICE);
|
||||
manager.killBackgroundProcesses(info.packageName);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (itemId == R.id.app_menu_compile_speed) {
|
||||
CompileUtil.compileSpeed(activity, activity.getSupportFragmentManager(), info);
|
||||
} else if (itemId == R.id.app_menu_compile_dexopt) {
|
||||
CompileUtil.compileDexopt(activity, activity.getSupportFragmentManager(), info);
|
||||
} else if (itemId == R.id.app_menu_compile_reset) {
|
||||
CompileUtil.reset(activity, activity.getSupportFragmentManager(), info);
|
||||
} else if (itemId == R.id.app_menu_store) {
|
||||
Uri uri = Uri.parse("market://details?id=" + info.packageName);
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
activity.startActivity(intent);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
} else if (itemId == R.id.app_menu_info) {
|
||||
activity.startActivity(new Intent(ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package", info.packageName, null)));
|
||||
} else if (itemId == R.id.app_menu_uninstall) {
|
||||
activity.startActivity(new Intent(Intent.ACTION_UNINSTALL_PACKAGE, Uri.fromParts("package", info.packageName, null)));
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public void onCreateOptionsMenu(@NonNull Menu menu, @NonNull MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.menu_app_list, menu);
|
||||
Intent intent = AppHelper.getSettingsIntent(modulePackageName, pm);
|
||||
if (intent == null) {
|
||||
menu.removeItem(R.id.menu_launch);
|
||||
}
|
||||
menu.findItem(R.id.item_show_system).setChecked(preferences.getBoolean("show_system_apps", false));
|
||||
menu.findItem(R.id.item_show_games).setChecked(preferences.getBoolean("show_games", false));
|
||||
menu.findItem(R.id.item_show_modules).setChecked(preferences.getBoolean("show_modules", false));
|
||||
|
|
@ -203,6 +263,8 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
|
||||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
Log.e("Test", enabled + "");
|
||||
holder.root.setAlpha(enabled ? 1.0f : .5f);
|
||||
PackageInfo info = showList.get(position);
|
||||
holder.appName.setText(getAppLabel(info.applicationInfo, pm));
|
||||
GlideApp.with(holder.appIcon)
|
||||
|
|
@ -218,20 +280,21 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
|
||||
}
|
||||
});
|
||||
holder.appVersion.setText(info.versionName);
|
||||
holder.appVersion.setSelected(true);
|
||||
String creationDate = dateformat.format(new Date(info.firstInstallTime));
|
||||
String updateDate = dateformat.format(new Date(info.lastUpdateTime));
|
||||
holder.timestamps.setText(holder.itemView.getContext().getString(R.string.install_timestamps, creationDate, updateDate));
|
||||
holder.appPackage.setText(info.packageName);
|
||||
holder.appDescription.setText(activity.getString(R.string.app_description, info.packageName, info.versionName));
|
||||
|
||||
holder.mSwitch.setOnCheckedChangeListener(null);
|
||||
holder.mSwitch.setChecked(checkedList.contains(info.packageName));
|
||||
holder.itemView.setOnCreateContextMenuListener((menu, v, menuInfo) -> activity.getMenuInflater().inflate(R.menu.menu_app_item, menu));
|
||||
|
||||
holder.mSwitch.setEnabled(((ScopeAdapter) this).enabled);
|
||||
holder.mSwitch.setOnCheckedChangeListener((v, isChecked) ->
|
||||
onCheckedChange(v, isChecked, info.packageName));
|
||||
holder.itemView.setOnClickListener(v -> AppHelper.showMenu(activity, activity.getSupportFragmentManager(), v, info.applicationInfo));
|
||||
holder.checkbox.setOnCheckedChangeListener(null);
|
||||
holder.checkbox.setChecked(checkedList.contains(info.packageName));
|
||||
|
||||
holder.checkbox.setOnCheckedChangeListener((v, isChecked) -> onCheckedChange(v, isChecked, info.packageName));
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
if (enabled) holder.checkbox.toggle();
|
||||
});
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
selectedInfo = info.applicationInfo;
|
||||
return false;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -254,7 +317,6 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
}
|
||||
|
||||
public void refresh() {
|
||||
//noinspection deprecation
|
||||
AsyncTask.THREAD_POOL_EXECUTOR.execute(this::loadApps);
|
||||
}
|
||||
|
||||
|
|
@ -277,21 +339,20 @@ public class ScopeAdapter extends RecyclerView.Adapter<ScopeAdapter.ViewHolder>
|
|||
|
||||
static class ViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
View root;
|
||||
ImageView appIcon;
|
||||
TextView appName;
|
||||
TextView appPackage;
|
||||
TextView appVersion;
|
||||
TextView timestamps;
|
||||
SwitchCompat mSwitch;
|
||||
TextView appDescription;
|
||||
MaterialCheckBox checkbox;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
root = itemView.findViewById(R.id.item_root);
|
||||
appIcon = itemView.findViewById(R.id.app_icon);
|
||||
appName = itemView.findViewById(R.id.app_name);
|
||||
appPackage = itemView.findViewById(R.id.package_name);
|
||||
appVersion = itemView.findViewById(R.id.version_name);
|
||||
timestamps = itemView.findViewById(R.id.timestamps);
|
||||
mSwitch = itemView.findViewById(R.id.checkbox);
|
||||
appDescription = itemView.findViewById(R.id.description);
|
||||
checkbox = itemView.findViewById(R.id.checkbox);
|
||||
checkbox.setVisibility(View.VISIBLE);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@ public class AppListActivity extends BaseActivity {
|
|||
ActionBar bar = getSupportActionBar();
|
||||
assert bar != null;
|
||||
bar.setDisplayHomeAsUpEnabled(true);
|
||||
bar.setTitle(R.string.menu_scope);
|
||||
bar.setSubtitle(moduleName);
|
||||
bar.setTitle(moduleName);
|
||||
bar.setSubtitle(modulePackageName);
|
||||
scopeAdapter = new ScopeAdapter(this, modulePackageName, binding.masterSwitch);
|
||||
scopeAdapter.setHasStableIds(true);
|
||||
binding.recyclerView.setAdapter(scopeAdapter);
|
||||
|
|
@ -87,10 +87,10 @@ public class AppListActivity extends BaseActivity {
|
|||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
|
||||
if (!scopeAdapter.onOptionsItemSelected(item)) {
|
||||
return super.onOptionsItemSelected(item);
|
||||
if (scopeAdapter.onOptionsItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -108,6 +108,14 @@ public class AppListActivity extends BaseActivity {
|
|||
runOnUiThread(() -> scopeAdapter.getFilter().filter(queryStr));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(@NonNull MenuItem item) {
|
||||
if (scopeAdapter.onContextItemSelected(item)) {
|
||||
return true;
|
||||
}
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (searchView.isIconified()) {
|
||||
|
|
|
|||
|
|
@ -3,7 +3,6 @@ package io.github.lsposed.manager.ui.activity;
|
|||
import android.content.Intent;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.text.TextUtils;
|
||||
|
|
@ -19,7 +18,6 @@ import android.widget.TextView;
|
|||
import androidx.annotation.NonNull;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.widget.SearchView;
|
||||
import androidx.appcompat.widget.SwitchCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
|
@ -30,18 +28,12 @@ import java.io.File;
|
|||
import java.io.FileInputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.PrintWriter;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
|
||||
import io.github.lsposed.manager.BuildConfig;
|
||||
import io.github.lsposed.manager.Constants;
|
||||
import io.github.lsposed.manager.R;
|
||||
import io.github.lsposed.manager.adapters.AppHelper;
|
||||
|
|
@ -56,14 +48,12 @@ import static android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS;
|
|||
|
||||
public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleListener {
|
||||
|
||||
public static final String SETTINGS_CATEGORY = "de.robv.android.xposed.category.MODULE_SETTINGS";
|
||||
ActivityModulesBinding binding;
|
||||
private int installedXposedVersion;
|
||||
private ApplicationFilter filter;
|
||||
private SearchView searchView;
|
||||
private SearchView.OnQueryTextListener mSearchListener;
|
||||
private PackageManager pm;
|
||||
private final DateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd", Locale.getDefault());
|
||||
private ModuleUtil moduleUtil;
|
||||
private ModuleAdapter adapter = null;
|
||||
private final Runnable reloadModules = new Runnable() {
|
||||
|
|
@ -293,7 +283,7 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
if (packageName == null) {
|
||||
return false;
|
||||
}
|
||||
Intent intent = getSettingsIntent(packageName);
|
||||
Intent intent = AppHelper.getSettingsIntent(packageName, pm);
|
||||
if (intent != null) {
|
||||
startActivity(intent);
|
||||
} else {
|
||||
|
|
@ -316,38 +306,10 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
} else if (itemId == R.id.menu_uninstall) {
|
||||
startActivity(new Intent(Intent.ACTION_UNINSTALL_PACKAGE, Uri.fromParts("package", module.packageName, null)));
|
||||
return true;
|
||||
} else if (itemId == R.id.menu_scope) {
|
||||
Intent intent = new Intent(this, AppListActivity.class);
|
||||
intent.putExtra("modulePackageName", module.packageName);
|
||||
intent.putExtra("moduleName", module.getAppName());
|
||||
startActivity(intent);
|
||||
return true;
|
||||
}
|
||||
return super.onContextItemSelected(item);
|
||||
}
|
||||
|
||||
private Intent getSettingsIntent(String packageName) {
|
||||
// taken from
|
||||
// ApplicationPackageManager.getLaunchIntentForPackage(String)
|
||||
// first looks for an Xposed-specific category, falls back to
|
||||
// getLaunchIntentForPackage
|
||||
PackageManager pm = getPackageManager();
|
||||
|
||||
Intent intentToResolve = new Intent(Intent.ACTION_MAIN);
|
||||
intentToResolve.addCategory(SETTINGS_CATEGORY);
|
||||
intentToResolve.setPackage(packageName);
|
||||
List<ResolveInfo> ris = pm.queryIntentActivities(intentToResolve, 0);
|
||||
|
||||
if (ris.size() <= 0) {
|
||||
return pm.getLaunchIntentForPackage(packageName);
|
||||
}
|
||||
|
||||
Intent intent = new Intent(intentToResolve);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
intent.setClassName(ris.get(0).activityInfo.packageName, ris.get(0).activityInfo.name);
|
||||
return intent;
|
||||
}
|
||||
|
||||
private boolean lowercaseContains(String s, CharSequence filter) {
|
||||
return !TextUtils.isEmpty(s) && s.toLowerCase().contains(filter);
|
||||
}
|
||||
|
|
@ -374,17 +336,12 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
@Override
|
||||
public void onBindViewHolder(@NonNull ViewHolder holder, int position) {
|
||||
ModuleUtil.InstalledModule item = items.get(position);
|
||||
boolean enabled = moduleUtil.isModuleEnabled(item.packageName);
|
||||
holder.itemView.setOnClickListener(v -> {
|
||||
String packageName = item.packageName;
|
||||
if (packageName == null || packageName.equals(BuildConfig.APPLICATION_ID)) {
|
||||
return;
|
||||
}
|
||||
Intent launchIntent = getSettingsIntent(packageName);
|
||||
if (launchIntent != null) {
|
||||
startActivity(launchIntent);
|
||||
} else {
|
||||
Snackbar.make(findViewById(R.id.snackbar), R.string.module_no_ui, Snackbar.LENGTH_LONG).show();
|
||||
}
|
||||
Intent intent = new Intent(ModulesActivity.this, AppListActivity.class);
|
||||
intent.putExtra("modulePackageName", item.packageName);
|
||||
intent.putExtra("moduleName", item.getAppName());
|
||||
startActivity(intent);
|
||||
});
|
||||
|
||||
holder.itemView.setOnLongClickListener(v -> {
|
||||
|
|
@ -392,20 +349,21 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
return false;
|
||||
});
|
||||
|
||||
holder.itemView.setOnCreateContextMenuListener((menu, v, menuInfo) -> getMenuInflater().inflate(R.menu.context_menu_modules, menu));
|
||||
holder.root.setAlpha(enabled ? 1.0f : .5f);
|
||||
|
||||
holder.itemView.setOnCreateContextMenuListener((menu, v, menuInfo) -> {
|
||||
getMenuInflater().inflate(R.menu.context_menu_modules, menu);
|
||||
Intent intent = AppHelper.getSettingsIntent(item.packageName, pm);
|
||||
if (intent == null) {
|
||||
menu.removeItem(R.id.menu_launch);
|
||||
}
|
||||
});
|
||||
holder.appName.setText(item.getAppName());
|
||||
|
||||
TextView version = holder.appVersion;
|
||||
version.setText(Objects.requireNonNull(item).versionName);
|
||||
version.setSelected(true);
|
||||
|
||||
TextView packageTv = holder.appPackage;
|
||||
packageTv.setText(item.packageName);
|
||||
|
||||
String creationDate = dateformat.format(new Date(item.installTime));
|
||||
String updateDate = dateformat.format(new Date(item.updateTime));
|
||||
holder.timestamps.setText(getString(R.string.install_timestamps, creationDate, updateDate));
|
||||
|
||||
GlideApp.with(holder.appIcon)
|
||||
.load(item.getPackageInfo())
|
||||
.into(holder.appIcon);
|
||||
|
|
@ -418,59 +376,24 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
descriptionText.setText(getString(R.string.module_empty_description));
|
||||
descriptionText.setTextColor(ContextCompat.getColor(ModulesActivity.this, R.color.warning));
|
||||
}
|
||||
|
||||
SwitchCompat mSwitch = holder.mSwitch;
|
||||
mSwitch.setOnCheckedChangeListener((buttonView, isChecked) -> {
|
||||
String packageName = item.packageName;
|
||||
boolean changed = moduleUtil.isModuleEnabled(packageName) ^ isChecked;
|
||||
if (changed) {
|
||||
if (isChecked && AppHelper.getScopeList(packageName).isEmpty()) {
|
||||
moduleUtil.setModuleEnabled(packageName, true);
|
||||
Intent intent = new Intent(ModulesActivity.this, AppListActivity.class);
|
||||
intent.putExtra("modulePackageName", packageName);
|
||||
intent.putExtra("moduleName", item.getAppName());
|
||||
startActivity(intent);
|
||||
return;
|
||||
}
|
||||
moduleUtil.setModuleEnabled(packageName, isChecked);
|
||||
moduleUtil.updateModulesList(true, binding.snackbar);
|
||||
}
|
||||
});
|
||||
mSwitch.setChecked(moduleUtil.isModuleEnabled(item.packageName));
|
||||
TextView warningText = holder.warningText;
|
||||
|
||||
if (item.minVersion == 0) {
|
||||
if (!preferences.getBoolean("skip_xposedminversion_check", false)) {
|
||||
mSwitch.setEnabled(false);
|
||||
}
|
||||
warningText.setText(getString(R.string.no_min_version_specified));
|
||||
warningText.setVisibility(View.VISIBLE);
|
||||
} else if (installedXposedVersion > 0 && item.minVersion > installedXposedVersion) {
|
||||
if (!preferences.getBoolean("skip_xposedminversion_check", false)) {
|
||||
mSwitch.setEnabled(false);
|
||||
}
|
||||
warningText.setText(String.format(getString(R.string.warning_xposed_min_version), item.minVersion));
|
||||
warningText.setVisibility(View.VISIBLE);
|
||||
} else if (item.minVersion < ModuleUtil.MIN_MODULE_VERSION) {
|
||||
if (!preferences.getBoolean("skip_xposedminversion_check", false)) {
|
||||
mSwitch.setEnabled(false);
|
||||
}
|
||||
warningText.setText(String.format(getString(R.string.warning_min_version_too_low), item.minVersion, ModuleUtil.MIN_MODULE_VERSION));
|
||||
warningText.setVisibility(View.VISIBLE);
|
||||
} else if (item.isInstalledOnExternalStorage()) {
|
||||
if (!preferences.getBoolean("skip_xposedminversion_check", false)) {
|
||||
mSwitch.setEnabled(false);
|
||||
}
|
||||
warningText.setText(getString(R.string.warning_installed_on_external_storage));
|
||||
warningText.setVisibility(View.VISIBLE);
|
||||
} else if (installedXposedVersion == 0 || (installedXposedVersion == -1)) {
|
||||
if (!preferences.getBoolean("skip_xposedminversion_check", false)) {
|
||||
mSwitch.setEnabled(false);
|
||||
}
|
||||
warningText.setText(getString(R.string.not_installed_no_lollipop));
|
||||
warningText.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
mSwitch.setEnabled(true);
|
||||
warningText.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
|
@ -495,25 +418,22 @@ public class ModulesActivity extends BaseActivity implements ModuleUtil.ModuleLi
|
|||
}
|
||||
|
||||
class ViewHolder extends RecyclerView.ViewHolder {
|
||||
View root;
|
||||
ImageView appIcon;
|
||||
TextView appName;
|
||||
TextView appPackage;
|
||||
TextView appDescription;
|
||||
TextView appVersion;
|
||||
TextView timestamps;
|
||||
TextView warningText;
|
||||
SwitchCompat mSwitch;
|
||||
|
||||
ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
root = itemView.findViewById(R.id.item_root);
|
||||
appIcon = itemView.findViewById(R.id.app_icon);
|
||||
appName = itemView.findViewById(R.id.app_name);
|
||||
appDescription = itemView.findViewById(R.id.description);
|
||||
appPackage = itemView.findViewById(R.id.package_name);
|
||||
appVersion = itemView.findViewById(R.id.version_name);
|
||||
timestamps = itemView.findViewById(R.id.timestamps);
|
||||
appVersion.setVisibility(View.VISIBLE);
|
||||
warningText = itemView.findViewById(R.id.warning);
|
||||
mSwitch = itemView.findViewById(R.id.checkbox);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,12 +11,6 @@ import androidx.core.content.ContextCompat;
|
|||
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||
|
||||
import io.github.lsposed.manager.App;
|
||||
import io.github.lsposed.manager.BuildConfig;
|
||||
import io.github.lsposed.manager.Constants;
|
||||
import io.github.lsposed.manager.R;
|
||||
import io.github.lsposed.manager.databinding.StatusInstallerBinding;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
|
|
@ -25,6 +19,11 @@ import java.lang.reflect.Method;
|
|||
import java.util.Locale;
|
||||
|
||||
import dalvik.system.VMRuntime;
|
||||
import io.github.lsposed.manager.App;
|
||||
import io.github.lsposed.manager.BuildConfig;
|
||||
import io.github.lsposed.manager.Constants;
|
||||
import io.github.lsposed.manager.R;
|
||||
import io.github.lsposed.manager.databinding.StatusInstallerBinding;
|
||||
|
||||
@SuppressLint("StaticFieldLeak")
|
||||
public class StatusDialogBuilder extends MaterialAlertDialogBuilder {
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ import com.takisoft.preferencex.ColorPickerPreference;
|
|||
import com.takisoft.preferencex.ColorPickerPreferenceDialogFragmentCompat;
|
||||
import com.takisoft.preferencex.PreferenceFragmentCompat;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import io.github.lsposed.manager.util.CustomThemeColor;
|
||||
import io.github.lsposed.manager.util.CustomThemeColors;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class ThemeColorPreference extends ColorPickerPreference {
|
||||
|
||||
static {
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ package io.github.lsposed.manager.util;
|
|||
import android.content.Context;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.drawable.AdaptiveIconDrawable;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
|
|
@ -21,7 +22,7 @@ public class IconLoader extends AppGlideModule {
|
|||
public void registerComponents(Context context, @NonNull Glide glide, Registry registry) {
|
||||
int iconSize = context.getResources().getDimensionPixelSize(R.dimen.app_icon_size);
|
||||
registry.prepend(PackageInfo.class, Bitmap.class, new AppIconModelLoader.Factory(iconSize,
|
||||
false, context));
|
||||
context.getApplicationInfo().loadIcon(context.getPackageManager()) instanceof AdaptiveIconDrawable, context));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
|
|
@ -7,110 +7,98 @@
|
|||
android:clickable="true"
|
||||
android:focusable="true"
|
||||
android:minHeight="?attr/listPreferredItemHeight"
|
||||
android:paddingVertical="8dp"
|
||||
android:paddingStart="8dp"
|
||||
android:paddingEnd="?modulesHorizontalPadding"
|
||||
tools:ignore="RtlSymmetry">
|
||||
android:paddingVertical="16dp"
|
||||
android:paddingStart="16dp"
|
||||
android:paddingEnd="16dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="48dp"
|
||||
android:layout_height="48dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:srcCompat="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="wrap_content"
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:id="@+id/item_root"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="8dp"
|
||||
android:singleLine="false"
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toEndOf="@id/app_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@tools:sample/first_names" />
|
||||
tools:ignore="RtlSymmetry">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/version_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:maxWidth="100dp"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewEnd"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/app_name"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="@tools:sample/last_names" />
|
||||
<ImageView
|
||||
android:id="@+id/app_icon"
|
||||
android:layout_width="36dp"
|
||||
android:layout_height="36dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="ContentDescription"
|
||||
tools:srcCompat="@tools:sample/backgrounds/scenic" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/package_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="end"
|
||||
android:singleLine="true"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintEnd_toStartOf="@+id/checkbox"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintStart_toStartOf="@+id/app_name"
|
||||
app:layout_constraintTop_toBottomOf="@+id/app_name"
|
||||
tools:text="@tools:sample/cities" />
|
||||
<TextView
|
||||
android:id="@+id/app_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginStart="20dp"
|
||||
android:singleLine="false"
|
||||
android:textAppearance="?android:attr/textAppearance"
|
||||
android:textSize="16sp"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintStart_toEndOf="@id/app_icon"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/description"
|
||||
tools:text="@tools:sample/first_names" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/timestamps"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
app:layout_constraintStart_toStartOf="@+id/package_name"
|
||||
app:layout_constraintTop_toBottomOf="@+id/package_name"
|
||||
tools:text="@tools:sample/cities" />
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/checkbox"
|
||||
app:layout_constraintHorizontal_bias="0.0"
|
||||
app:layout_constraintStart_toStartOf="@+id/app_name"
|
||||
app:layout_constraintTop_toBottomOf="@id/app_name"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/description"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:visibility="gone"
|
||||
app:layout_constrainedWidth="true"
|
||||
app:layout_constraintEnd_toStartOf="@+id/checkbox"
|
||||
app:layout_constraintHorizontal_bias="0"
|
||||
app:layout_constraintStart_toStartOf="@+id/timestamps"
|
||||
app:layout_constraintTop_toBottomOf="@+id/timestamps"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
<TextView
|
||||
android:id="@+id/version_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ellipsize="marquee"
|
||||
android:marqueeRepeatLimit="marquee_forever"
|
||||
android:maxWidth="100dp"
|
||||
android:singleLine="true"
|
||||
android:textAlignment="viewEnd"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textIsSelectable="false"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintHorizontal_bias="1.0"
|
||||
app:layout_constraintStart_toEndOf="@+id/app_name"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:ignore="RtlHardcoded"
|
||||
tools:text="@tools:sample/last_names" />
|
||||
|
||||
<com.google.android.material.switchmaterial.SwitchMaterial
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:checked="false"
|
||||
android:focusable="false"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<com.google.android.material.checkbox.MaterialCheckBox
|
||||
android:id="@+id/checkbox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="@android:color/transparent"
|
||||
android:focusable="false"
|
||||
android:clickable="false"
|
||||
android:visibility="gone"
|
||||
android:minHeight="0dp"
|
||||
android:minWidth="0dp"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/warning"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="@color/warning"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="@+id/description"
|
||||
app:layout_constraintTop_toBottomOf="@+id/description"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
<TextView
|
||||
android:id="@+id/warning"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:layout_marginBottom="8dp"
|
||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||
android:textColor="@color/warning"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="@+id/description"
|
||||
app:layout_constraintTop_toBottomOf="@+id/description"
|
||||
tools:text="@tools:sample/lorem" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</FrameLayout>
|
||||
|
|
@ -16,6 +16,7 @@
|
|||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
android:paddingTop="16dp"
|
||||
android:paddingStart="54dp"
|
||||
android:paddingBottom="16dp">
|
||||
|
||||
<TextView
|
||||
|
|
|
|||
|
|
@ -3,16 +3,7 @@
|
|||
|
||||
<item
|
||||
android:id="@+id/menu_launch"
|
||||
android:title="@string/module_launch" />
|
||||
<item
|
||||
android:id="@+id/menu_scope"
|
||||
android:title="@string/menu_scope" />
|
||||
<!-- <item
|
||||
android:id="@+id/menu_download_updates"
|
||||
android:title="@string/module_download_updates" />
|
||||
<item
|
||||
android:id="@+id/menu_support"
|
||||
android:title="@string/module_support" />-->
|
||||
android:title="@string/module_settings" />
|
||||
<item
|
||||
android:id="@+id/menu_app_store"
|
||||
android:title="@string/modules_app_store" />
|
||||
|
|
|
|||
|
|
@ -8,6 +8,12 @@
|
|||
app:actionViewClass="androidx.appcompat.widget.SearchView"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/menu_launch"
|
||||
android:title="@string/module_settings"
|
||||
android:icon="@drawable/ic_settings"
|
||||
app:showAsAction="ifRoom" />
|
||||
|
||||
<item
|
||||
android:id="@+id/item_show_games"
|
||||
android:checkable="true"
|
||||
|
|
|
|||
|
|
@ -160,4 +160,6 @@
|
|||
<string name="menu_show_games">Games</string>
|
||||
<string name="menu_show_modules">Modules</string>
|
||||
<string name="failed_to_save_scope_list">Failed save scope list</string>
|
||||
<string name="module_settings">Module settings</string>
|
||||
<string name="app_description">%s\nVersion: %s</string>
|
||||
</resources>
|
||||
|
|
|
|||
Loading…
Reference in New Issue