package de.robv.android.xposed.installer;
import android.Manifest;
import android.app.ListFragment;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v13.app.FragmentCompat;
import android.support.v4.app.ActivityCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.Toolbar;
import android.util.DisplayMetrics;
import android.util.TypedValue;
import android.view.ContextMenu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import de.robv.android.xposed.installer.repo.Module;
import de.robv.android.xposed.installer.repo.ModuleVersion;
import de.robv.android.xposed.installer.util.DownloadsUtil;
import de.robv.android.xposed.installer.util.RepoLoader;
import de.robv.android.xposed.installer.util.ThemeUtil;
import static de.robv.android.xposed.installer.XposedApp.WRITE_EXTERNAL_PERMISSION;
public class ModulesBookmark extends XposedBaseActivity {
private static RepoLoader mRepoLoader;
private static View container;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ThemeUtil.setTheme(this);
setContentView(R.layout.activity_container);
mRepoLoader = RepoLoader.getInstance();
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
setSupportActionBar(toolbar);
toolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
finish();
}
});
ActionBar ab = getSupportActionBar();
if (ab != null) {
ab.setTitle(R.string.bookmarks);
ab.setDisplayHomeAsUpEnabled(true);
}
setFloating(toolbar, 0);
container = findViewById(R.id.container);
if (savedInstanceState == null) {
getFragmentManager().beginTransaction().add(R.id.container, new ModulesBookmarkFragment()).commit();
}
}
public static class ModulesBookmarkFragment extends ListFragment implements AdapterView.OnItemClickListener, SharedPreferences.OnSharedPreferenceChangeListener {
private List<Module> mBookmarkedModules = new ArrayList<>();
private BookmarkModuleAdapter mAdapter;
private SharedPreferences mBookmarksPref;
private boolean changed;
private MenuItem mClickedMenuItem = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mBookmarksPref = getActivity().getSharedPreferences("bookmarks", MODE_PRIVATE);
mBookmarksPref.registerOnSharedPreferenceChangeListener(this);
}
@Override
public void onResume() {
super.onResume();
if (changed)
getModules();
}
@Override
public void onDestroy() {
super.onDestroy();
mBookmarksPref.unregisterOnSharedPreferenceChangeListener(this);
}
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
getListView().setDivider(null);
getListView().setDividerHeight(getDp(6));
getListView().setPadding(getDp(8), getDp(8), getDp(8), getDp(8));
getListView().setOnItemClickListener(this);
getListView().setClipToPadding(false);
registerForContextMenu(getListView());
setEmptyText(getString(R.string.no_bookmark_added));
mAdapter = new BookmarkModuleAdapter(getActivity());
getModules();
setListAdapter(mAdapter);
setHasOptionsMenu(true);
}
private void getModules() {
mAdapter.clear();
mBookmarkedModules.clear();
for (String s : mBookmarksPref.getAll().keySet()) {
boolean isBookmarked = mBookmarksPref.getBoolean(s, false);
if (isBookmarked) {
Module m = mRepoLoader.getModule(s);
if (m != null) mBookmarkedModules.add(m);
}
}
Collections.sort(mBookmarkedModules, new Comparator<Module>() {
@Override
public int compare(Module mod1, Module mod2) {
return mod1.name.compareTo(mod2.name);
}
});
mAdapter.addAll(mBookmarkedModules);
mAdapter.notifyDataSetChanged();
}
private int getDp(float value) {
DisplayMetrics metrics = getResources().getDisplayMetrics();
return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, value, metrics);
}
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
Intent detailsIntent = new Intent(getActivity(), DownloadDetailsActivity.class);
detailsIntent.setData(Uri.fromParts("package", mBookmarkedModules.get(position).packageName, null));
startActivity(detailsIntent);
}
@Override
public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
changed = true;
}
@Override
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
Module module = getItemFromContextMenuInfo(menuInfo);
if (module == null)
return;
menu.setHeaderTitle(module.name);
getActivity().getMenuInflater().inflate(R.menu.context_menu_modules_bookmark, menu);
}
@Override
public boolean onContextItemSelected(MenuItem item) {
final Module module = getItemFromContextMenuInfo(
item.getMenuInfo());
if (module == null)
return false;
final String pkg = module.packageName;
ModuleVersion mv = DownloadsUtil.getStableVersion(module);
if (mv == null)
return false;
mClickedMenuItem = item;
switch (item.getItemId()) {
case R.id.install_bookmark:
DownloadsUtil.add(getActivity(), module.name, mv.downloadLink, new DownloadsUtil.DownloadFinishedCallback() {
@Override
public void onDownloadFinished(Context context, DownloadsUtil.DownloadInfo info) {
XposedApp.installApk(context, info);
}
}, DownloadsUtil.MIME_TYPES.APK);
break;
case R.id.install_remove_bookmark:
DownloadsUtil.add(getActivity(), module.name, mv.downloadLink, new DownloadsUtil.DownloadFinishedCallback() {
@Override
public void onDownloadFinished(Context context, DownloadsUtil.DownloadInfo info) {
XposedApp.installApk(context, info);
remove(pkg);
}
}, DownloadsUtil.MIME_TYPES.APK);
break;
case R.id.download_bookmark:
if (checkPermissions())
return false;
DownloadsUtil.add(getActivity(), module.name, mv.downloadLink, new DownloadsUtil.DownloadFinishedCallback() {
@Override
public void onDownloadFinished(Context context, DownloadsUtil.DownloadInfo info) {
Toast.makeText(context, getString(R.string.module_saved,
info.localFilename), Toast.LENGTH_SHORT).show();
}
}, DownloadsUtil.MIME_TYPES.APK, true, true);
break;
case R.id.download_remove_bookmark:
if (checkPermissions())
return false;
DownloadsUtil.add(getActivity(), module.name, mv.downloadLink, new DownloadsUtil.DownloadFinishedCallback() {
@Override
public void onDownloadFinished(Context context, DownloadsUtil.DownloadInfo info) {
remove(pkg);
Toast.makeText(context, getString(R.string.module_saved, info.localFilename), Toast.LENGTH_SHORT).show();
}
}, DownloadsUtil.MIME_TYPES.APK, true, true);
break;
case R.id.remove:
remove(pkg);
break;
}
return false;
}
private boolean checkPermissions() {
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, WRITE_EXTERNAL_PERMISSION);
return true;
}
return false;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == WRITE_EXTERNAL_PERMISSION) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (mClickedMenuItem != null) {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
onContextItemSelected(mClickedMenuItem);
}
}, 500);
}
} else {
Toast.makeText(getActivity(), R.string.permissionNotGranted, Toast.LENGTH_LONG).show();
}
}
}
private void remove(final String pkg) {
mBookmarksPref.edit().putBoolean(pkg, false).apply();
Snackbar.make(container, R.string.bookmark_removed, Snackbar.LENGTH_SHORT).setAction(R.string.undo, new View.OnClickListener() {
@Override
public void onClick(View v) {
mBookmarksPref.edit().putBoolean(pkg, true).apply();
getModules();
}
}).show();
getModules();
}
private Module getItemFromContextMenuInfo(ContextMenu.ContextMenuInfo menuInfo) {
AdapterView.AdapterContextMenuInfo info = (AdapterView.AdapterContextMenuInfo) menuInfo;
int position = info.position - getListView().getHeaderViewsCount();
return (position >= 0) ? (Module) getListAdapter().getItem(position) : null;
}
}
private static class BookmarkModuleAdapter extends ArrayAdapter<Module> {
public BookmarkModuleAdapter(Context context) {
super(context, R.layout.list_item_module, R.id.title);
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View view = super.getView(position, convertView, parent);
view.findViewById(R.id.checkbox).setVisibility(View.GONE);
view.findViewById(R.id.version_name).setVisibility(View.GONE);
view.findViewById(R.id.icon).setVisibility(View.GONE);
Module item = getItem(position);
((TextView) view.findViewById(R.id.title)).setText(item.name);
((TextView) view.findViewById(R.id.description))
.setText(item.summary);
return view;
}
}
}