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;
import com.topjohnwu.magisk.ui.utils.Utils;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
......@@ -8,6 +10,10 @@ public class Module {
private final boolean isValid;
private final boolean isCache;
private File mRemoveFile;
private File mDisableFile;
private File mPropFile;
private String mName;
......@@ -18,9 +24,11 @@ public class Module {
this.isCache = file.getPath().contains("cache");
this.isValid = new File(file + "/module.prop").exists();
if (isValid) {
mPropFile = new File(file + "/module.prop");
}
if (!isValid) return;
mPropFile = new File(file + "/module.prop");
mRemoveFile = new File(file + "/remove");
mDisableFile = new File(file + "/disable");
}
public boolean isValid() {
......@@ -43,6 +51,14 @@ public class Module {
return mDescription;
}
public void createRemoveFile() {
Utils.executeCommand("echo \"\" > " + mRemoveFile.getPath());
}
public void createDisableFile() {
Utils.executeCommand("echo \"\" > " + mDisableFile.getPath());
}
public void parse() throws Exception {
BufferedReader reader = new BufferedReader(new FileReader(mPropFile));
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;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.topjohnwu.magisk.R;
......@@ -17,37 +18,34 @@ import butterknife.ButterKnife;
public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHolder> {
private final List<Module> mList;
private final ItemClickListener mListener;
public ModulesAdapter(List<Module> mList) {
this.mList = mList;
public ModulesAdapter(List<Module> list, ItemClickListener listener) {
this.mList = list;
this.mListener = listener;
}
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
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);
}
@Override
public void onBindViewHolder(ViewHolder holder, int position) {
public void onBindViewHolder(final ViewHolder holder, int position) {
Module module = mList.get(position);
holder.title.setText(module.getName());
holder.versionName.setText(module.getVersion());
holder.description.setText(module.getDescription());
//FIXME
//holder.cache.setText("" + module.isCache());
holder.overflowButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.onItemClick(holder.overflowButton, holder.getAdapterPosition());
}
});
}
@Override
......@@ -60,7 +58,7 @@ public class ModulesAdapter extends RecyclerView.Adapter<ModulesAdapter.ViewHold
@BindView(R.id.title) TextView title;
@BindView(R.id.version_name) TextView versionName;
@BindView(R.id.description) TextView description;
//@BindView(R.id.cache) TextView cache;
@BindView(R.id.overflow) ImageView overflowButton;
public ViewHolder(View itemView) {
super(itemView);
......
package com.topjohnwu.magisk.ui;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
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.view.LayoutInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ProgressBar;
import com.topjohnwu.magisk.R;
import com.topjohnwu.magisk.model.Module;
import com.topjohnwu.magisk.rv.ItemClickListener;
import com.topjohnwu.magisk.rv.ModulesAdapter;
import com.topjohnwu.magisk.ui.utils.Utils;
import java.io.File;
import java.io.FileFilter;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
......@@ -28,31 +34,64 @@ public class ModulesFragment extends android.support.v4.app.Fragment {
private static final String MAGISK_CACHE_PATH = "/cache/magisk";
@BindView(R.id.recyclerView) RecyclerView recyclerView;
@BindView(R.id.progressBar) ProgressBar progressBar;
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
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.modules_fragment, container, false);
ButterKnife.bind(this, v);
View view = inflater.inflate(R.layout.modules_fragment, container, false);
ButterKnife.bind(this, view);
new CheckFolders().execute();
return v;
return view;
}
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
protected Boolean doInBackground(Void... voids) {
File[] magisk = new File(MAGISK_PATH).listFiles(new FileFilter() {
......@@ -104,9 +143,9 @@ public class ModulesFragment extends android.support.v4.app.Fragment {
protected void onPostExecute(Boolean 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 @@
android:layout_marginTop="?attr/actionBarSize"
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:id="@+id/recyclerView"
android:layout_width="match_parent"
......
......@@ -73,7 +73,7 @@
android:focusable="false"
android:gravity="center"
android:padding="3dp"
android:src="@drawable/root"/>
android:src="@drawable/ic_menu_overflow_material"/>
</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 @@
<string name="root">Root</string>
<string name="modules">Modules</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>
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