From 840d54cccfc5f4213378607bd7c0f1d3641359ac Mon Sep 17 00:00:00 2001 From: NekoInverter <42698724+NekoInverter@users.noreply.github.com> Date: Sun, 22 Nov 2020 13:19:11 +0800 Subject: [PATCH] Add master switch for scope list --- .../edxposed/manager/ModuleScopeActivity.java | 10 +- .../edxposed/manager/adapters/AppAdapter.java | 5 + .../edxposed/manager/adapters/AppHelper.java | 1 + .../manager/adapters/ScopeAdapter.java | 18 ++- .../edxposed/manager/widget/MasterSwitch.java | 112 ++++++++++++++++++ .../main/res/layout/activity_scope_list.xml | 57 +++++++++ app/src/main/res/layout/master_switch.xml | 49 ++++++++ app/src/main/res/values-zh-rCN/strings.xml | 1 + app/src/main/res/values/attrs.xml | 7 ++ app/src/main/res/values/strings.xml | 1 + app/src/main/res/values/styles.xml | 18 +++ 11 files changed, 273 insertions(+), 6 deletions(-) create mode 100644 app/src/main/java/org/meowcat/edxposed/manager/widget/MasterSwitch.java create mode 100644 app/src/main/res/layout/activity_scope_list.xml create mode 100644 app/src/main/res/layout/master_switch.xml diff --git a/app/src/main/java/org/meowcat/edxposed/manager/ModuleScopeActivity.java b/app/src/main/java/org/meowcat/edxposed/manager/ModuleScopeActivity.java index 15e78a92..43989f67 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/ModuleScopeActivity.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/ModuleScopeActivity.java @@ -16,14 +16,14 @@ 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.ScopeAdapter; -import org.meowcat.edxposed.manager.databinding.ActivityBlackListBinding; +import org.meowcat.edxposed.manager.databinding.ActivityScopeListBinding; public class ModuleScopeActivity extends BaseActivity implements AppAdapter.Callback { private SearchView searchView; - private AppAdapter appAdapter; + private ScopeAdapter appAdapter; private SearchView.OnQueryTextListener searchListener; - private ActivityBlackListBinding binding; + private ActivityScopeListBinding binding; private final Runnable runnable = new Runnable() { @Override public void run() { @@ -37,7 +37,7 @@ public class ModuleScopeActivity extends BaseActivity implements AppAdapter.Call super.onCreate(savedInstanceState); String modulePackageName = getIntent().getStringExtra("modulePackageName"); String moduleName = getIntent().getStringExtra("moduleName"); - binding = ActivityBlackListBinding.inflate(getLayoutInflater()); + binding = ActivityScopeListBinding.inflate(getLayoutInflater()); setContentView(binding.getRoot()); setSupportActionBar(binding.toolbar); binding.toolbar.setNavigationOnClickListener(view -> finish()); @@ -47,7 +47,7 @@ public class ModuleScopeActivity extends BaseActivity implements AppAdapter.Call bar.setSubtitle(moduleName); } setupWindowInsets(binding.snackbar, binding.recyclerView); - appAdapter = new ScopeAdapter(this, modulePackageName); + appAdapter = new ScopeAdapter(this, modulePackageName, binding.masterSwitch); appAdapter.setHasStableIds(true); binding.recyclerView.setAdapter(appAdapter); binding.recyclerView.setLayoutManager(new LinearLayoutManager(this)); 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 536a21a4..6d454f99 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 @@ -205,6 +205,11 @@ public class AppAdapter extends RecyclerView.Adapter impl holder.mSwitch.setOnCheckedChangeListener(null); holder.mSwitch.setChecked(checkedList.contains(info.packageName)); + if (this instanceof ScopeAdapter) { + holder.mSwitch.setEnabled(((ScopeAdapter) this).enabled); + } else { + holder.mSwitch.setEnabled(true); + } holder.mSwitch.setOnCheckedChangeListener((v, isChecked) -> onCheckedChange(v, isChecked, info)); holder.itemView.setOnClickListener(v -> { diff --git a/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppHelper.java b/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppHelper.java index 8295ad5f..120451e2 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppHelper.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/adapters/AppHelper.java @@ -354,6 +354,7 @@ public class AppHelper { static boolean saveScopeList(String modulePackageName, List list) { File file = new File(BASE_PATH + String.format(SCOPE_LIST_PATH, modulePackageName)); if (list.size() == 0) { + scopeList.put(modulePackageName, list); return file.delete(); } try { diff --git a/app/src/main/java/org/meowcat/edxposed/manager/adapters/ScopeAdapter.java b/app/src/main/java/org/meowcat/edxposed/manager/adapters/ScopeAdapter.java index 56a8af72..342ed00d 100644 --- a/app/src/main/java/org/meowcat/edxposed/manager/adapters/ScopeAdapter.java +++ b/app/src/main/java/org/meowcat/edxposed/manager/adapters/ScopeAdapter.java @@ -1,11 +1,13 @@ package org.meowcat.edxposed.manager.adapters; +import android.app.Activity; import android.content.Context; import android.content.pm.ApplicationInfo; import android.widget.CompoundButton; import org.meowcat.edxposed.manager.R; import org.meowcat.edxposed.manager.util.ToastUtil; +import org.meowcat.edxposed.manager.widget.MasterSwitch; import java.util.ArrayList; import java.util.List; @@ -13,11 +15,23 @@ import java.util.List; public class ScopeAdapter extends AppAdapter { protected final String modulePackageName; + protected boolean enabled = true; private List checkedList; + private final MasterSwitch masterSwitch; - public ScopeAdapter(Context context, String modulePackageName) { + public ScopeAdapter(Context context, String modulePackageName, MasterSwitch masterSwitch) { super(context); this.modulePackageName = modulePackageName; + this.masterSwitch = masterSwitch; + masterSwitch.setTitle(context.getString(R.string.enable_scope)); + masterSwitch.setOnCheckedChangedListener(new MasterSwitch.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(boolean checked) { + enabled = checked; + AppHelper.saveScopeList(modulePackageName, enabled ? checkedList : new ArrayList<>()); + notifyDataSetChanged(); + } + }); } @Override @@ -30,6 +44,8 @@ public class ScopeAdapter extends AppAdapter { } scopeList.retainAll(list); checkedList = scopeList; + enabled = checkedList.size() != 0; + ((Activity) context).runOnUiThread(() -> masterSwitch.setChecked(enabled)); return checkedList; } diff --git a/app/src/main/java/org/meowcat/edxposed/manager/widget/MasterSwitch.java b/app/src/main/java/org/meowcat/edxposed/manager/widget/MasterSwitch.java new file mode 100644 index 00000000..5b098baa --- /dev/null +++ b/app/src/main/java/org/meowcat/edxposed/manager/widget/MasterSwitch.java @@ -0,0 +1,112 @@ +package org.meowcat.edxposed.manager.widget; + +import android.content.Context; +import android.content.res.TypedArray; +import android.graphics.drawable.ColorDrawable; +import android.graphics.drawable.StateListDrawable; +import android.util.AttributeSet; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.Checkable; +import android.widget.FrameLayout; +import android.widget.TextView; + +import androidx.annotation.NonNull; +import androidx.annotation.Nullable; +import androidx.appcompat.widget.SwitchCompat; + +import org.meowcat.edxposed.manager.R; + +public class MasterSwitch extends FrameLayout implements View.OnClickListener, Checkable { + + private TextView masterTitle; + private SwitchCompat switchCompat; + + private String title; + + private OnCheckedChangeListener listener; + + private boolean isChecked; + + public MasterSwitch(@NonNull Context context, @Nullable AttributeSet attrs) { + super(context, attrs); + init(context, attrs); + } + + public MasterSwitch(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + init(context, attrs); + } + + public MasterSwitch(@NonNull Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + init(context, attrs); + } + + private void init(Context context, AttributeSet attrs) { + LayoutInflater inflater = LayoutInflater.from(getContext()); + inflater.inflate(R.layout.master_switch, this, true); + + TypedArray a = context.obtainStyledAttributes(attrs, R.styleable.MasterSwitch); + int colorOn = a.getColor(R.styleable.MasterSwitch_masterSwitchBackgroundOn, 0); + int colorOff = a.getColor(R.styleable.MasterSwitch_masterSwitchBackgroundOff, 0); + a.recycle(); + + StateListDrawable drawable = new StateListDrawable(); + drawable.addState(new int[]{android.R.attr.state_selected}, new ColorDrawable(colorOn)); + drawable.addState(new int[]{}, new ColorDrawable(colorOff)); + setBackground(drawable); + + masterTitle = findViewById(android.R.id.title); + switchCompat = findViewById(R.id.switchWidget); + + setOnClickListener(this); + } + + public void setTitle(String title) { + this.title = title; + masterTitle.setText(title); + } + + private void updateViews() { + if (switchCompat != null) { + setSelected(isChecked); + switchCompat.setChecked(isChecked); + } + } + + @Override + public boolean isChecked() { + return isChecked; + } + + @Override + public void toggle() { + setChecked(!isChecked); + } + + @Override + public void setChecked(boolean checked) { + final boolean changed = isChecked != checked; + if (changed) { + isChecked = checked; + updateViews(); + if (listener != null) { + listener.onCheckedChanged(checked); + } + } + } + + public void setOnCheckedChangedListener(OnCheckedChangeListener listener) { + this.listener = listener; + } + + public static abstract class OnCheckedChangeListener { + public abstract void onCheckedChanged(boolean checked); + } + + @Override + public void onClick(View v) { + toggle(); + } +} diff --git a/app/src/main/res/layout/activity_scope_list.xml b/app/src/main/res/layout/activity_scope_list.xml new file mode 100644 index 00000000..4c06f576 --- /dev/null +++ b/app/src/main/res/layout/activity_scope_list.xml @@ -0,0 +1,57 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/master_switch.xml b/app/src/main/res/layout/master_switch.xml new file mode 100644 index 00000000..0f08afad --- /dev/null +++ b/app/src/main/res/layout/master_switch.xml @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 14bdda42..46400b23 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -311,4 +311,5 @@ 禁用绕过隐藏 API 的限制 禁用绕过隐藏 API 的限制将会通过某些检测(如Snapchat)\n警告: 启用此选项可能会使某些功能无法正常工作,或出现一些其他问题 作用域 + 启用作用域 diff --git a/app/src/main/res/values/attrs.xml b/app/src/main/res/values/attrs.xml index 12c85419..b514607e 100644 --- a/app/src/main/res/values/attrs.xml +++ b/app/src/main/res/values/attrs.xml @@ -9,4 +9,11 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 4a3843d3..874d5275 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -342,4 +342,5 @@ Disable hidden API restrictions bypass Disable hidden API restrictions bypass will pass some detection (eg Snapchat), these APIs are disabled by default\nWARNING: Enable this option may cause some features do not work properly, or some other problems Scope + Enable scope diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 448c9d62..117c56b0 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -33,6 +33,24 @@ + + + + +