From f404fe05706e08cb7b678b7799d0b38859818b00 Mon Sep 17 00:00:00 2001 From: d8ahazard Date: Tue, 6 Sep 2016 16:54:08 -0500 Subject: [PATCH] Break/Fix Wheeeeee --- .../topjohnwu/magisk/BaseModuleFragment.java | 53 ++-- .../topjohnwu/magisk/BaseRepoFragment.java | 26 +- .../com/topjohnwu/magisk/ModulesFragment.java | 37 ++- .../com/topjohnwu/magisk/ReposAdapter.java | 91 +++++-- .../com/topjohnwu/magisk/module/Module.java | 125 ++++++--- .../com/topjohnwu/magisk/module/Repo.java | 250 +++++++++++++----- .../topjohnwu/magisk/module/RepoAdapter.java | 52 ++-- .../magisk/utils/AnimationHelper.java | 58 ++++ .../com/topjohnwu/magisk/utils/GitAgent.java | 8 + .../com/topjohnwu/magisk/utils/Utils.java | 8 +- .../topjohnwu/magisk/utils/WebRequest.java | 11 +- app/src/main/res/drawable/ic_done_black.xml | 9 + app/src/main/res/layout/list_item_repo.xml | 24 +- .../res/layout/list_item_repo_expanded.xml | 67 +++++ .../res/layout/single_module_fragment.xml | 7 +- app/src/main/res/values/strings.xml | 3 + 16 files changed, 607 insertions(+), 222 deletions(-) create mode 100644 app/src/main/java/com/topjohnwu/magisk/utils/AnimationHelper.java create mode 100644 app/src/main/java/com/topjohnwu/magisk/utils/GitAgent.java create mode 100644 app/src/main/res/drawable/ic_done_black.xml create mode 100644 app/src/main/res/layout/list_item_repo_expanded.xml diff --git a/app/src/main/java/com/topjohnwu/magisk/BaseModuleFragment.java b/app/src/main/java/com/topjohnwu/magisk/BaseModuleFragment.java index 739ec0463..e41a73df8 100644 --- a/app/src/main/java/com/topjohnwu/magisk/BaseModuleFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/BaseModuleFragment.java @@ -6,9 +6,7 @@ import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.design.widget.Snackbar; import android.support.v4.app.Fragment; -import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.RecyclerView; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -19,26 +17,24 @@ import com.topjohnwu.magisk.module.Module; import com.topjohnwu.magisk.utils.Utils; import java.util.List; -import java.util.concurrent.ExecutionException; import butterknife.BindView; import butterknife.ButterKnife; public abstract class BaseModuleFragment extends Fragment { - @BindView(R.id.recyclerView) RecyclerView recyclerView; - @BindView(R.id.empty_rv) TextView emptyTv; - private SwipeRefreshLayout mSwipeRefreshLayout; + @BindView(R.id.recyclerView) + RecyclerView recyclerView; + @BindView(R.id.empty_rv) + TextView emptyTv; private View view; private SharedPreferences prefs; + @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { view = inflater.inflate(R.layout.single_module_fragment, container, false); - mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout); - mSwipeRefreshLayout.setOnRefreshListener(() -> { - refreshItems(); - }); + ButterKnife.bind(this, view); prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); @@ -59,16 +55,19 @@ public abstract class BaseModuleFragment extends Fragment { return view; } - recyclerView.setAdapter(new ModulesAdapter(listModules(), (chk, position) -> { - // On Checkbox change listener - CheckBox chbox = (CheckBox) chk; + recyclerView.setAdapter(new ModulesAdapter(listModules(), new Utils.ItemClickListener() { + @Override + public void onItemClick(View chk, int position) { + // On Checkbox change listener + CheckBox chbox = (CheckBox) chk; - if (!chbox.isChecked()) { - listModules().get(position).createDisableFile(); - Snackbar.make(chk, R.string.disable_file_created, Snackbar.LENGTH_SHORT).show(); - } else { - listModules().get(position).removeDisableFile(); - Snackbar.make(chk, R.string.disable_file_removed, Snackbar.LENGTH_SHORT).show(); + if (!chbox.isChecked()) { + BaseModuleFragment.this.listModules().get(position).createDisableFile(); + Snackbar.make(chk, R.string.disable_file_created, Snackbar.LENGTH_SHORT).show(); + } else { + BaseModuleFragment.this.listModules().get(position).removeDisableFile(); + Snackbar.make(chk, R.string.disable_file_removed, Snackbar.LENGTH_SHORT).show(); + } } }, (deleteBtn, position) -> { // On delete button click listener @@ -84,22 +83,6 @@ public abstract class BaseModuleFragment extends Fragment { return view; } - void refreshItems() { - Log.d("Magisk", "Calling refreshitems for online"); - Utils.LoadModules utils = new Utils.LoadModules(getActivity(),true); - utils.execute(); - onItemsLoadComplete(); - view.requestLayout(); - } - - - void onItemsLoadComplete() { - // Update the adapter and notify data set changed - // ... - - // Stop refresh animation - mSwipeRefreshLayout.setRefreshing(false); - } protected abstract List listModules(); } diff --git a/app/src/main/java/com/topjohnwu/magisk/BaseRepoFragment.java b/app/src/main/java/com/topjohnwu/magisk/BaseRepoFragment.java index a60bd1043..bc7d49474 100644 --- a/app/src/main/java/com/topjohnwu/magisk/BaseRepoFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/BaseRepoFragment.java @@ -3,17 +3,14 @@ package com.topjohnwu.magisk; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.Fragment; -import android.support.v4.widget.SwipeRefreshLayout; +import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; -import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.TextView; -import com.topjohnwu.magisk.module.Module; import com.topjohnwu.magisk.module.Repo; -import com.topjohnwu.magisk.utils.Utils; import java.util.List; @@ -26,15 +23,14 @@ public abstract class BaseRepoFragment extends Fragment { RecyclerView recyclerView; @BindView(R.id.empty_rv) TextView emptyTv; - private SwipeRefreshLayout mSwipeRefreshLayout; + + + @Nullable @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.single_module_fragment, container, false); - mSwipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swipeRefreshLayout); - mSwipeRefreshLayout.setOnRefreshListener(() -> { - refreshItems(); - }); + ButterKnife.bind(this, view); @@ -51,18 +47,6 @@ public abstract class BaseRepoFragment extends Fragment { return view; } - void refreshItems() { - Log.d("Magisk", "Calling refreshitems for online"); - new Utils.LoadModules(getActivity(),true).execute(); - onItemsLoadComplete(); - } - void onItemsLoadComplete() { - // Update the adapter and notify data set changed - // ... - - // Stop refresh animation - mSwipeRefreshLayout.setRefreshing(false); - } protected abstract List listRepos(); } diff --git a/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java b/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java index 3ab89fcc1..0af544180 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java @@ -14,6 +14,7 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; import android.support.v4.view.ViewPager; +import android.support.v4.widget.SwipeRefreshLayout; import android.util.Log; import android.view.LayoutInflater; import android.view.Menu; @@ -40,7 +41,9 @@ public class ModulesFragment extends Fragment { public static List listModulesCache = new ArrayList<>(); public static List listModulesDownload = new ArrayList<>(); private static final int FILE_SELECT_CODE = 0; + private TabsAdapter ta; private File input; + private SwipeRefreshLayout mSwipeRefreshLayout; @BindView(R.id.progressBar) ProgressBar progressBar; @BindView(R.id.fab) FloatingActionButton fabio; @@ -51,6 +54,7 @@ public class ModulesFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { View view = inflater.inflate(R.layout.modules_fragment, container, false); + ButterKnife.bind(this, view); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); if (prefs.contains("hasCachedRepos")) { @@ -58,11 +62,18 @@ public class ModulesFragment extends Fragment { } else { new Utils.LoadModules(getActivity(), true).execute(); } + new updateUI().execute(); setHasOptionsMenu(true); return view; } + public void updateThisShit() { + new Utils.LoadModules(getActivity(), true).execute(); + new updateUI().execute(); + setHasOptionsMenu(true); + } + @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); @@ -82,6 +93,8 @@ public class ModulesFragment extends Fragment { } + + public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { case FILE_SELECT_CODE: @@ -104,9 +117,10 @@ public class ModulesFragment extends Fragment { listModulesCache.clear(); listModulesDownload.clear(); progressBar.setVisibility(View.VISIBLE); - viewPager.setAdapter(new TabsAdapter(getChildFragmentManager())); + ta = new TabsAdapter(getChildFragmentManager()); + viewPager.setAdapter(ta); tabLayout.setupWithViewPager(viewPager); - new Utils.LoadModules(getActivity(),false).execute(); + new Utils.LoadModules(getActivity(),true).execute(); new updateUI().execute(); break; } @@ -114,6 +128,19 @@ public class ModulesFragment extends Fragment { return super.onOptionsItemSelected(item); } + public void redrawLayout() { + listModules.clear(); + listModulesCache.clear(); + listModulesDownload.clear(); + progressBar.setVisibility(View.VISIBLE); + ta = new TabsAdapter(getChildFragmentManager()); + viewPager.setAdapter(ta); + tabLayout.setupWithViewPager(viewPager); + new Utils.LoadModules(getActivity(),false).execute(); + new updateUI().execute(); + + } + public static class NormalModuleFragment extends BaseModuleFragment { @Override @@ -141,7 +168,7 @@ public class ModulesFragment extends Fragment { } - private class updateUI extends AsyncTask { + public class updateUI extends AsyncTask { @Override protected Void doInBackground(Void... voids) { @@ -153,8 +180,8 @@ public class ModulesFragment extends Fragment { super.onPostExecute(v); progressBar.setVisibility(View.GONE); - - viewPager.setAdapter(new TabsAdapter(getChildFragmentManager())); + ta = new TabsAdapter(getChildFragmentManager()); + viewPager.setAdapter(ta); tabLayout.setupWithViewPager(viewPager); } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java b/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java index f543e7d29..5d65987a6 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java @@ -3,22 +3,21 @@ package com.topjohnwu.magisk; import android.content.Context; import android.content.SharedPreferences; import android.preference.PreferenceManager; +import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.CheckBox; import android.widget.ImageView; +import android.widget.LinearLayout; import android.widget.TextView; -import android.widget.Toast; -import com.topjohnwu.magisk.module.Module; import com.topjohnwu.magisk.module.Repo; -import com.topjohnwu.magisk.utils.Shell; -import com.topjohnwu.magisk.utils.Utils; +import com.topjohnwu.magisk.utils.AnimationHelper; + +import org.w3c.dom.Text; -import java.io.File; import java.util.List; import butterknife.BindView; @@ -27,22 +26,39 @@ import butterknife.ButterKnife; public class ReposAdapter extends RecyclerView.Adapter { private final List mList; - private View view; + private View viewMain; private Context context; + @BindView(R.id.update) + ImageView updateImage; + @BindView(R.id.installed) + ImageView installedImage; + @BindView(R.id.popup_layout) + LinearLayout popupLayout; + @BindView(R.id.author) + TextView authorText; + @BindView(R.id.log) + TextView logText; + @BindView(R.id.updateStatus) TextView updateStatus; + @BindView(R.id.installedStatus) TextView installedStatus; + private boolean isCardExpanded; + public ReposAdapter(List list) { this.mList = list; } + private boolean mIsInstalled; + + @Override public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { - view = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_repo, parent, false); + viewMain = LayoutInflater.from(parent.getContext()).inflate(R.layout.list_item_repo, parent, false); + ButterKnife.bind(this, viewMain); context = parent.getContext(); - - return new ViewHolder(view); + return new ViewHolder(viewMain); } @Override @@ -50,26 +66,49 @@ public class ReposAdapter extends RecyclerView.Adapter final Repo repo = mList.get(position); holder.title.setText(repo.getName()); - holder.versionName.setText(repo.getVersion()); + holder.versionName.setText(repo.getmVersion()); holder.description.setText(repo.getDescription()); - view.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View view) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - if (!prefs.contains("isInstalled_" + repo.getName())) { + Log.d("Magisk","ReposAdapter: Setting up info " + repo.getId() + " and " + repo.getDescription() + " and " + repo.getmVersion()); + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (prefs.contains("repo_isInstalled_" + repo.getId())) { + mIsInstalled = prefs.getBoolean("repo_isInstalled_" + repo.getId(),false); + if (mIsInstalled) { + installedImage.setImageResource(R.drawable.ic_done_black); + installedStatus.setText(R.string.module_installed); + } + } - Utils.DownloadReceiver reciever = new Utils.DownloadReceiver() { - @Override - public void task(File file) { - Log.d("Magisk", "Task firing"); - new Utils.FlashZIP(context, repo.getName(), file.toString()).execute(); - } - }; - String filename = repo.getName().replace(" ", "") + ".zip"; - Utils.downloadAndReceive(context, reciever, repo.getZipUrl(), filename); + isCardExpanded = false; + AnimationHelper.collapse(popupLayout); + + viewMain.setOnClickListener(new View.OnClickListener() { + @Override + + public void onClick(View view) { + if (isCardExpanded) { + + AnimationHelper.collapse(popupLayout); + isCardExpanded = false; } else { - Toast.makeText(context,repo.getName() + " is already installed.",Toast.LENGTH_SHORT).show(); + AnimationHelper.expand(popupLayout); + isCardExpanded = true; + } + +// if (!mIsInstalled) { +// +// Utils.DownloadReceiver reciever = new Utils.DownloadReceiver() { +// @Override +// public void task(File file) { +// Log.d("Magisk", "Task firing"); +// new Utils.FlashZIP(context, repo.getId(), file.toString()).execute(); +// } +// }; +// String filename = repo.getId().replace(" ", "") + ".zip"; +// Utils.downloadAndReceive(context, reciever, repo.getmZipUrl(), filename); +// } else { +// Toast.makeText(context,repo.getId() + " is already installed.",Toast.LENGTH_SHORT).show(); +// } } }); diff --git a/app/src/main/java/com/topjohnwu/magisk/module/Module.java b/app/src/main/java/com/topjohnwu/magisk/module/Module.java index c46998f08..0e20a1294 100644 --- a/app/src/main/java/com/topjohnwu/magisk/module/Module.java +++ b/app/src/main/java/com/topjohnwu/magisk/module/Module.java @@ -17,58 +17,117 @@ public class Module { private String mName = null; private String mVersion = "(No version provided)"; private String mDescription = "(No description provided)"; - private String mUrl = null; + private String mUrl,mSupportUrl,mDonateUrl,mZipUrl,mBaseUrl,mManifestUrl,mAuthor; + private boolean mEnable, mRemove,mUpdateAvailable,mIsOnline; - private boolean mEnable; - private boolean mRemove; private String mId; private int mVersionCode; public Module(String path, Context context) { - SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); - Map keys = prefs.getAll(); - for(Map.Entry entry : keys.entrySet()){ - - if(entry.getValue().toString().contains(path)) { - Log.d("Magisk", "Hey, look a matching path, this guy's name is " + entry.getKey().replace("path_","")); - } - } mRemoveFile = path + "/remove"; mDisableFile = path + "/disable"; for (String line : Utils.readFile(path + "/module.prop")) { - String[] parts = line.split("=", 2); - if (parts.length != 2) { + String[] props = line.split("=", 2); + if (props.length != 2) { continue; } - String key = parts[0].trim(); + String key = props[0].trim(); if (key.charAt(0) == '#') { continue; } - String value = parts[1].trim(); - switch (key) { + String value = props[1].trim(); + switch (props[0]) { + case "versionCode": + this.mVersionCode = Integer.valueOf(props[1]); + break; case "name": - mName = value; + this.mName = props[1]; break; - case "version": - mVersion = value; - break; - case "description": - mDescription = value; + case "author": + this.mAuthor = props[1]; break; case "id": - mId = value; + this.mId = props[1]; break; - case "versionCode": - try { - mVersionCode = Integer.parseInt(value); - } catch (NumberFormatException e) { - mVersionCode = 0; + case "version": + this.mVersion = props[1]; + break; + case "description": + this.mDescription = props[1]; + break; + case "donate": + this.mDonateUrl = props[1]; + break; + case "support": + this.mSupportUrl = props[1]; + break; + case "donateUrl": + this.mDonateUrl = props[1]; + break; + case "zipUrl": + this.mZipUrl = props[1]; + break; + case "baseUrl": + this.mBaseUrl = props[1]; + break; + case "manifestUrl": + this.mManifestUrl = props[1]; + break; + default: + Log.d("Magisk", "Manifest string not recognized: " + props[0]); + break; + } + + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); + if (mId != null) { + Log.d("Magisk", "Module: Checking for preference named repo_" + mId); + if (prefs.contains("repo_" + mId)) { + String entryString = prefs.getString("repo_" + mId, ""); + + + String entryName = "repo" + mId; + + String[] subStrings = entryString.split("\n"); + for (String subKeys : subStrings) { + String[] idEntry = subKeys.split("=", 2); + Log.d("Magisk", "Module: Checking entry strings. Key is " + idEntry[0] + " and value is " + idEntry[1]); + if (idEntry[0].equals("id")) { + if (idEntry.length != 2) { + continue; + } + + if (idEntry[1].equals(mId)) { + Log.d("Magisk", "Module: Hey, I know I'm online..."); + mIsOnline = true; + } else mIsOnline = false; + } + if (idEntry[0].equals("versionCode")) { + if (idEntry.length != 2) { + continue; + } + + if (Integer.valueOf(idEntry[1]) > mVersionCode) { + mUpdateAvailable = true; + Log.d("Magisk", "Module: Hey, I have an update..."); + } else mUpdateAvailable = false; + } } - break; + + + } + + SharedPreferences.Editor editor = prefs.edit(); + if (mIsOnline) { + editor.putBoolean("repo_isInstalled_" + mId, true); + + } else { + editor.putBoolean("repo_isInstalled_" + mId, false); + } + editor.apply(); } } @@ -86,11 +145,11 @@ public class Module { public Module(Repo repo) { mName = repo.getName(); - mVersion = repo.getVersion(); + mVersion = repo.getmVersion(); mDescription = repo.getDescription(); mId = "foo"; mVersionCode = 111; - mUrl = repo.getZipUrl(); + mUrl = repo.getmZipUrl(); mEnable = true; mRemove = false; @@ -134,4 +193,8 @@ public class Module { return mRemove; } + public boolean isOnline() {return mIsOnline; } + + public boolean isUpdateAvailable() { return mUpdateAvailable; }; + } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/module/Repo.java b/app/src/main/java/com/topjohnwu/magisk/module/Repo.java index 228e7809c..e6944915f 100644 --- a/app/src/main/java/com/topjohnwu/magisk/module/Repo.java +++ b/app/src/main/java/com/topjohnwu/magisk/module/Repo.java @@ -15,53 +15,76 @@ import java.text.SimpleDateFormat; import java.util.Date; public class Repo { - public String name; - public String baseUrl, zipUrl, manifestUrl, logUrl, manifest, version, moduleName, moduleDescription, moduleAuthor, moduleAuthorUrl; - public Date lastUpdate; - public Boolean usesRoot, usesXposed; + private String mBaseUrl; + private String mZipUrl; + private String mLogUrl; + private String mManifestUrl; + private String mVersion; + private String mName; + private String mDescription; + private String mAuthor; + public String mAuthorUrl; + private String mId; + private String mVersionCode; + private String mSupportUrl; + private String mDonateUrl; + private Date lastUpdate; private Context appContext; - private SharedPreferences prefs; + private boolean mIsInstalled; + public Repo(String manifestString, Context context) { + ParseProps(manifestString); + appContext = context; + + } public Repo(String name, String url, Date updated, Context context) { appContext = context; - this.name = name; - this.baseUrl = url; + this.mName = name; + this.mBaseUrl = url; this.lastUpdate = updated; this.fetch(); } public Repo(String moduleName, String moduleDescription, String zipUrl, Date lastUpdated, Context context) { - Log.d("Magisk", "Hey, I'm a repo! My name is " + moduleName); appContext = context; - this.zipUrl = zipUrl; - this.moduleDescription = moduleDescription; - this.moduleName = moduleName; + this.mZipUrl = zipUrl; + this.mDescription = moduleDescription; + this.mName = moduleName; this.lastUpdate = lastUpdated; - + this.fetch(); } - public void fetch() { - prefs = PreferenceManager.getDefaultSharedPreferences(appContext); + private void fetch() { + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext); + if (prefs.contains("repo_" + this.mId)) { + String repoString = prefs.getString("repo_" + this.mId,""); + if (!repoString.equals("")) { + ParseProps(repoString); + } + } + if (prefs.contains("repo_isInstalled_" + this.mId)) { + mIsInstalled = prefs.getBoolean("repo_isInstalled_" + this.mId,false); + + } + WebRequest webreq = new WebRequest(); // Construct initial url for contents - Log.d("Magisk", "Manifest string is: " + baseUrl + "/contents/"); - String repoString = webreq.makeWebServiceCall(baseUrl + "/contents/", WebRequest.GET); - + Log.d("Magisk", "Manifest string is: " + mBaseUrl + "/contents/"); + String repoString = webreq.makeWebServiceCall(mBaseUrl + "/contents/", WebRequest.GET); try { JSONArray repoArray = new JSONArray(repoString); - for (int f = 0; f < repoArray.length(); f++) { JSONObject jsonobject = repoArray.getJSONObject(f); String name = jsonobject.getString("name"); if (name.contains(".zip")) { - this.zipUrl = jsonobject.getString("download_url"); - } else if (name.equals("module.json")) { - this.manifestUrl = jsonobject.getString("download_url"); - } else if (name.equals("Changelog.txt")) { - this.logUrl = jsonobject.getString("download_url"); + this.mZipUrl = jsonobject.getString("download_url"); + } else if (name.equals("module.prop")) { + this.mManifestUrl = jsonobject.getString("download_url"); + } else if (name.equals("changelog.txt")) { + this.mLogUrl = jsonobject.getString("download_url"); } } } catch (JSONException e) { @@ -69,60 +92,159 @@ public class Repo { } Log.d("Magisk", "Inner fetch: " + repoString); - try { - WebRequest jsonReq = new WebRequest(); - // Construct initial url for contents - String manifestString = webreq.makeWebServiceCall(this.manifestUrl, WebRequest.GET); - JSONObject manifestObject = new JSONObject(manifestString); - Log.d("Magisk", "Object: " + manifestObject.toString()); - version = manifestObject.getString("versionCode"); - moduleName = manifestObject.getString("moduleName"); - moduleDescription = manifestObject.getString("moduleDescription"); - moduleAuthor = manifestObject.getString("moduleAuthor"); - usesRoot = Boolean.getBoolean(manifestObject.getString("usesRoot")); - usesXposed = Boolean.getBoolean(manifestObject.getString("usesXposed")); - SharedPreferences.Editor editor = prefs.edit(); - String prefsString = "[{\"moduleDescription\":\"" + moduleDescription + "\"," - + "\"moduleName\":\"" + moduleName + "\"," - + "\"moduleAuthor\":\"" + moduleAuthor + "\"," - + "\"moduleAuthorUrl\":\"" + moduleAuthorUrl + "\"," - + "\"usesRoot\":\"" + usesRoot + "\"," - + "\"usesXposed\":\"" + usesXposed + "\"," - + "\"zipUrl\":\"" + zipUrl + "\"," - + "\"lastUpdate\":\"" + lastUpdate + "\"," - + "\"logUrl\":\"" + logUrl + "\"}]"; - editor.putString("module_" + moduleName, prefsString); - editor.putBoolean("hasCachedRepos", true); - SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmss"); - editor.putString("updated", sdf.toString()); - Log.d("Magisk", "Storing Preferences: " + prefsString); - editor.apply(); - - } catch (JSONException e) { - e.printStackTrace(); + WebRequest propReq = new WebRequest(); + String manifestString = propReq.makeWebServiceCall(this.mManifestUrl,WebRequest.GET,true); + if (ParseProps(manifestString)) { + PutProps(manifestString); } } - public String getName() { - return moduleName; + private void PutProps(String manifestString) { + manifestString = manifestString + "zipUrl=" + mZipUrl + "\nbaseUrl=" + mBaseUrl + "\nlogUrl=" + mLogUrl + "\nmanifestUrl=" + mManifestUrl; + SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(appContext); + SharedPreferences.Editor editor = prefs.edit(); + editor.putString("repo_" + mId, manifestString); + editor.putBoolean("hasCachedRepos", true); + editor.putString("updated_" + mId, this.lastUpdate.toString()); + Log.d("Magisk", "Storing Preferences: " + manifestString); + editor.apply(); + } + private boolean ParseProps(String string) { + Log.d("Magisk","Repo: parseprops called for string " + string); + if ((string.length() <= 1) | (!string.contains("id"))) { + return false; + } else { + String lines[] = string.split("\\n"); + for (String line : lines) { + if (line != "") { + String props[] = line.split("="); + Log.d("Magisk", "Repo: Split values are " + props[0] + " and " + props[1]); + switch (props[0]) { + case "versionCode": + this.mVersionCode = props[1]; + break; + case "name": + this.mName = props[1]; + break; + case "author": + this.mAuthor = props[1]; + break; + case "id": + this.mId = props[1]; + break; + case "version": + this.mVersion = props[1]; + break; + case "description": + this.mDescription = props[1]; + break; + case "donate": + this.mDonateUrl = props[1]; + break; + case "support": + this.mSupportUrl = props[1]; + break; + case "donateUrl": + this.mDonateUrl = props[1]; + break; + case "zipUrl": + this.mZipUrl = props[1]; + break; + case "baseUrl": + this.mBaseUrl = props[1]; + break; + case "manifestUrl": + this.mManifestUrl = props[1]; + break; + default: + Log.d("Magisk", "Manifest string not recognized: " + props[0]); + break; + } + } + + } + return this.mName != null; + + } } - public String getVersion() { - return version; + public String getStringProperty(String mValue) { + switch (mValue) { + case "author": + return mAuthor; + case "id": + return mId; + case "version": + return mVersion; + case "description": + return mDescription; + case "supportUrl": + return mSupportUrl; + case "donateUrl": + return mDonateUrl; + case "baseeUrl": + return mBaseUrl; + case "zipUrl": + return mZipUrl; + default: + return null; + } + } + + public String getName() { + return mName; + } + + public String getmVersion() { + return mVersion; + } + + public int getmVersionCode() { + return Integer.valueOf(mVersionCode); } public String getDescription() { - return moduleDescription; + return mDescription; } - public String getZipUrl() { - return zipUrl; + public String getId() { + return mId; } - public String getLogUrl() { - return logUrl; + public String getmZipUrl() { + return mZipUrl; + } + + public String getmBaseUrl() { + return mBaseUrl; + } + + public String getmLogUrl() { + return mLogUrl; } -} \ No newline at end of file + public String getmAuthor() { + return mAuthor; + } + + public String getmDonateUrl() { + return mDonateUrl; + } + + public String getmManifestUrl() { + return mManifestUrl; + } + + public String getmSupportUrl() { + return mSupportUrl; + } + + public Date getLastUpdate() { + return lastUpdate; + } + + public boolean isInstalled() { return mIsInstalled; } +} + diff --git a/app/src/main/java/com/topjohnwu/magisk/module/RepoAdapter.java b/app/src/main/java/com/topjohnwu/magisk/module/RepoAdapter.java index a18d77b13..c5e3b9c0d 100644 --- a/app/src/main/java/com/topjohnwu/magisk/module/RepoAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/module/RepoAdapter.java @@ -3,29 +3,39 @@ package com.topjohnwu.magisk.module; import android.content.Context; import android.content.SharedPreferences; import android.os.AsyncTask; +import android.os.Build; import android.preference.PreferenceManager; +import android.support.annotation.NonNull; import android.util.Log; import android.widget.Toast; +import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.WebRequest; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; +import java.io.File; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; +import java.util.Collection; import java.util.Date; +import java.util.Iterator; import java.util.List; import java.util.Map; +import java.util.Set; public class RepoAdapter { private String[] result; private static String url = "https://api.github.com/orgs/Magisk-Modules-Repo/repos"; - private static List repos = new ArrayList(); + private static List repos = new ArrayList() { + + }; private static final String TAG_ID = "id"; private static final String TAG_NAME = "name"; + private static String TAG = "Magisk"; private Context activityContext; private Date updatedDate, currentDate; @@ -36,39 +46,17 @@ public class RepoAdapter { new MyAsyncTask().execute(); List out = null; } else { - Log.d("Magisk", "Building from cache"); + Log.d(TAG, "Building from cache"); Map map = prefs.getAll(); repos.clear(); - for (Map.Entry entry : map.entrySet()) { - if (entry.getKey().contains("module_")) { - String repoString = entry.getValue().toString().replace(""", "\""); - JSONArray repoArray = null; - try { - repoArray = new JSONArray(repoString); - - - for (int f = 0; f < repoArray.length(); f++) { - JSONObject jsonobject = repoArray.getJSONObject(f); - String name = entry.getKey().replace("module_", ""); - name = name.replace(" ", ""); - String moduleName, moduleDescription, zipUrl; - moduleName = jsonobject.getString("moduleName"); - moduleDescription = jsonobject.getString("moduleDescription"); - zipUrl = jsonobject.getString("zipUrl"); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'"); - try { - updatedDate = format.parse(jsonobject.getString("lastUpdate")); - } catch (ParseException e) { - e.printStackTrace(); - } - repos.add(new Repo(name, moduleDescription, zipUrl, updatedDate, activityContext)); - - } - } catch (JSONException e) { - e.printStackTrace(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + map.entrySet().stream().filter(entry -> entry.getKey().contains("repo_")).forEach(entry -> { + String repoString = entry.getValue().toString(); + if (repoString.length() >= 0) { + repos.add(new Repo(repoString,context)); } - } + }); } } @@ -120,8 +108,8 @@ public class RepoAdapter { // TODO Auto-generated catch block e.printStackTrace(); } - - if (!name.contains("Repo.github.io")) { + if ((!name.contains("Repo.github.io"))) { + //if (!name.contains("Repo.github.io") && name.contains("template")) { repos.add(new Repo(name, url, updatedDate, activityContext)); } } diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/AnimationHelper.java b/app/src/main/java/com/topjohnwu/magisk/utils/AnimationHelper.java new file mode 100644 index 000000000..ebb1d3301 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/utils/AnimationHelper.java @@ -0,0 +1,58 @@ +package com.topjohnwu.magisk.utils; + +import android.view.View; +import android.view.animation.Animation; +import android.view.animation.Transformation; +import android.widget.LinearLayout; + +public class AnimationHelper { + public static void expand(final View v) { + v.measure(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); + final int targetHeight = v.getMeasuredHeight(); + + v.getLayoutParams().height = 0; + v.setVisibility(View.VISIBLE); + Animation a = new Animation() { + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + v.getLayoutParams().height = interpolatedTime == 1 + ? LinearLayout.LayoutParams.WRAP_CONTENT + : (int) (targetHeight * interpolatedTime); + v.requestLayout(); + } + + @Override + public boolean willChangeBounds() { + return true; + } + }; + + // 1dp/ms + a.setDuration((int) (targetHeight / v.getContext().getResources().getDisplayMetrics().density)); + v.startAnimation(a); + } + + public static void collapse(final View v) { + final int initialHeight = v.getMeasuredHeight(); + + Animation a = new Animation() { + @Override + protected void applyTransformation(float interpolatedTime, Transformation t) { + if (interpolatedTime == 1) { + v.setVisibility(View.GONE); + } else { + v.getLayoutParams().height = initialHeight - (int) (initialHeight * interpolatedTime); + v.requestLayout(); + } + } + + @Override + public boolean willChangeBounds() { + return true; + } + }; + // 1dp/ms + a.setDuration((int) (initialHeight / v.getContext().getResources().getDisplayMetrics().density)); + v.startAnimation(a); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/GitAgent.java b/app/src/main/java/com/topjohnwu/magisk/utils/GitAgent.java new file mode 100644 index 000000000..927c4cfb1 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/utils/GitAgent.java @@ -0,0 +1,8 @@ +package com.topjohnwu.magisk.utils; + + +public class GitAgent { + + + +} diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java index ebe8a68aa..8c4322174 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -41,6 +41,7 @@ import java.net.URL; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.List; +import java.util.Set; public class Utils { @@ -394,9 +395,8 @@ public class Utils { Log.d("Magisk", "Reload called, online mode set to " + doReload); List magiskCache = getModList(MAGISK_CACHE_PATH); RepoAdapter mr = new RepoAdapter(); - - List magiskRepos = mr.listRepos(mContext, doReload); + for (String mod : magisk) { ModulesFragment.listModules.add(new Module(mod,mContext)); } @@ -404,7 +404,9 @@ public class Utils { ModulesFragment.listModulesCache.add(new Module(mod,mContext)); } for (Repo repo : magiskRepos) { - ModulesFragment.listModulesDownload.add(repo); + if (repo.getId() != null){ + ModulesFragment.listModulesDownload.add(repo); + } } return null; diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/WebRequest.java b/app/src/main/java/com/topjohnwu/magisk/utils/WebRequest.java index 1b782a158..171ac5a8a 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/WebRequest.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/WebRequest.java @@ -18,6 +18,7 @@ public class WebRequest { static String response = null; public final static int GET = 1; public final static int POST = 2; + private boolean addNewLine; //Constructor with no parameter public WebRequest() { @@ -31,7 +32,15 @@ public class WebRequest { * @requestmethod - http request method */ public String makeWebServiceCall(String url, int requestmethod) { + addNewLine=false; return this.makeWebServiceCall(url, requestmethod, null); + + } + + public String makeWebServiceCall(String url, int requestmethod, boolean addNewLines) { + addNewLine = addNewLines; + return this.makeWebServiceCall(url, requestmethod, null); + } /** @@ -90,7 +99,7 @@ public class WebRequest { String line; BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream())); while ((line = br.readLine()) != null) { - response += line; + response += line + "\n"; } } else { response = ""; diff --git a/app/src/main/res/drawable/ic_done_black.xml b/app/src/main/res/drawable/ic_done_black.xml new file mode 100644 index 000000000..7affe9ba9 --- /dev/null +++ b/app/src/main/res/drawable/ic_done_black.xml @@ -0,0 +1,9 @@ + + + diff --git a/app/src/main/res/layout/list_item_repo.xml b/app/src/main/res/layout/list_item_repo.xml index 353a08fc9..4eea607f8 100644 --- a/app/src/main/res/layout/list_item_repo.xml +++ b/app/src/main/res/layout/list_item_repo.xml @@ -1,4 +1,8 @@ + + + + + + + + - \ No newline at end of file + + \ No newline at end of file diff --git a/app/src/main/res/layout/list_item_repo_expanded.xml b/app/src/main/res/layout/list_item_repo_expanded.xml new file mode 100644 index 000000000..c7303199a --- /dev/null +++ b/app/src/main/res/layout/list_item_repo_expanded.xml @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/app/src/main/res/layout/single_module_fragment.xml b/app/src/main/res/layout/single_module_fragment.xml index 42363f378..e6ab2c8fc 100644 --- a/app/src/main/res/layout/single_module_fragment.xml +++ b/app/src/main/res/layout/single_module_fragment.xml @@ -1,8 +1,9 @@ - @@ -24,4 +25,4 @@ android:textStyle="italic" android:visibility="gone"/> - \ No newline at end of file + \ 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 983a104e4..6f0fe3a30 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -42,6 +42,9 @@ Cache modules No modules found + Update available + Module is up-to-date + Module is installed Module will be removed at next reboot Module will not be removed at next reboot Module will be disabled at next reboot