Commit 10efe385 authored by topjohnwu's avatar topjohnwu

Update repo fragment and adapter

parent 6933bcf7
...@@ -3,7 +3,6 @@ package com.topjohnwu.magisk; ...@@ -3,7 +3,6 @@ package com.topjohnwu.magisk;
import android.animation.Animator; import android.animation.Animator;
import android.animation.ValueAnimator; import android.animation.ValueAnimator;
import android.app.ProgressDialog; import android.app.ProgressDialog;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.net.Uri; import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
...@@ -136,7 +135,7 @@ public class MagiskFragment extends Fragment ...@@ -136,7 +135,7 @@ public class MagiskFragment extends Fragment
private boolean verity = keepVerityChkbox.isChecked(); private boolean verity = keepVerityChkbox.isChecked();
@Override @Override
public void onDownloadDone(Uri uri, Context context) { public void onDownloadDone(Uri uri) {
if (Shell.rootAccess()) { if (Shell.rootAccess()) {
magiskManager.shell.su_raw( magiskManager.shell.su_raw(
"rm -f /dev/.magisk", "rm -f /dev/.magisk",
...@@ -144,7 +143,7 @@ public class MagiskFragment extends Fragment ...@@ -144,7 +143,7 @@ public class MagiskFragment extends Fragment
"echo \"KEEPFORCEENCRYPT=" + String.valueOf(enc) + "\" >> /dev/.magisk", "echo \"KEEPFORCEENCRYPT=" + String.valueOf(enc) + "\" >> /dev/.magisk",
"echo \"KEEPVERITY=" + String.valueOf(verity) + "\" >> /dev/.magisk" "echo \"KEEPVERITY=" + String.valueOf(verity) + "\" >> /dev/.magisk"
); );
startActivity(new Intent(context, FlashActivity.class).setData(uri)); startActivity(new Intent(getActivity(), FlashActivity.class).setData(uri));
} else { } else {
Utils.showUriSnack(getActivity(), uri); Utils.showUriSnack(getActivity(), uri);
} }
......
...@@ -2,7 +2,6 @@ package com.topjohnwu.magisk; ...@@ -2,7 +2,6 @@ package com.topjohnwu.magisk;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.support.v4.view.MenuItemCompat;
import android.support.v4.widget.SwipeRefreshLayout; import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
...@@ -14,18 +13,11 @@ import android.widget.SearchView; ...@@ -14,18 +13,11 @@ import android.widget.SearchView;
import android.widget.TextView; import android.widget.TextView;
import com.topjohnwu.magisk.adapters.ReposAdapter; import com.topjohnwu.magisk.adapters.ReposAdapter;
import com.topjohnwu.magisk.adapters.SimpleSectionedRecyclerViewAdapter;
import com.topjohnwu.magisk.asyncs.LoadRepos; import com.topjohnwu.magisk.asyncs.LoadRepos;
import com.topjohnwu.magisk.asyncs.ParallelTask;
import com.topjohnwu.magisk.components.Fragment; import com.topjohnwu.magisk.components.Fragment;
import com.topjohnwu.magisk.module.Module;
import com.topjohnwu.magisk.module.Repo;
import com.topjohnwu.magisk.utils.CallbackEvent; import com.topjohnwu.magisk.utils.CallbackEvent;
import com.topjohnwu.magisk.utils.Logger; import com.topjohnwu.magisk.utils.Logger;
import java.util.ArrayList;
import java.util.List;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.Unbinder; import butterknife.Unbinder;
...@@ -37,16 +29,7 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo ...@@ -37,16 +29,7 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
@BindView(R.id.empty_rv) TextView emptyRv; @BindView(R.id.empty_rv) TextView emptyRv;
@BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout; @BindView(R.id.swipeRefreshLayout) SwipeRefreshLayout mSwipeRefreshLayout;
private List<Repo> mUpdateRepos = new ArrayList<>(); private ReposAdapter adapter;
private List<Repo> mInstalledRepos = new ArrayList<>();
private List<Repo> mOthersRepos = new ArrayList<>();
private List<Repo> fUpdateRepos = new ArrayList<>();
private List<Repo> fInstalledRepos = new ArrayList<>();
private List<Repo> fOthersRepos = new ArrayList<>();
private SimpleSectionedRecyclerViewAdapter mSectionedAdapter;
private SearchView.OnQueryTextListener searchListener;
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
...@@ -60,10 +43,9 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo ...@@ -60,10 +43,9 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
View view = inflater.inflate(R.layout.fragment_repos, container, false); View view = inflater.inflate(R.layout.fragment_repos, container, false);
unbinder = ButterKnife.bind(this, view); unbinder = ButterKnife.bind(this, view);
mSectionedAdapter = new SimpleSectionedRecyclerViewAdapter(R.layout.section, adapter = new ReposAdapter(getApplication().repoMap);
R.id.section_text, new ReposAdapter(fUpdateRepos, fInstalledRepos, fOthersRepos));
recyclerView.setAdapter(mSectionedAdapter); recyclerView.setAdapter(adapter);
mSwipeRefreshLayout.setRefreshing(true); mSwipeRefreshLayout.setRefreshing(true);
...@@ -73,38 +55,42 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo ...@@ -73,38 +55,42 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
}); });
if (getApplication().repoLoadDone.isTriggered) { if (getApplication().repoLoadDone.isTriggered) {
reloadRepos(); onTrigger(null);
updateUI();
} }
searchListener = new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
new FilterApps().exec(newText);
return false;
}
};
return view; return view;
} }
@Override @Override
public void onTrigger(CallbackEvent<Void> event) { public void onTrigger(CallbackEvent<Void> event) {
Logger.dev("ReposFragment: UI refresh triggered"); Logger.dev("ReposFragment: UI refresh triggered");
reloadRepos(); if (getApplication().repoMap.isEmpty()) {
updateUI(); recyclerView.setVisibility(View.GONE);
emptyRv.setVisibility(View.VISIBLE);
} else {
adapter.filter(getApplication().moduleMap, "");
recyclerView.setVisibility(View.VISIBLE);
emptyRv.setVisibility(View.GONE);
mSwipeRefreshLayout.setRefreshing(false);
}
} }
@Override @Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
inflater.inflate(R.menu.menu_repo, menu); inflater.inflate(R.menu.menu_repo, menu);
SearchView search = (SearchView) MenuItemCompat.getActionView(menu.findItem(R.id.repo_search)); SearchView search = (SearchView) menu.findItem(R.id.repo_search).getActionView();
search.setOnQueryTextListener(searchListener); search.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override
public boolean onQueryTextSubmit(String query) {
return false;
}
@Override
public boolean onQueryTextChange(String newText) {
adapter.filter(getApplication().moduleMap, newText);
return false;
}
});
} }
@Override @Override
...@@ -125,92 +111,4 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo ...@@ -125,92 +111,4 @@ public class ReposFragment extends Fragment implements CallbackEvent.Listener<Vo
super.onDestroyView(); super.onDestroyView();
unbinder.unbind(); unbinder.unbind();
} }
private void reloadRepos() {
mUpdateRepos.clear();
mInstalledRepos.clear();
mOthersRepos.clear();
for (Repo repo : getApplication().repoMap.values()) {
Module module = getApplication().moduleMap.get(repo.getId());
if (module != null) {
if (repo.getVersionCode() > module.getVersionCode()) {
mUpdateRepos.add(repo);
} else {
mInstalledRepos.add(repo);
}
} else {
mOthersRepos.add(repo);
}
}
fUpdateRepos.clear();
fInstalledRepos.clear();
fOthersRepos.clear();
fUpdateRepos.addAll(mUpdateRepos);
fInstalledRepos.addAll(mInstalledRepos);
fOthersRepos.addAll(mOthersRepos);
}
private void updateUI() {
if (fUpdateRepos.size() + fInstalledRepos.size() + fOthersRepos.size() == 0) {
emptyRv.setVisibility(View.VISIBLE);
recyclerView.setVisibility(View.GONE);
} else {
List<SimpleSectionedRecyclerViewAdapter.Section> sections = new ArrayList<>();
if (!fUpdateRepos.isEmpty()) {
sections.add(new SimpleSectionedRecyclerViewAdapter.Section(0, getString(R.string.update_available)));
}
if (!fInstalledRepos.isEmpty()) {
sections.add(new SimpleSectionedRecyclerViewAdapter.Section(fUpdateRepos.size(), getString(R.string.installed)));
}
if (!fOthersRepos.isEmpty()) {
sections.add(new SimpleSectionedRecyclerViewAdapter.Section(fUpdateRepos.size() + fInstalledRepos.size(), getString(R.string.not_installed)));
}
SimpleSectionedRecyclerViewAdapter.Section[] array = sections.toArray(new SimpleSectionedRecyclerViewAdapter.Section[sections.size()]);
mSectionedAdapter.setSections(array);
emptyRv.setVisibility(View.GONE);
recyclerView.setVisibility(View.VISIBLE);
}
mSwipeRefreshLayout.setRefreshing(false);
}
private class FilterApps extends ParallelTask<String, Void, Void> {
@Override
protected Void doInBackground(String... strings) {
String newText = strings[0];
fUpdateRepos.clear();
fInstalledRepos.clear();
fOthersRepos.clear();
for (Repo repo: mUpdateRepos) {
if (repo.getName().toLowerCase().contains(newText.toLowerCase())
|| repo.getAuthor().toLowerCase().contains(newText.toLowerCase())
|| repo.getDescription().toLowerCase().contains(newText.toLowerCase())
) {
fUpdateRepos.add(repo);
}
}
for (Repo repo: mInstalledRepos) {
if (repo.getName().toLowerCase().contains(newText.toLowerCase())
|| repo.getAuthor().toLowerCase().contains(newText.toLowerCase())
|| repo.getDescription().toLowerCase().contains(newText.toLowerCase())
) {
fInstalledRepos.add(repo);
}
}
for (Repo repo: mOthersRepos) {
if (repo.getName().toLowerCase().contains(newText.toLowerCase())
|| repo.getAuthor().toLowerCase().contains(newText.toLowerCase())
|| repo.getDescription().toLowerCase().contains(newText.toLowerCase())
) {
fOthersRepos.add(repo);
}
}
return null;
}
@Override
protected void onPostExecute(Void v) {
updateUI();
}
}
} }
package com.topjohnwu.magisk.adapters;
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<RecyclerView.ViewHolder> {
private static final int SECTION_TYPE = 0;
private boolean mValid = true;
private int mSectionResourceId;
private int mTextResourceId;
private RecyclerView.Adapter mBaseAdapter;
private SparseArray<Section> mSections = new SparseArray<Section>();
public SimpleSectionedRecyclerViewAdapter(int sectionResourceId, int textResourceId,
RecyclerView.Adapter baseAdapter) {
mSectionResourceId = sectionResourceId;
mTextResourceId = textResourceId;
mBaseAdapter = baseAdapter;
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) {
View view = LayoutInflater.from(parent.getContext()).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<Section>() {
@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);
}
}
...@@ -31,7 +31,7 @@ public abstract class DownloadReceiver extends BroadcastReceiver { ...@@ -31,7 +31,7 @@ public abstract class DownloadReceiver extends BroadcastReceiver {
switch (status) { switch (status) {
case DownloadManager.STATUS_SUCCESSFUL: case DownloadManager.STATUS_SUCCESSFUL:
Uri uri = Uri.parse(c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI))); Uri uri = Uri.parse(c.getString(c.getColumnIndex(DownloadManager.COLUMN_LOCAL_URI)));
onDownloadDone(uri, context); onDownloadDone(uri);
break; break;
default: default:
Toast.makeText(context, R.string.download_file_error, Toast.LENGTH_LONG).show(); Toast.makeText(context, R.string.download_file_error, Toast.LENGTH_LONG).show();
...@@ -52,5 +52,5 @@ public abstract class DownloadReceiver extends BroadcastReceiver { ...@@ -52,5 +52,5 @@ public abstract class DownloadReceiver extends BroadcastReceiver {
mFilename = filename; mFilename = filename;
} }
public abstract void onDownloadDone(Uri uri, Context context); public abstract void onDownloadDone(Uri uri);
} }
...@@ -18,7 +18,7 @@ public class ManagerUpdate extends BroadcastReceiver { ...@@ -18,7 +18,7 @@ public class ManagerUpdate extends BroadcastReceiver {
context, context,
new DownloadReceiver() { new DownloadReceiver() {
@Override @Override
public void onDownloadDone(Uri uri, Context context) { public void onDownloadDone(Uri uri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE); Intent install = new Intent(Intent.ACTION_INSTALL_PACKAGE);
install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); install.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
......
...@@ -7,7 +7,7 @@ buildscript { ...@@ -7,7 +7,7 @@ buildscript {
maven { url "https://maven.google.com" } maven { url "https://maven.google.com" }
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.0.0-alpha6' classpath 'com.android.tools.build:gradle:3.0.0-alpha7'
// NOTE: Do not place your application dependencies here; they belong // NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files // in the individual module build.gradle files
......
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