Commit 31b552ab authored by dvdandroid's avatar dvdandroid Committed by topjohnwu

Module fragment with menu; remove and disable buttons

parent f5e53cd6
MagiskManager
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<option name="DEFAULT_COMPILER" value="Javac" />
<resourceExtensions />
<wildcardResourcePatterns>
<entry name="!?*.java" />
<entry name="!?*.form" />
<entry name="!?*.class" />
<entry name="!?*.groovy" />
<entry name="!?*.scala" />
<entry name="!?*.flex" />
<entry name="!?*.kt" />
<entry name="!?*.clj" />
</wildcardResourcePatterns>
<annotationProcessing>
<profile default="true" name="Default" enabled="true">
<processorPath useClasspath="true" />
</profile>
</annotationProcessing>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="PROJECT" charset="UTF-8" />
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GradleSettings">
<option name="linkedExternalProjectsSettings">
<GradleProjectSettings>
<option name="distributionType" value="LOCAL" />
<option name="externalProjectPath" value="$PROJECT_DIR$" />
<option name="gradleHome" value="C:\Program Files\Android-Studio\gradle\gradle-2.14.1" />
<option name="modules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/lib" />
<option value="$PROJECT_DIR$/lib/RootCommands" />
</set>
</option>
<option name="myModules">
<set>
<option value="$PROJECT_DIR$" />
<option value="$PROJECT_DIR$/app" />
<option value="$PROJECT_DIR$/lib" />
<option value="$PROJECT_DIR$/lib/RootCommands" />
</set>
</option>
</GradleProjectSettings>
</option>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="EntryPointsManager">
<entry_points version="2.0" />
</component>
<component name="NullableNotNullManager">
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
<option name="myNullables">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
</list>
</value>
</option>
<option name="myNotNulls">
<value>
<list size="4">
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
</list>
</value>
</option>
</component>
<component name="ProjectLevelVcsManager" settingsEditedManually="false">
<OptionsSetting value="true" id="Add" />
<OptionsSetting value="true" id="Remove" />
<OptionsSetting value="true" id="Checkout" />
<OptionsSetting value="true" id="Update" />
<OptionsSetting value="true" id="Status" />
<OptionsSetting value="true" id="Edit" />
<ConfirmationsSetting value="0" id="Add" />
<ConfirmationsSetting value="0" id="Remove" />
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" assert-keyword="true" jdk-15="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/build/classes" />
</component>
<component name="ProjectType">
<option name="id" value="Android" />
</component>
<component name="masterDetails">
<states>
<state key="ProjectJDKs.UI">
<settings>
<last-edited>1.8</last-edited>
<splitter-proportions>
<option name="proportions">
<list>
<option value="0.2" />
</list>
</option>
</splitter-proportions>
</settings>
</state>
</states>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/MagiskManager.iml" filepath="$PROJECT_DIR$/MagiskManager.iml" />
<module fileurl="file://$PROJECT_DIR$/lib/RootCommands/RootCommands.iml" filepath="$PROJECT_DIR$/lib/RootCommands/RootCommands.iml" />
<module fileurl="file://$PROJECT_DIR$/app/app.iml" filepath="$PROJECT_DIR$/app/app.iml" />
<module fileurl="file://$PROJECT_DIR$/lib/lib.iml" filepath="$PROJECT_DIR$/lib/lib.iml" />
</modules>
</component>
</project>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RunConfigurationProducerService">
<option name="ignoredProducers">
<set>
<option value="org.jetbrains.plugins.gradle.execution.test.runner.AllInPackageGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestClassGradleConfigurationProducer" />
<option value="org.jetbrains.plugins.gradle.execution.test.runner.TestMethodGradleConfigurationProducer" />
</set>
</option>
</component>
</project>
\ No newline at end of file
package com.topjohnwu.magisk.model; package com.topjohnwu.magisk.model;
import com.topjohnwu.magisk.ui.utils.Utils;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.File; import java.io.File;
import java.io.FileReader; import java.io.FileReader;
...@@ -8,6 +10,10 @@ public class Module { ...@@ -8,6 +10,10 @@ public class Module {
private final boolean isValid; private final boolean isValid;
private final boolean isCache; private final boolean isCache;
private File mRemoveFile;
private File mDisableFile;
private File mPropFile; private File mPropFile;
private String mName; private String mName;
...@@ -18,9 +24,11 @@ public class Module { ...@@ -18,9 +24,11 @@ public class Module {
this.isCache = file.getPath().contains("cache"); this.isCache = file.getPath().contains("cache");
this.isValid = new File(file + "/module.prop").exists(); this.isValid = new File(file + "/module.prop").exists();
if (isValid) { if (!isValid) return;
mPropFile = new File(file + "/module.prop"); mPropFile = new File(file + "/module.prop");
} mRemoveFile = new File(file + "/remove");
mDisableFile = new File(file + "/disable");
} }
public boolean isValid() { public boolean isValid() {
...@@ -43,6 +51,14 @@ public class Module { ...@@ -43,6 +51,14 @@ public class Module {
return mDescription; return mDescription;
} }
public void createRemoveFile() {
Utils.executeCommand("echo \"\" > " + mRemoveFile.getPath());
}
public void createDisableFile() {
Utils.executeCommand("echo \"\" > " + mDisableFile.getPath());
}
public void parse() throws Exception { public void parse() throws Exception {
BufferedReader reader = new BufferedReader(new FileReader(mPropFile)); BufferedReader reader = new BufferedReader(new FileReader(mPropFile));
String line; String line;
......
package com.topjohnwu.magisk.rv;
import android.view.View;
public interface ItemClickListener {
void onItemClick(View view, int position);
}
...@@ -4,6 +4,7 @@ import android.support.v7.widget.RecyclerView; ...@@ -4,6 +4,7 @@ import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.R;
...@@ -17,37 +18,34 @@ import butterknife.ButterKnife; ...@@ -17,37 +18,34 @@ import butterknife.ButterKnife;
public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> { public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> {
private final List<Module> mList; private final List<Module> mList;
private final ItemClickListener mListener;
public ModulesAdapter(List<Module> mList) { public ModulesAdapter(List<Module> list, ItemClickListener listener) {
this.mList = mList; this.mList = list;
this.mListener = listener;
} }
@Override @Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false); View view = LayoutInflater.from(parent.getContext()).inflate(R.layout.row, parent, false);
/*FIXME
final ViewHolder viewHolder = new ViewHolder(view);
view.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
listener.onItemClick(viewHolder.getAdapterPosition());
}
});*/
return new ViewHolder(view); return new ViewHolder(view);
} }
@Override @Override
public void onBindViewHolder(ViewHolder holder, int position) { public void onBindViewHolder(final ViewHolder holder, int position) {
Module module = mList.get(position); Module module = mList.get(position);
holder.title.setText(module.getName()); holder.title.setText(module.getName());
holder.versionName.setText(module.getVersion()); holder.versionName.setText(module.getVersion());
holder.description.setText(module.getDescription()); holder.description.setText(module.getDescription());
//FIXME holder.overflowButton.setOnClickListener(new View.OnClickListener() {
@Override
//holder.cache.setText("" + module.isCache()); public void onClick(View view) {
mListener.onItemClick(holder.overflowButton, holder.getAdapterPosition());
}
});
} }
@Override @Override
...@@ -60,7 +58,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold ...@@ -60,7 +58,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
@BindView(R.id.title) TextView title; @BindView(R.id.title) TextView title;
@BindView(R.id.version_name) TextView versionName; @BindView(R.id.version_name) TextView versionName;
@BindView(R.id.description) TextView description; @BindView(R.id.description) TextView description;
//@BindView(R.id.cache) TextView cache; @BindView(R.id.overflow) ImageView overflowButton;
public ViewHolder(View itemView) { public ViewHolder(View itemView) {
super(itemView); super(itemView);
......
package com.topjohnwu.magisk.ui; package com.topjohnwu.magisk.ui;
import android.app.ProgressDialog;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.ProgressBar;
import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.model.Module; import com.topjohnwu.magisk.model.Module;
import com.topjohnwu.magisk.rv.ItemClickListener;
import com.topjohnwu.magisk.rv.ModulesAdapter; import com.topjohnwu.magisk.rv.ModulesAdapter;
import com.topjohnwu.magisk.ui.utils.Utils; import com.topjohnwu.magisk.ui.utils.Utils;
import java.io.File; import java.io.File;
import java.io.FileFilter; import java.io.FileFilter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
...@@ -28,31 +34,64 @@ public class ModulesFragment extends android.support.v4.app.Fragment { ...@@ -28,31 +34,64 @@ public class ModulesFragment extends android.support.v4.app.Fragment {
private static final String MAGISK_CACHE_PATH = "/cache/magisk"; private static final String MAGISK_CACHE_PATH = "/cache/magisk";
@BindView(R.id.recyclerView) RecyclerView recyclerView; @BindView(R.id.recyclerView) RecyclerView recyclerView;
@BindView(R.id.progressBar) ProgressBar progressBar;
private List<Module> listModules = new ArrayList<>(); private List<Module> listModules = new ArrayList<>();
private ItemClickListener moduleActions = new ItemClickListener() {
@Override
public void onItemClick(final View view, final int position) {
PopupMenu popup = new PopupMenu(getContext(), view);
try {
Field[] fields = popup.getClass().getDeclaredFields();
for (Field field : fields) {
if ("mPopup".equals(field.getName())) {
field.setAccessible(true);
Object menuPopupHelper = field.get(popup);
Class<?> classPopupHelper = Class.forName(menuPopupHelper.getClass().getName());
Method setForceIcons = classPopupHelper.getMethod("setForceShowIcon", boolean.class);
setForceIcons.invoke(menuPopupHelper, true);
break;
}
}
} catch (Exception ignored) {
}
popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
switch (item.getItemId()) {
case R.id.remove:
listModules.get(position).createRemoveFile();
Snackbar.make(view, R.string.remove_file_created, Snackbar.LENGTH_SHORT).show();
break;
case R.id.disable:
listModules.get(position).createDisableFile();
Snackbar.make(view, R.string.disable_file_created, Snackbar.LENGTH_SHORT).show();
break;
}
return false;
}
});
popup.inflate(R.menu.module_popup);
popup.show();
}
};
@Nullable @Nullable
@Override @Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.modules_fragment, container, false); View view = inflater.inflate(R.layout.modules_fragment, container, false);
ButterKnife.bind(this, v); ButterKnife.bind(this, view);
new CheckFolders().execute(); new CheckFolders().execute();
return v; return view;
} }
private class CheckFolders extends AsyncTask<Void, Integer, Boolean> { private class CheckFolders extends AsyncTask<Void, Integer, Boolean> {
private ProgressDialog progress;
@Override
protected void onPreExecute() {
super.onPreExecute();
progress = ProgressDialog.show(getContext(), null, getString(R.string.loading), true, false);
}
@Override @Override
protected Boolean doInBackground(Void... voids) { protected Boolean doInBackground(Void... voids) {
File[] magisk = new File(MAGISK_PATH).listFiles(new FileFilter() { File[] magisk = new File(MAGISK_PATH).listFiles(new FileFilter() {
...@@ -104,9 +143,9 @@ public class ModulesFragment extends android.support.v4.app.Fragment { ...@@ -104,9 +143,9 @@ public class ModulesFragment extends android.support.v4.app.Fragment {
protected void onPostExecute(Boolean result) { protected void onPostExecute(Boolean result) {
super.onPostExecute(result); super.onPostExecute(result);
progress.dismiss(); progressBar.setVisibility(View.GONE);
recyclerView.setAdapter(new ModulesAdapter(listModules)); recyclerView.setAdapter(new ModulesAdapter(listModules, moduleActions));
} }
} }
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#757575"
android:pathData="M12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM4,12c0,-4.42 3.58,-8 8,-8 1.85,0 3.55,0.63 4.9,1.69L5.69,16.9C4.63,15.55 4,13.85 4,12zM12,20c-1.85,0 -3.55,-0.63 -4.9,-1.69L18.31,7.1C19.37,8.45 20,10.15 20,12c0,4.42 -3.58,8 -8,8z"/>
</vector>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0">
<path
android:fillColor="#757575"
android:pathData="M6,19c0,1.1 0.9,2 2,2h8c1.1,0 2,-0.9 2,-2V7H6v12zM19,4h-3.5l-1,-1h-5l-1,1H5v2h14V4z"/>
</vector>
<?xml version="1.0" encoding="utf-8"?>
<!--
Copyright (C) 2015 The Android Open Source Project
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0" >
<path
android:pathData="M12,8c1.1,0 2,-0.9 2,-2s-0.9,-2 -2,-2c-1.1,0 -2,0.9 -2,2S10.9,8 12,8zM12,10c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,10 12,10zM12,16c-1.1,0 -2,0.9 -2,2s0.9,2 2,2c1.1,0 2,-0.9 2,-2S13.1,16 12,16z"
android:fillColor="#757575"/>
</vector>
\ No newline at end of file
...@@ -6,6 +6,12 @@ ...@@ -6,6 +6,12 @@
android:layout_marginTop="?attr/actionBarSize" android:layout_marginTop="?attr/actionBarSize"
android:orientation="vertical"> android:orientation="vertical">
<ProgressBar
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/progressBar"
android:layout_gravity="center"/>
<android.support.v7.widget.RecyclerView <android.support.v7.widget.RecyclerView
android:id="@+id/recyclerView" android:id="@+id/recyclerView"
android:layout_width="match_parent" android:layout_width="match_parent"
......
...@@ -73,7 +73,7 @@ ...@@ -73,7 +73,7 @@
android:focusable="false" android:focusable="false"
android:gravity="center" android:gravity="center"
android:padding="3dp" android:padding="3dp"
android:src="@drawable/root"/> android:src="@drawable/ic_menu_overflow_material"/>
</LinearLayout> </LinearLayout>
......
<?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/remove"
android:icon="@drawable/ic_delete"
android:title="@string/remove"/>
<item
android:id="@+id/disable"
android:icon="@drawable/ic_block"
android:title="@string/disable"/>
</menu>
\ No newline at end of file
...@@ -28,4 +28,8 @@ ...@@ -28,4 +28,8 @@
<string name="root">Root</string> <string name="root">Root</string>
<string name="modules">Modules</string> <string name="modules">Modules</string>
<string name="log">Log</string> <string name="log">Log</string>
<string name="remove">Remove</string>
<string name="disable">Disable</string>
<string name="remove_file_created">Module will be removed at next reboot</string>
<string name="disable_file_created">Module will be disabled at next reboot</string>
</resources> </resources>
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment