diff --git a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java index be6d35850..7dcb0e001 100644 --- a/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/MagiskFragment.java @@ -33,12 +33,16 @@ import butterknife.BindView; import butterknife.ButterKnife; public class MagiskFragment extends Fragment { + + public static int magiskVersion, remoteMagiskVersion = -1, remoteAppVersionCode = -1; + public static String magiskLink, magiskChangelog, appLink, appChangelog, remoteAppVersion; + @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; @BindView(R.id.magiskStatusView) View magiskStatusView; @BindView(R.id.magisk_status_container) View magiskStatusContainer; @BindView(R.id.magisk_status_icon) ImageView magiskStatusIcon; - @BindView(R.id.magisk_version) TextView magiskVersion; + @BindView(R.id.magisk_version) TextView magiskVersionText; @BindView(R.id.app_updateView) View appUpdateView; @BindView(R.id.app_check_updates_container) View appCheckUpdatesContainer; @@ -53,6 +57,7 @@ public class MagiskFragment extends Fragment { @BindView(R.id.magisk_check_updates_progress) ProgressBar magiskCheckUpdatesProgress; @BindColor(R.color.grey500) int grey500; + @BindColor(android.R.color.transparent) int trans; private int colorOK, colorWarn, colorNeutral; int statusOK = R.drawable.ic_check_circle; @@ -80,24 +85,37 @@ public class MagiskFragment extends Fragment { ta1.recycle(); ta2.recycle(); - if (Utils.magiskVersion == -1) { + if (magiskVersion == -1) { magiskStatusContainer.setBackgroundColor(grey500); magiskStatusIcon.setImageResource(statusUnknown); - magiskVersion.setTextColor(grey500); - magiskVersion.setText(R.string.magisk_version_error); + magiskVersionText.setTextColor(grey500); + magiskVersionText.setText(R.string.magisk_version_error); } else { magiskStatusContainer.setBackgroundColor(colorOK); magiskStatusIcon.setImageResource(statusOK); - magiskVersion.setText(getString(R.string.magisk_version, String.valueOf(Utils.magiskVersion))); - magiskVersion.setTextColor(colorOK); + magiskVersionText.setText(getString(R.string.magisk_version, String.valueOf(magiskVersion))); + magiskVersionText.setTextColor(colorOK); } prefs = PreferenceManager.getDefaultSharedPreferences(getActivity()); mSwipeRefreshLayout.setOnRefreshListener(() -> { prefs.edit().putBoolean("update_check_done", false).apply(); + + appCheckUpdatesContainer.setBackgroundColor(trans); + magiskCheckUpdatesContainer.setBackgroundColor(trans); + + appCheckUpdatesIcon.setImageResource(0); + magiskCheckUpdatesIcon.setImageResource(0); + + appCheckUpdatesStatus.setText(null); + magiskCheckUpdatesStatus.setText(null); + + appCheckUpdatesProgress.setVisibility(View.VISIBLE); + magiskCheckUpdatesProgress.setVisibility(View.VISIBLE); + new Async.CheckUpdates(getActivity()).executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); }); @@ -139,7 +157,7 @@ public class MagiskFragment extends Fragment { builder = new AlertDialog.Builder(getActivity()); } - if (Utils.remoteMagiskVersion == -1) { + if (remoteMagiskVersion == -1) { appCheckUpdatesContainer.setBackgroundColor(colorWarn); magiskCheckUpdatesContainer.setBackgroundColor(colorWarn); @@ -151,14 +169,14 @@ public class MagiskFragment extends Fragment { magiskCheckUpdatesStatus.setText(R.string.cannot_check_updates); magiskCheckUpdatesStatus.setTextColor(colorWarn); } else { - if (Utils.remoteMagiskVersion > Utils.magiskVersion) { + if (remoteMagiskVersion > magiskVersion) { magiskCheckUpdatesContainer.setBackgroundColor(colorNeutral); magiskCheckUpdatesIcon.setImageResource(R.drawable.ic_file_download); - magiskCheckUpdatesStatus.setText(getString(R.string.magisk_update_available, String.valueOf(Utils.remoteMagiskVersion))); + magiskCheckUpdatesStatus.setText(getString(R.string.magisk_update_available, String.valueOf(remoteMagiskVersion))); magiskCheckUpdatesStatus.setTextColor(colorNeutral); magiskUpdateView.setOnClickListener(view -> builder .setTitle(getString(R.string.update_title, getString(R.string.magisk))) - .setMessage(getString(R.string.update_msg, getString(R.string.magisk), String.valueOf(Utils.remoteMagiskVersion), Utils.magiskChangelog)) + .setMessage(getString(R.string.update_msg, getString(R.string.magisk), String.valueOf(remoteMagiskVersion), magiskChangelog)) .setCancelable(true) .setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive( getActivity(), @@ -168,8 +186,8 @@ public class MagiskFragment extends Fragment { new Async.FlashZIP(mContext, uri).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); } }, - Utils.magiskLink, - "Magisk-v" + String.valueOf(Utils.remoteMagiskVersion) + ".zip")) + magiskLink, + "Magisk-v" + String.valueOf(remoteMagiskVersion) + ".zip")) .setNegativeButton(R.string.no_thanks, null) .show()); } else { @@ -179,14 +197,14 @@ public class MagiskFragment extends Fragment { magiskCheckUpdatesStatus.setTextColor(colorOK); } - if (Utils.remoteAppVersionCode > BuildConfig.VERSION_CODE) { + if (remoteAppVersionCode > BuildConfig.VERSION_CODE) { appCheckUpdatesContainer.setBackgroundColor(colorNeutral); appCheckUpdatesIcon.setImageResource(R.drawable.ic_file_download); - appCheckUpdatesStatus.setText(getString(R.string.app_update_available, Utils.remoteAppVersion)); + appCheckUpdatesStatus.setText(getString(R.string.app_update_available, remoteAppVersion)); appCheckUpdatesStatus.setTextColor(colorNeutral); appUpdateView.setOnClickListener(view -> builder .setTitle(getString(R.string.update_title, getString(R.string.app_name))) - .setMessage(getString(R.string.update_msg, getString(R.string.app_name), Utils.remoteAppVersion, Utils.appChangelog)) + .setMessage(getString(R.string.update_msg, getString(R.string.app_name), remoteAppVersion, appChangelog)) .setCancelable(true) .setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive(getActivity(), new DownloadReceiver() { @@ -199,8 +217,8 @@ public class MagiskFragment extends Fragment { mContext.startActivity(install); } }, - Utils.appLink, - "MagiskManager-v" + Utils.remoteAppVersion + ".apk")) + appLink, + "MagiskManager-v" + remoteAppVersion + ".apk")) .setNegativeButton(R.string.no_thanks, null) .show() ); @@ -215,8 +233,9 @@ public class MagiskFragment extends Fragment { appCheckUpdatesProgress.setVisibility(View.GONE); magiskCheckUpdatesProgress.setVisibility(View.GONE); + mSwipeRefreshLayout.setRefreshing(false); - if (Utils.magiskVersion == -1) { + if (magiskVersion == -1) { builder .setTitle(R.string.no_magisk_title) .setMessage(R.string.no_magisk_msg) @@ -229,106 +248,10 @@ public class MagiskFragment extends Fragment { new Async.FlashZIP(mContext, uri).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); } }, - Utils.magiskLink, - "Magisk-v" + String.valueOf(Utils.remoteMagiskVersion) + ".zip")) + magiskLink, + "Magisk-v" + String.valueOf(remoteMagiskVersion) + ".zip")) .setNegativeButton(R.string.no_thanks, null) .show(); } } - -// private class updateUI extends AsyncTask { -// -// @Override -// protected Void doInBackground(Void... voids) { -// return null; -// } -// -// @Override -// protected void onPostExecute(Void v) { -// super.onPostExecute(v); -// String theme = PreferenceManager.getDefaultSharedPreferences(getActivity()).getString("theme", ""); -// if (theme.equals("Dark")) { -// builder = new AlertDialog.Builder(getActivity(),R.style.AlertDialog_dh); -// } else { -// builder = new AlertDialog.Builder(getActivity()); -// } -// -// if (Utils.remoteMagiskVersion == -1) { -// appCheckUpdatesContainer.setBackgroundColor(colorWarn); -// magiskCheckUpdatesContainer.setBackgroundColor(colorWarn); -// -// appCheckUpdatesIcon.setImageResource(R.drawable.ic_warning); -// magiskCheckUpdatesIcon.setImageResource(R.drawable.ic_warning); -// -// appCheckUpdatesStatus.setText(R.string.cannot_check_updates); -// appCheckUpdatesStatus.setTextColor(colorWarn); -// magiskCheckUpdatesStatus.setText(R.string.cannot_check_updates); -// magiskCheckUpdatesStatus.setTextColor(colorWarn); -// } else { -// if (Utils.remoteMagiskVersion > Utils.magiskVersion) { -// magiskCheckUpdatesContainer.setBackgroundColor(colorNeutral); -// magiskCheckUpdatesIcon.setImageResource(R.drawable.ic_file_download); -// magiskCheckUpdatesStatus.setText(getString(R.string.magisk_update_available, String.valueOf(Utils.remoteMagiskVersion))); -// magiskCheckUpdatesStatus.setTextColor(colorNeutral); -// magiskUpdateView.setOnClickListener(view -> builder -// .setTitle(getString(R.string.update_title, getString(R.string.magisk))) -// .setMessage(getString(R.string.update_msg, getString(R.string.magisk), String.valueOf(Utils.remoteMagiskVersion), Utils.magiskChangelog)) -// .setCancelable(true) -// .setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive( -// getActivity(), -// new DownloadReceiver() { -// @Override -// public void task(Uri uri) { -// new Async.FlashZIP(mContext, uri).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); -// } -// }, -// Utils.magiskLink, -// "Magisk-v" + String.valueOf(Utils.remoteMagiskVersion) + ".zip")) -// .setNegativeButton(R.string.no_thanks, null) -// .show()); -// } else { -// magiskCheckUpdatesContainer.setBackgroundColor(colorOK); -// magiskCheckUpdatesIcon.setImageResource(R.drawable.ic_check_circle); -// magiskCheckUpdatesStatus.setText(getString(R.string.up_to_date, getString(R.string.magisk))); -// magiskCheckUpdatesStatus.setTextColor(colorOK); -// } -// -// if (Utils.remoteAppVersionCode > BuildConfig.VERSION_CODE) { -// appCheckUpdatesContainer.setBackgroundColor(colorNeutral); -// appCheckUpdatesIcon.setImageResource(R.drawable.ic_file_download); -// appCheckUpdatesStatus.setText(getString(R.string.app_update_available, Utils.remoteAppVersion)); -// appCheckUpdatesStatus.setTextColor(colorNeutral); -// appUpdateView.setOnClickListener(view -> builder -// .setTitle(getString(R.string.update_title, getString(R.string.app_name))) -// .setMessage(getString(R.string.update_msg, getString(R.string.app_name), Utils.remoteAppVersion, Utils.appChangelog)) -// .setCancelable(true) -// .setPositiveButton(R.string.download_install, (dialogInterface, i) -> Utils.downloadAndReceive(getActivity(), -// new DownloadReceiver() { -// @Override -// public void task(Uri uri) { -// Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE); -// install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); -// Uri content = FileProvider.getUriForFile(getActivity(), "com.topjohnwu.magisk.provider", new File(uri.getPath())); -// install.setData(content); -// mContext.startActivity(install); -// } -// }, -// Utils.appLink, -// "MagiskManager-v" + Utils.remoteAppVersion + ".apk")) -// .setNegativeButton(R.string.no_thanks, null) -// .show() -// ); -// } else { -// appCheckUpdatesContainer.setBackgroundColor(colorOK); -// appCheckUpdatesIcon.setImageResource(R.drawable.ic_check_circle); -// appCheckUpdatesStatus.setText(getString(R.string.up_to_date, getString(R.string.app_name))); -// appCheckUpdatesStatus.setTextColor(colorOK); -// -// } -// } -// -// appCheckUpdatesProgress.setVisibility(View.GONE); -// magiskCheckUpdatesProgress.setVisibility(View.GONE); -// } -// } } diff --git a/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java b/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java index 5b3183bce..2bfc6d2cb 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/ModulesFragment.java @@ -20,6 +20,7 @@ import com.ipaulpro.afilechooser.utils.FileUtils; import com.topjohnwu.magisk.module.Module; import com.topjohnwu.magisk.utils.Async; import com.topjohnwu.magisk.utils.Logger; +import com.topjohnwu.magisk.utils.ModuleHelper; import java.util.ArrayList; import java.util.List; @@ -36,7 +37,7 @@ public class ModulesFragment extends Fragment { @BindView(R.id.fab) FloatingActionButton fabio; private SharedPreferences prefs; - public static List listModules = new ArrayList<>(); + private List listModules = new ArrayList<>(); private View mView; private SharedPreferences.OnSharedPreferenceChangeListener listener; @@ -105,6 +106,7 @@ public class ModulesFragment extends Fragment { } private void updateUI() { + ModuleHelper.getModuleList(listModules); if (listModules.size() == 0) { emptyTv.setVisibility(View.VISIBLE); recyclerView.setVisibility(View.GONE); diff --git a/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java b/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java index bcfb98f9b..381227a17 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java +++ b/app/src/main/java/com/topjohnwu/magisk/ReposAdapter.java @@ -80,13 +80,6 @@ public class ReposAdapter extends RecyclerView.Adapter if (description != null) { holder.description.setText(description); } - if (repo.isInstalled()) { - holder.installedStatus.setText(context.getString(R.string.module_installed)); - holder.installedStatus.setTextColor(Color.parseColor("#14AD00")); - holder.updateStatus.setText(repo.canUpdate() ? context.getString(R.string.module_update_available) : context.getString(R.string.module_up_to_date)); - } else { - holder.installedStatus.setText(context.getString(R.string.module_not_installed)); - } View.OnClickListener listener = view -> { if (view.getId() == holder.updateImage.getId()) { @@ -148,8 +141,6 @@ public class ReposAdapter extends RecyclerView.Adapter @BindView(R.id.version_name) TextView versionName; @BindView(R.id.description) TextView description; @BindView(R.id.author) TextView author; - @BindView(R.id.installedStatus) TextView installedStatus; - @BindView(R.id.updateStatus) TextView updateStatus; @BindView(R.id.expand_layout) LinearLayout expandLayout; @BindView(R.id.update) ImageView updateImage; @BindView(R.id.installed) ImageView installedImage; diff --git a/app/src/main/java/com/topjohnwu/magisk/ReposFragment.java b/app/src/main/java/com/topjohnwu/magisk/ReposFragment.java index 28189f603..280473edd 100644 --- a/app/src/main/java/com/topjohnwu/magisk/ReposFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/ReposFragment.java @@ -8,6 +8,7 @@ import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AlertDialog; +import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -17,6 +18,7 @@ import android.widget.TextView; import com.topjohnwu.magisk.module.Repo; import com.topjohnwu.magisk.utils.Async; import com.topjohnwu.magisk.utils.Logger; +import com.topjohnwu.magisk.utils.ModuleHelper; import java.util.ArrayList; import java.util.List; @@ -26,18 +28,15 @@ import butterknife.ButterKnife; public class ReposFragment extends Fragment { - public static List mListRepos = new ArrayList<>(); + private List mListRepos = new ArrayList<>(); + private List mUpdateRepos = new ArrayList<>(); + private List mInstalledRepos = new ArrayList<>(); + private List mOthersRepos = new ArrayList<>(); @BindView(R.id.recyclerView) RecyclerView recyclerView; @BindView(R.id.empty_rv) TextView emptyTv; @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; - private View mView; - private boolean mCanUpdate; - private boolean alertUpdate; - private boolean ignoreAlertUpdate; - private String alertPackage; - private AlertDialog.Builder builder; private SharedPreferences.OnSharedPreferenceChangeListener listener; private SharedPreferences prefs; @@ -45,8 +44,8 @@ public class ReposFragment extends Fragment { @Override public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - mView = inflater.inflate(R.layout.repos_fragment, container, false); - ButterKnife.bind(this, mView); + View view = inflater.inflate(R.layout.repos_fragment, container, false); + ButterKnife.bind(this, view); mSwipeRefreshLayout.setRefreshing(true); @@ -71,95 +70,14 @@ public class ReposFragment extends Fragment { } }; - //LoadRepo(false); -// if (mListRepos.size() == 0) { -// emptyTv.setVisibility(View.VISIBLE); -// recyclerView.setVisibility(View.GONE); -// return view; -// } - //CheckForUpdates(); - //recyclerView.setAdapter(new ReposAdapter(this, mListRepos)); - - return mView; + return view; } -// private void CheckForUpdates() { -// for (int i = 0; i < mListRepos.size(); i++) { -// if (mListRepos.get(i).canUpdate()) { -// alertUpdate = true; -// mListReposToUpdate.add(mListRepos.get(i)); -// -// } -// } -// } - @Override public void onAttachFragment(Fragment childFragment) { super.onAttachFragment(childFragment); } -// private void LoadRepo(boolean doReload) { -// RepoHelper.TaskDelegate taskDelegate = result -> { -// if (result.equals("Complete")) { -// Log.d("Magisk", "ReposFragment, got delegate"); -// UpdateUI(); -// if (mView != null) { -// mView.invalidate(); -// mView.requestLayout(); -// } -// -// } -// -// }; -// Log.d("Magisk", "ReposFragment, LoadRepo called"); -// new Async.LoadRepos(getActivity()); -// } - -// private void NotifyOfAlerts() { -// if (alertUpdate && !ignoreAlertUpdate) { -// Iterator iterRepo = mListReposToUpdate.iterator(); -// while (iterRepo.hasNext()) { -// Repo repo = iterRepo.next(); -// DialogInterface.OnClickListener dialogClickListener = (dialog, which) -> { -// switch (which) { -// case DialogInterface.BUTTON_POSITIVE: -// Utils.DownloadReceiver receiver = new Utils.DownloadReceiver() { -// @Override -// public void task(File file) { -// Log.d("Magisk", "Task firing"); -// new Async.FlashZIP(getActivity(), repo.getId(), file.toString()).executeOnExecutor(AsyncTask.SERIAL_EXECUTOR); -// } -// }; -// String filename = repo.getId().replace(" ", "") + ".zip"; -// Utils.downloadAndReceive(getActivity(), receiver, repo.getZipUrl(), filename); -// -// break; -// -// case DialogInterface.BUTTON_NEGATIVE: -//// ignoreAlertUpdate = true; -//// SharedPreferences.Editor editor = prefs.edit(); -//// editor.putBoolean("ignoreUpdateAlerts", ignoreAlertUpdate); -//// editor.apply(); -// break; -// } -// }; -// -// String theme = PreferenceManager.getDefaultSharedPreferences(getActivity()).getString("theme", ""); -// Logger.dev("ReposFragment: Theme is " + theme); -// if (theme.equals("Dark")) { -// builder = new AlertDialog.Builder(getActivity(),R.style.AlertDialog_dh); -// } else { -// builder = new AlertDialog.Builder(getActivity()); -// } -// builder.setMessage("An update is available for " + repo.getName() + ". Would you like to install it?").setPositiveButton("Yes", dialogClickListener) -// .setNegativeButton("No", dialogClickListener).show(); -// iterRepo.remove(); -// -// } -// -// } -// } - @Override public void onResume() { super.onResume(); @@ -174,12 +92,31 @@ public class ReposFragment extends Fragment { } private void updateUI() { + ModuleHelper.getRepoLists(mUpdateRepos, mInstalledRepos, mOthersRepos); + mListRepos.clear(); + mListRepos.addAll(mUpdateRepos); + mListRepos.addAll(mInstalledRepos); + mListRepos.addAll(mOthersRepos); if (mListRepos.size() == 0) { emptyTv.setVisibility(View.VISIBLE); recyclerView.setVisibility(View.GONE); } else { + List sections = new ArrayList<>(); + if (!mUpdateRepos.isEmpty()) { + sections.add(new SimpleSectionedRecyclerViewAdapter.Section(0, getString(R.string.update_available))); + } + if (!mInstalledRepos.isEmpty()) { + sections.add(new SimpleSectionedRecyclerViewAdapter.Section(mUpdateRepos.size(), getString(R.string.installed))); + } + if (!mOthersRepos.isEmpty()) { + sections.add(new SimpleSectionedRecyclerViewAdapter.Section(mUpdateRepos.size() + mInstalledRepos.size(), getString(R.string.not_installed))); + } + SimpleSectionedRecyclerViewAdapter.Section[] array = sections.toArray(new SimpleSectionedRecyclerViewAdapter.Section[sections.size()]); + SimpleSectionedRecyclerViewAdapter mSectionedAdapter = new + SimpleSectionedRecyclerViewAdapter(getActivity(), R.layout.section, R.id.section_text, new ReposAdapter(mListRepos)); + mSectionedAdapter.setSections(array); recyclerView.setVisibility(View.VISIBLE); - recyclerView.setAdapter(new ReposAdapter(mListRepos)); + recyclerView.setAdapter(mSectionedAdapter); } mSwipeRefreshLayout.setRefreshing(false); } diff --git a/app/src/main/java/com/topjohnwu/magisk/SettingsFragment.java b/app/src/main/java/com/topjohnwu/magisk/SettingsFragment.java index 03dc1f728..f04b25e9e 100644 --- a/app/src/main/java/com/topjohnwu/magisk/SettingsFragment.java +++ b/app/src/main/java/com/topjohnwu/magisk/SettingsFragment.java @@ -27,7 +27,6 @@ public class SettingsFragment extends PreferenceFragment implements SharedPrefer @Override public void onCreate(Bundle savedInstanceState) { - // TODO Auto-generated method stub super.onCreate(savedInstanceState); addPreferencesFromResource(R.xml.uisettings); PreferenceManager.setDefaultValues(getActivity(), R.xml.uisettings, false); @@ -36,7 +35,7 @@ public class SettingsFragment extends PreferenceFragment implements SharedPrefer @Override public void onResume() { super.onResume(); - getActivity().setTitle("Settings"); + getActivity().setTitle(R.string.settings); PreferenceManager.getDefaultSharedPreferences(getActivity()).registerOnSharedPreferenceChangeListener(this); } @@ -58,7 +57,7 @@ public class SettingsFragment extends PreferenceFragment implements SharedPrefer CheckBoxPreference keepRootOffPreference = (CheckBoxPreference) findPreference("keep_root_off"); CheckBoxPreference hideRootNotificationPreference = (CheckBoxPreference) findPreference("hide_root_notification"); themePreference.setSummary(themePreference.getValue()); - if (Utils.magiskVersion == -1) { + if (MagiskFragment.magiskVersion == -1) { quickTilePreference.setEnabled(false); keepRootOffPreference.setEnabled(false); hideRootNotificationPreference.setEnabled(false); diff --git a/app/src/main/java/com/topjohnwu/magisk/SimpleSectionedRecyclerViewAdapter.java b/app/src/main/java/com/topjohnwu/magisk/SimpleSectionedRecyclerViewAdapter.java new file mode 100644 index 000000000..9b2295f51 --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/SimpleSectionedRecyclerViewAdapter.java @@ -0,0 +1,183 @@ +package com.topjohnwu.magisk; + +import android.content.Context; +import android.support.v7.widget.RecyclerView; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import java.util.Arrays; +import java.util.Comparator; + +public class SimpleSectionedRecyclerViewAdapter extends RecyclerView.Adapter { + + private final Context mContext; + private static final int SECTION_TYPE = 0; + + private boolean mValid = true; + private int mSectionResourceId; + private int mTextResourceId; + private LayoutInflater mLayoutInflater; + private RecyclerView.Adapter mBaseAdapter; + private SparseArray
mSections = new SparseArray
(); + + + public SimpleSectionedRecyclerViewAdapter(Context context, int sectionResourceId, int textResourceId, + RecyclerView.Adapter baseAdapter) { + + mLayoutInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mSectionResourceId = sectionResourceId; + mTextResourceId = textResourceId; + mBaseAdapter = baseAdapter; + mContext = context; + + mBaseAdapter.registerAdapterDataObserver(new RecyclerView.AdapterDataObserver() { + @Override + public void onChanged() { + mValid = mBaseAdapter.getItemCount()>0; + notifyDataSetChanged(); + } + + @Override + public void onItemRangeChanged(int positionStart, int itemCount) { + mValid = mBaseAdapter.getItemCount()>0; + notifyItemRangeChanged(positionStart, itemCount); + } + + @Override + public void onItemRangeInserted(int positionStart, int itemCount) { + mValid = mBaseAdapter.getItemCount()>0; + notifyItemRangeInserted(positionStart, itemCount); + } + + @Override + public void onItemRangeRemoved(int positionStart, int itemCount) { + mValid = mBaseAdapter.getItemCount()>0; + notifyItemRangeRemoved(positionStart, itemCount); + } + }); + } + + + public static class SectionViewHolder extends RecyclerView.ViewHolder { + + public TextView title; + + public SectionViewHolder(View view, int mTextResourceid) { + super(view); + title = (TextView) view.findViewById(mTextResourceid); + } + } + + @Override + public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int typeView) { + if (typeView == SECTION_TYPE) { + final View view = LayoutInflater.from(mContext).inflate(mSectionResourceId, parent, false); + return new SectionViewHolder(view,mTextResourceId); + }else{ + return mBaseAdapter.onCreateViewHolder(parent, typeView -1); + } + } + + @Override + public void onBindViewHolder(RecyclerView.ViewHolder sectionViewHolder, int position) { + if (isSectionHeaderPosition(position)) { + ((SectionViewHolder)sectionViewHolder).title.setText(mSections.get(position).title); + }else{ + mBaseAdapter.onBindViewHolder(sectionViewHolder,sectionedPositionToPosition(position)); + } + + } + + @Override + public int getItemViewType(int position) { + return isSectionHeaderPosition(position) + ? SECTION_TYPE + : mBaseAdapter.getItemViewType(sectionedPositionToPosition(position)) +1 ; + } + + + public static class Section { + int firstPosition; + int sectionedPosition; + CharSequence title; + + public Section(int firstPosition, CharSequence title) { + this.firstPosition = firstPosition; + this.title = title; + } + + public CharSequence getTitle() { + return title; + } + } + + + public void setSections(Section[] sections) { + mSections.clear(); + + Arrays.sort(sections, new Comparator
() { + @Override + public int compare(Section o, Section o1) { + return (o.firstPosition == o1.firstPosition) + ? 0 + : ((o.firstPosition < o1.firstPosition) ? -1 : 1); + } + }); + + int offset = 0; // offset positions for the headers we're adding + for (Section section : sections) { + section.sectionedPosition = section.firstPosition + offset; + mSections.append(section.sectionedPosition, section); + ++offset; + } + + notifyDataSetChanged(); + } + + public int positionToSectionedPosition(int position) { + int offset = 0; + for (int i = 0; i < mSections.size(); i++) { + if (mSections.valueAt(i).firstPosition > position) { + break; + } + ++offset; + } + return position + offset; + } + + public int sectionedPositionToPosition(int sectionedPosition) { + if (isSectionHeaderPosition(sectionedPosition)) { + return RecyclerView.NO_POSITION; + } + + int offset = 0; + for (int i = 0; i < mSections.size(); i++) { + if (mSections.valueAt(i).sectionedPosition > sectionedPosition) { + break; + } + --offset; + } + return sectionedPosition + offset; + } + + public boolean isSectionHeaderPosition(int position) { + return mSections.get(position) != null; + } + + + @Override + public long getItemId(int position) { + return isSectionHeaderPosition(position) + ? Integer.MAX_VALUE - mSections.indexOfKey(position) + : mBaseAdapter.getItemId(sectionedPositionToPosition(position)); + } + + @Override + public int getItemCount() { + return (mValid ? mBaseAdapter.getItemCount() + mSections.size() : 0); + } + +} diff --git a/app/src/main/java/com/topjohnwu/magisk/module/BaseModule.java b/app/src/main/java/com/topjohnwu/magisk/module/BaseModule.java index 4b996642c..6926c41b6 100644 --- a/app/src/main/java/com/topjohnwu/magisk/module/BaseModule.java +++ b/app/src/main/java/com/topjohnwu/magisk/module/BaseModule.java @@ -8,7 +8,7 @@ import java.util.List; public abstract class BaseModule { protected String mId, mName, mVersion, mAuthor, mDescription, mSupportUrl, mDonateUrl; - protected boolean mIsCacheModule = false, mCanUpdate = false; + protected boolean mIsCacheModule = false; protected int mVersionCode = 0; protected void parseProps(List props) { parseProps(props.toArray(new String[props.size()])); } @@ -54,7 +54,6 @@ public abstract class BaseModule { this.mIsCacheModule = Boolean.parseBoolean(prop[1]); break; default: - Log.d("Magisk", "Module: Manifest string not recognized: " + prop[0]); break; } } @@ -97,12 +96,4 @@ public abstract class BaseModule { public String getSupportUrl() { return mSupportUrl; } - - public void setUpdate() { - mCanUpdate = true; - } - - public boolean canUpdate() { - return mCanUpdate; - } } 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 4dcafa396..20c7c3742 100644 --- a/app/src/main/java/com/topjohnwu/magisk/module/Module.java +++ b/app/src/main/java/com/topjohnwu/magisk/module/Module.java @@ -1,7 +1,7 @@ package com.topjohnwu.magisk.module; import com.topjohnwu.magisk.utils.Logger; -import com.topjohnwu.magisk.utils.RepoHelper; +import com.topjohnwu.magisk.utils.ModuleHelper; import com.topjohnwu.magisk.utils.Utils; public class Module extends BaseModule { @@ -32,17 +32,6 @@ public class Module extends BaseModule { } - public void checkUpdate() { - Repo repo = RepoHelper.repoMap.get(mId); - if (repo != null) { - repo.setInstalled(); - if (repo.getVersionCode() > mVersionCode) { - repo.setUpdate(); - mCanUpdate = true; - } - } - } - public void createDisableFile() { mEnable = !Utils.createFile(mDisableFile); } 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 6d7278cbb..013bd9475 100644 --- a/app/src/main/java/com/topjohnwu/magisk/module/Repo.java +++ b/app/src/main/java/com/topjohnwu/magisk/module/Repo.java @@ -6,6 +6,7 @@ import android.preference.PreferenceManager; import android.util.Log; import com.topjohnwu.magisk.R; +import com.topjohnwu.magisk.utils.ModuleHelper; import com.topjohnwu.magisk.utils.Utils; import com.topjohnwu.magisk.utils.WebRequest; @@ -18,7 +19,6 @@ import java.util.Date; public class Repo extends BaseModule { protected String repoName, mLogUrl, mManifestUrl, mZipUrl; protected Date mLastUpdate; - protected boolean mIsInstalled = false; public Repo(Context context, String name, Date lastUpdate) { repoName = name; @@ -42,10 +42,6 @@ public class Repo extends BaseModule { } } - public void setInstalled() { - mIsInstalled = true; - } - public String getZipUrl() { return mZipUrl; } @@ -61,6 +57,4 @@ public class Repo extends BaseModule { public Date getLastUpdate() { return mLastUpdate; } - - public boolean isInstalled() { return mIsInstalled; } } diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/Async.java b/app/src/main/java/com/topjohnwu/magisk/utils/Async.java index ea81cb47e..dab2bd50b 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Async.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Async.java @@ -10,15 +10,11 @@ import android.os.Environment; import android.preference.PreferenceManager; import android.provider.OpenableColumns; import android.support.v7.app.AlertDialog; -import android.text.TextUtils; import android.util.Log; import android.widget.Toast; -import com.topjohnwu.magisk.ModulesFragment; +import com.topjohnwu.magisk.MagiskFragment; import com.topjohnwu.magisk.R; -import com.topjohnwu.magisk.ReposFragment; -import com.topjohnwu.magisk.module.Module; -import com.topjohnwu.magisk.receivers.DownloadReceiver; import org.json.JSONException; import org.json.JSONObject; @@ -30,11 +26,12 @@ import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; -import java.util.Collections; import java.util.List; public class Async { + public static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/updates/magisk_update.json"; + public static class constructEnv extends AsyncTask { Context mContext; @@ -77,21 +74,21 @@ public class Async { @Override protected Void doInBackground(Void... voids) { - String jsonStr = WebRequest.makeWebServiceCall(Utils.UPDATE_JSON, WebRequest.GET); + String jsonStr = WebRequest.makeWebServiceCall(UPDATE_JSON, WebRequest.GET); try { JSONObject json = new JSONObject(jsonStr); JSONObject magisk = json.getJSONObject("magisk"); JSONObject app = json.getJSONObject("app"); - Utils.remoteMagiskVersion = magisk.getInt("versionCode"); - Utils.magiskLink = magisk.getString("link"); - Utils.magiskChangelog = magisk.getString("changelog"); + MagiskFragment.remoteMagiskVersion = magisk.getInt("versionCode"); + MagiskFragment.magiskLink = magisk.getString("link"); + MagiskFragment.magiskChangelog = magisk.getString("changelog"); - Utils.remoteAppVersion = app.getString("version"); - Utils.remoteAppVersionCode = app.getInt("versionCode"); - Utils.appLink = app.getString("link"); - Utils.appChangelog = app.getString("changelog"); + MagiskFragment.remoteAppVersion = app.getString("version"); + MagiskFragment.remoteAppVersionCode = app.getInt("versionCode"); + MagiskFragment.appLink = app.getString("link"); + MagiskFragment.appChangelog = app.getString("changelog"); } catch (JSONException ignored) { Logger.dev("JSON error!"); @@ -116,28 +113,7 @@ public class Async { @Override protected Void doInBackground(Void... voids) { - ModulesFragment.listModules.clear(); - Logger.dev("Loading modules"); - List magisk = Utils.getModList(Utils.MAGISK_PATH); - List magiskCache = Utils.getModList(Utils.MAGISK_CACHE_PATH); - - for (String mod : magisk) { - Logger.dev("Adding modules from " + mod); - ModulesFragment.listModules.add(new Module(mod)); - } - - for (String mod : magiskCache) { - Logger.dev("Adding cache modules from " + mod); - Module cacheMod = new Module(mod); - // Prevent people forgot to change module.prop - cacheMod.setCache(); - ModulesFragment.listModules.add(cacheMod); - } - - Collections.sort(ModulesFragment.listModules, new Utils.ModuleComparator()); - - Logger.dev("Module load done"); - + ModuleHelper.createModuleMap(); return null; } @@ -158,10 +134,7 @@ public class Async { @Override protected Void doInBackground(Void... voids) { - ReposFragment.mListRepos.clear(); - RepoHelper.createRepoMap(mContext); - RepoHelper.checkUpdate(); - ReposFragment.mListRepos = RepoHelper.getSortedList(); + ModuleHelper.createRepoMap(mContext); return null; } diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/ModuleHelper.java b/app/src/main/java/com/topjohnwu/magisk/utils/ModuleHelper.java new file mode 100644 index 000000000..63816edbe --- /dev/null +++ b/app/src/main/java/com/topjohnwu/magisk/utils/ModuleHelper.java @@ -0,0 +1,141 @@ +package com.topjohnwu.magisk.utils; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.google.gson.Gson; +import com.google.gson.reflect.TypeToken; +import com.topjohnwu.magisk.R; +import com.topjohnwu.magisk.module.Module; +import com.topjohnwu.magisk.module.Repo; + +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.text.ParseException; +import java.text.SimpleDateFormat; +import java.util.Comparator; +import java.util.Date; +import java.util.List; +import java.util.Locale; +import java.util.TreeMap; + +public class ModuleHelper { + public static final String MAGISK_PATH = "/magisk"; + public static final String MAGISK_CACHE_PATH = "/cache/magisk"; + + private static final String file_key = "RepoMap"; + private static final String key = "repomap"; + private static TreeMap repoMap = new TreeMap<>(new ModuleComparator()); + private static TreeMap moduleMap = new TreeMap<>(new ModuleComparator()); + + + public static void createModuleMap() { + Logger.dev("ModuleHelper: Loading modules"); + + moduleMap.clear(); + + for (String path : Utils.getModList(MAGISK_PATH)) { + Logger.dev("ModuleHelper: Adding modules from " + path); + Module module = new Module(path); + moduleMap.put(module.getId(), module); + } + + for (String path : Utils.getModList(MAGISK_CACHE_PATH)) { + Logger.dev("ModuleHelper: Adding cache modules from " + path); + Module cacheMod = new Module(path); + // Force set to cache + cacheMod.setCache(); + moduleMap.put(cacheMod.getId(), cacheMod); + } + + Logger.dev("ModuleHelper: Module load done"); + } + + public static void createRepoMap(Context context) { + Logger.dev("ModuleHelper: Loading repos"); + + repoMap.clear(); + + Gson gson = new Gson(); + SharedPreferences prefs = context.getSharedPreferences(file_key, Context.MODE_PRIVATE); + String jsonString = prefs.getString(key, null); + + TreeMap cached = null; + + if (jsonString != null) { + cached = gson.fromJson(jsonString, new TypeToken< TreeMap >(){}.getType()); + } + + if (cached == null) { + cached = new TreeMap<>(new ModuleComparator()); + } + + // Making a request to url and getting response + String jsonStr = WebRequest.makeWebServiceCall(context.getString(R.string.url_main) + Utils.getToken(), WebRequest.GET); + if (jsonStr != null && !jsonStr.isEmpty()) { + try { + JSONArray jsonArray = new JSONArray(jsonStr); + for (int i = 0; i < jsonArray.length(); i++) { + JSONObject jsonobject = jsonArray.getJSONObject(i); + String id = jsonobject.getString("description"); + String name = jsonobject.getString("name"); + String lastUpdate = jsonobject.getString("pushed_at"); + SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); + Date updatedDate; + try { + updatedDate = format.parse(lastUpdate); + } catch (ParseException e) { + continue; + } + Repo repo = cached.get(id); + if (repo == null) { + Logger.dev("ModuleHelper: Create new repo " + id); + repoMap.put(id, new Repo(context, name, updatedDate)); + } else { + Logger.dev("ModuleHelper: Cached repo " + id); + repo.update(updatedDate); + repoMap.put(id, repo); + } + } + } catch (JSONException e) { + e.printStackTrace(); + } + + prefs.edit().putString(key, gson.toJson(repoMap)).apply(); + } + + Logger.dev("ModuleHelper: Repo load done"); + } + + public static void getModuleList(List moduleList) { + moduleList.clear(); + moduleList.addAll(moduleMap.values()); + } + + public static void getRepoLists(List update, List installed, List others) { + update.clear(); + installed.clear(); + others.clear(); + for (Repo repo : repoMap.values()) { + Module module = moduleMap.get(repo.getId()); + if (module != null) { + if (repo.getVersionCode() > module.getVersionCode()) { + update.add(repo); + } else { + installed.add(repo); + } + } else { + others.add(repo); + } + } + } + + public static class ModuleComparator implements Comparator { + @Override + public int compare(String o1, String o2) { + return o1.toLowerCase().compareTo(o2.toLowerCase()); + } + } +} diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/RepoHelper.java b/app/src/main/java/com/topjohnwu/magisk/utils/RepoHelper.java deleted file mode 100644 index d5cb32835..000000000 --- a/app/src/main/java/com/topjohnwu/magisk/utils/RepoHelper.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.topjohnwu.magisk.utils; - -import android.content.Context; -import android.content.SharedPreferences; - -import com.google.gson.Gson; -import com.google.gson.reflect.TypeToken; -import com.topjohnwu.magisk.ModulesFragment; -import com.topjohnwu.magisk.R; -import com.topjohnwu.magisk.module.Module; -import com.topjohnwu.magisk.module.Repo; - -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Locale; - -public class RepoHelper { - private static List repos = new ArrayList<>(); - private static String TAG = "Magisk"; - - private static final String file_key = "RepoMap"; - private static final String key = "repomap"; - public static HashMap repoMap; - - public static void createRepoMap(Context context) { - Gson gson = new Gson(); - SharedPreferences prefs = context.getSharedPreferences(file_key, Context.MODE_PRIVATE); - String jsonString = prefs.getString(key, null); - if (jsonString != null) { - repoMap = gson.fromJson(jsonString, new TypeToken< HashMap >(){}.getType()); - } - - if (repoMap == null) { - repoMap = new HashMap<>(); - } - - // Making a request to url and getting response - String jsonStr = WebRequest.makeWebServiceCall(context.getString(R.string.url_main) + Utils.getToken(), WebRequest.GET); - if (jsonStr != null && !jsonStr.isEmpty()) { - try { - JSONArray jsonArray = new JSONArray(jsonStr); - for (int i = 0; i < jsonArray.length(); i++) { - JSONObject jsonobject = jsonArray.getJSONObject(i); - String id = jsonobject.getString("description"); - String name = jsonobject.getString("name"); - String lastUpdate = jsonobject.getString("updated_at"); - SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US); - Date updatedDate; - try { - updatedDate = format.parse(lastUpdate); - } catch (ParseException e) { - continue; - } - Repo repo = repoMap.get(id); - if (repo == null) { - repoMap.put(id, new Repo(context, name, updatedDate)); - } else { - repo.update(updatedDate); - } - } - } catch (JSONException e) { - e.printStackTrace(); - } - jsonString = gson.toJson(repoMap); - SharedPreferences.Editor editor = prefs.edit(); - editor.putString(key, jsonString); - editor.apply(); - } - } - - public static void checkUpdate() { - for (Module module : ModulesFragment.listModules) { - module.checkUpdate(); - } - } - - public static List getSortedList() { - ArrayList list = new ArrayList<>(repoMap.values()); - Collections.sort(list, new Utils.ModuleComparator()); - return list; - } - - public interface TaskDelegate { - void taskCompletionResult(String result); - } - -} 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 bb3dd3a05..32b60f513 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/Utils.java @@ -21,6 +21,7 @@ import android.view.View; import android.widget.Toast; import com.kcoppock.broadcasttilesupport.BroadcastTileIntentBuilder; +import com.topjohnwu.magisk.MagiskFragment; import com.topjohnwu.magisk.R; import com.topjohnwu.magisk.module.BaseModule; import com.topjohnwu.magisk.receivers.DownloadReceiver; @@ -49,23 +50,17 @@ import javax.crypto.spec.DESKeySpec; public class Utils { - public static int magiskVersion, remoteMagiskVersion = -1, remoteAppVersionCode = -1; - public static String magiskLink, magiskChangelog, appLink, appChangelog, remoteAppVersion; private static final String TAG = "Magisk"; - public static final String MAGISK_PATH = "/magisk"; - public static final String MAGISK_CACHE_PATH = "/cache/magisk"; - public static final String UPDATE_JSON = "https://raw.githubusercontent.com/topjohnwu/MagiskManager/updates/magisk_update.json"; - private static final String cryptoPass = "MagiskRox666"; private static final String secret = "GTYybRBTYf5his9kQ16ZNO7qgkBJ/5MyVe4CGceAOIoXgSnnk8FTd4F1dE9p5Eus"; public static void init(Context context) { List ret = Shell.sh("getprop magisk.version"); if (ret.get(0).isEmpty()) { - magiskVersion = -1; + MagiskFragment.magiskVersion = -1; } else { - magiskVersion = Integer.parseInt(ret.get(0)); + MagiskFragment.magiskVersion = Integer.parseInt(ret.get(0)); } String toolPath = context.getApplicationInfo().dataDir + "/busybox"; Shell.su("PATH=$PATH:" + toolPath); @@ -111,7 +106,7 @@ public class Utils { } public static void toggleRoot(Boolean b, Context context) { - if (Utils.magiskVersion != -1) { + if (MagiskFragment.magiskVersion != -1) { if (b) { Shell.su("ln -s $(getprop magisk.supath) /magisk/.core/bin", "setprop magisk.root 1"); } else { @@ -126,7 +121,7 @@ public class Utils { public static void toggleAutoRoot(Boolean b, Context context) { Logger.dev("Utils: toggleAutocalled for " + b ); - if (Utils.magiskVersion != -1) { + if (MagiskFragment.magiskVersion != -1) { if (!Utils.hasServicePermission(context)) { Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS); Toast.makeText(context, "Please enable Magisk in accessibility for auto-toggle work.", Toast.LENGTH_LONG).show(); @@ -412,10 +407,4 @@ public class Utils { } - public static class ModuleComparator implements Comparator { - @Override - public int compare(BaseModule o1, BaseModule o2) { - return o1.getName().compareToIgnoreCase(o2.getName()); - } - } } \ No newline at end of file diff --git a/app/src/main/java/com/topjohnwu/magisk/utils/WebWindow.java b/app/src/main/java/com/topjohnwu/magisk/utils/WebWindow.java index 4249245ca..30d7e4633 100644 --- a/app/src/main/java/com/topjohnwu/magisk/utils/WebWindow.java +++ b/app/src/main/java/com/topjohnwu/magisk/utils/WebWindow.java @@ -21,6 +21,8 @@ public WebWindow(String title, String url, Context context) { } alert.setTitle(title); + Logger.dev("WebView: URL = " + url); + WebView wv = new WebView(context); wv.loadUrl(url); wv.setWebViewClient(new WebViewClient() { diff --git a/app/src/main/res/layout/list_item_repo.xml b/app/src/main/res/layout/list_item_repo.xml index ce307a48e..f8ae2c526 100644 --- a/app/src/main/res/layout/list_item_repo.xml +++ b/app/src/main/res/layout/list_item_repo.xml @@ -91,32 +91,15 @@ android:layout_height="wrap_content" android:layout_alignParentStart="true" android:layout_below="@id/description" - android:minHeight="100dp" android:orientation="vertical"> - - - - + android:orientation="horizontal" + android:layout_margin="15dip"> + + \ 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 d4bd437c0..711fba218 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -11,6 +11,7 @@ Modules Downloads Log + Settings Installed Magisk v%1$s @@ -46,11 +47,7 @@ (No info provided) - Cache modules No modules found - An update is available! - Module is up-to-date - Module is installed Module is not installed Module will be removed at next reboot Module will not be removed at next reboot @@ -58,6 +55,11 @@ Module will be enabled at next reboot Created by %1$s + + Update Available + Installed + Not Installed + Save to SD Send @@ -72,7 +74,7 @@ About Main developers - Topjohnwu in collaboration with Digitalhigh and Dvdandroid.]]> + topjohnwu in collaboration with Digitalhigh and Dvdandroid.]]> App\'s changelog App\'s version @@ -104,13 +106,12 @@ SuperSU It seems that you have incompatible root installed\nDo you want to install Magisk compatible root now? - + https://api.github.com/orgs/Magisk-Modules-Repo/repos?access_token= https://raw.githubusercontent.com/Magisk-Modules-Repo/%1$s/master/%2$s https://github.com/Magisk-Modules-Repo/%1$s/archive/master.zip - Settings Quick Settings Enable Quicksettings Tile Click here to enable or disable the quick settings tile.