/*
* Copyright (C) 2013 - 2014 Alexander "Evisceration" Martinz
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
package org.namelessrom.devicecontrol.modules.appmanager;
import android.annotation.TargetApi;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.graphics.drawable.ColorDrawable;
import android.os.Build;
import android.support.annotation.NonNull;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CheckBox;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.PopupMenu;
import android.widget.TextView;
import com.kennyc.bottomsheet.BottomSheet;
import com.kennyc.bottomsheet.BottomSheetListener;
import org.namelessrom.devicecontrol.R;
import org.namelessrom.devicecontrol.utils.AppHelper;
import org.namelessrom.devicecontrol.views.CardView;
import java.util.ArrayList;
import java.util.Iterator;
public class AppListAdapter extends RecyclerView.Adapter<AppListAdapter.ViewHolder> {
private final Activity mActivity;
private final BaseAppListFragment mBaseAppListFragment;
private ArrayList<AppItem> mAppList;
private ArrayList<AppItem> mFiltered;
private final AppItem.UninstallListener mUninstallListener;
private final BaseAppListFragment.AppSelectedListener mAppSelectedListener;
private final ArrayList<AppItem> mSelectedApps;
public AppListAdapter(Activity activity, BaseAppListFragment baseAppListFragment, ArrayList<AppItem> appList,
AppItem.UninstallListener uninstallListener, BaseAppListFragment.AppSelectedListener appSelectedListener) {
mActivity = activity;
mBaseAppListFragment = baseAppListFragment;
mFiltered = appList;
mUninstallListener = uninstallListener;
mAppSelectedListener = appSelectedListener;
// save original items
mAppList = new ArrayList<>(mFiltered);
mSelectedApps = new ArrayList<>();
}
public void refill(ArrayList<AppItem> appItems) {
mFiltered = appItems;
mAppList.clear();
mAppList.addAll(mFiltered);
mSelectedApps.clear();
if (mAppSelectedListener != null) {
mAppSelectedListener.onAppSelected("refreshing", mSelectedApps);
}
notifyDataSetChanged();
}
public final class ViewHolder extends RecyclerView.ViewHolder implements CompoundButton.OnCheckedChangeListener, View.OnLongClickListener {
private final CardView cardView;
private final LinearLayout container;
private final AppIconImageView appIcon;
private final TextView appLabel;
private final TextView packageName;
private final TextView appVersion;
private final CheckBox appSelector;
private AppItem appItem;
public ViewHolder(final View v) {
super(v);
cardView = (CardView) v.findViewById(R.id.card_view);
appIcon = (AppIconImageView) v.findViewById(R.id.app_icon);
appLabel = (TextView) v.findViewById(R.id.app_label);
packageName = (TextView) v.findViewById(R.id.app_package);
appVersion = (TextView) v.findViewById(R.id.app_version);
appSelector = (CheckBox) v.findViewById(R.id.app_selector);
appSelector.setOnCheckedChangeListener(this);
container = (LinearLayout) v.findViewById(R.id.app_details_container);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
container.setOnTouchListener(new View.OnTouchListener() {
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
@Override public boolean onTouch(View v, MotionEvent event) {
v.getBackground().setHotspot(event.getX(), event.getY());
return false;
}
});
}
container.setOnClickListener(new View.OnClickListener() {
@Override public void onClick(View v) {
if (mSelectedApps.size() != 0) {
appSelector.toggle();
return;
}
final Intent intent = new Intent(mActivity, AppDetailsActivity.class);
intent.putExtra(AppDetailsActivity.ARG_FROM_ACTIVITY, true);
intent.putExtra(AppDetailsActivity.ARG_PACKAGE_NAME, appItem.getPackageName());
mActivity.startActivity(intent);
}
});
container.setOnLongClickListener(this);
}
public void bind(final AppItem appItem) {
this.appItem = appItem;
// do not load the image here, we load it in onViewAttachedToWindow()
// appIcon.loadImage(appItem, null);
appLabel.setText(appItem.getLabel());
packageName.setText(appItem.getPackageName());
appVersion.setText(appItem.getVersion());
int color = ContextCompat.getColor(mActivity, R.color.graph_text_color);
appLabel.setTextColor(appItem.isSystemApp() ? ContextCompat.getColor(mActivity, R.color.red_middle) : color);
color = appItem.isEnabled() ? android.R.color.transparent : R.color.darker_gray;
cardView.setForeground(new ColorDrawable(ContextCompat.getColor(mActivity, color)));
appSelector.setChecked(mSelectedApps.contains(appItem));
}
@Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
final String packageName = appItem.getPackageName();
if (isChecked) {
mSelectedApps.add(appItem);
} else {
mSelectedApps.remove(appItem);
}
if (mAppSelectedListener != null) {
mAppSelectedListener.onAppSelected(packageName, mSelectedApps);
}
}
@Override public boolean onLongClick(View v) {
final BottomSheet.Builder builder = new BottomSheet.Builder(mActivity, R.style.AppManagerBottomSheetStyle);
builder.setTitle(appItem.getLabel()).setListener(appBottomSheetListener);
final PopupMenu popupMenu = new PopupMenu(mActivity, null);
popupMenu.inflate(R.menu.sheet_app_item);
final Menu menu = popupMenu.getMenu();
if (appItem.isEnabled()) {
menu.removeItem(R.id.sheet_enable);
if (!appItem.isRunning(mActivity)) {
menu.removeItem(R.id.sheet_force_stop);
}
} else {
menu.removeItem(R.id.sheet_disable);
menu.removeItem(R.id.sheet_force_stop);
menu.removeItem(R.id.sheet_open);
}
builder.setMenu(menu).show();
return true;
}
private final BottomSheetListener appBottomSheetListener = new BottomSheetListener() {
@Override public void onSheetShown(@NonNull BottomSheet bottomSheet) { }
@Override public void onSheetItemSelected(@NonNull BottomSheet bottomSheet, MenuItem menuItem) {
final int id = menuItem.getItemId();
switch (id) {
case R.id.sheet_open: {
final boolean success = appItem.launchActivity(mActivity);
if (!success) {
Snackbar.make(container, R.string.could_not_launch_activity, Snackbar.LENGTH_SHORT).show();
}
break;
}
case R.id.sheet_force_stop: {
AppHelper.killProcess(mActivity, appItem.getPackageName());
Snackbar.make(container, R.string.force_stopped_app, Snackbar.LENGTH_SHORT).show();
break;
}
case R.id.sheet_enable: {
appItem.enable(mDisableEnableListener);
break;
}
case R.id.sheet_disable: {
appItem.disable(mDisableEnableListener);
break;
}
case R.id.sheet_clear_cache: {
appItem.clearCache(mActivity);
Snackbar.make(container, R.string.cleared_cache, Snackbar.LENGTH_SHORT).show();
break;
}
case R.id.sheet_clear_data: {
appItem.clearData(mActivity);
Snackbar.make(container, R.string.cleared_data, Snackbar.LENGTH_SHORT).show();
break;
}
case R.id.sheet_uninstall: {
final String message;
if (appItem.isSystemApp()) {
final String label = mActivity.getString(R.string.uninstall_msg, appItem.getLabel());
message = String.format("%s\n\n%s", label, mActivity.getString(R.string.uninstall_msg_system_app));
} else {
message = mActivity.getString(R.string.uninstall_msg, appItem.getLabel());
}
new AlertDialog.Builder(mActivity)
.setMessage(message)
.setNegativeButton(android.R.string.cancel,
new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
})
.setPositiveButton(android.R.string.yes,
new DialogInterface.OnClickListener() {
@Override public void onClick(DialogInterface dialog, int which) {
appItem.uninstall(mActivity, mUninstallListener);
}
})
.show();
break;
}
}
}
@Override public void onSheetDismissed(@NonNull BottomSheet bottomSheet, @DismissEvent int i) { }
};
}
private final AppItem.DisableEnableListener mDisableEnableListener = new AppItem.DisableEnableListener() {
@Override public void OnDisabledOrEnabled() {
if (mBaseAppListFragment != null) {
mBaseAppListFragment.loadApps(true);
}
}
};
@Override public int getItemCount() { return mFiltered.size(); }
@Override public void onViewAttachedToWindow(ViewHolder holder) {
super.onViewAttachedToWindow(holder);
holder.appIcon.loadImage(holder.appItem);
}
@Override public ViewHolder onCreateViewHolder(final ViewGroup parent, final int type) {
final CardView card = (CardView) LayoutInflater.from(parent.getContext()).inflate(R.layout.card_app_item, parent, false);
return new ViewHolder(card);
}
@Override public void onBindViewHolder(final ViewHolder viewHolder, final int position) {
final AppItem appItem = mFiltered.get(position);
viewHolder.bind(appItem);
}
public void filter(String query) {
mFiltered.clear();
mFiltered.addAll(mAppList);
query = (query != null ? query.trim().toLowerCase() : null);
if (!TextUtils.isEmpty(query)) {
final Iterator<AppItem> iterator = mFiltered.iterator();
while (iterator.hasNext()) {
AppItem appItem = iterator.next();
if (!appItem.getLabel().toLowerCase().contains(query)) {
iterator.remove();
}
}
}
notifyDataSetChanged();
}
}