/*
* Copyright (C) 2015-2016 Willi Ye <williye97@gmail.com>
*
* This file is part of Kernel Adiutor.
*
* Kernel Adiutor 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.
*
* Kernel Adiutor 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 Kernel Adiutor. If not, see <http://www.gnu.org/licenses/>.
*
*/
package com.grarak.kerneladiutor.fragments.tools;
import android.Manifest;
import android.appwidget.AppWidgetManager;
import android.content.ComponentName;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Configuration;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.design.widget.Snackbar;
import android.support.v4.content.ContextCompat;
import android.support.v4.graphics.drawable.DrawableCompat;
import android.support.v7.widget.PopupMenu;
import android.support.v7.widget.SwitchCompat;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.TextView;
import com.grarak.kerneladiutor.R;
import com.grarak.kerneladiutor.activities.FilePickerActivity;
import com.grarak.kerneladiutor.activities.tools.profile.ProfileActivity;
import com.grarak.kerneladiutor.activities.tools.profile.ProfileEditActivity;
import com.grarak.kerneladiutor.activities.tools.profile.ProfileTaskerActivity;
import com.grarak.kerneladiutor.database.tools.profiles.ExportProfile;
import com.grarak.kerneladiutor.database.tools.profiles.ImportProfile;
import com.grarak.kerneladiutor.database.tools.profiles.Profiles;
import com.grarak.kerneladiutor.fragments.BaseFragment;
import com.grarak.kerneladiutor.fragments.DescriptionFragment;
import com.grarak.kerneladiutor.fragments.RecyclerViewFragment;
import com.grarak.kerneladiutor.services.boot.Service;
import com.grarak.kerneladiutor.services.profile.Tile;
import com.grarak.kerneladiutor.services.profile.Widget;
import com.grarak.kerneladiutor.utils.Prefs;
import com.grarak.kerneladiutor.utils.Utils;
import com.grarak.kerneladiutor.utils.ViewUtils;
import com.grarak.kerneladiutor.utils.kernel.cpu.CPUFreq;
import com.grarak.kerneladiutor.utils.root.Control;
import com.grarak.kerneladiutor.utils.root.RootUtils;
import com.grarak.kerneladiutor.views.dialog.Dialog;
import com.grarak.kerneladiutor.views.recyclerview.CardView;
import com.grarak.kerneladiutor.views.recyclerview.DescriptionView;
import com.grarak.kerneladiutor.views.recyclerview.RecyclerViewItem;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
/**
* Created by willi on 10.07.16.
*/
public class ProfileFragment extends RecyclerViewFragment {
public static ProfileFragment newInstance(boolean tasker) {
ProfileFragment fragment = new ProfileFragment();
fragment.mTaskerMode = tasker;
return fragment;
}
private boolean mTaskerMode;
private Profiles mProfiles;
private AsyncTask<Void, Void, List<RecyclerViewItem>> mLoader;
private boolean mLoaded;
private LinkedHashMap<String, String> mCommands;
private Dialog mDeleteDialog;
private Dialog mApplyDialog;
private Profiles.ProfileItem mExportProfile;
private Dialog mOptionsDialog;
private Dialog mDonateDialog;
private ImportProfile mImportProfile;
private Dialog mSelectDialog;
private DetailsFragment mDetailsFragment;
@Override
protected boolean showViewPager() {
return true;
}
@Override
protected boolean showTopFab() {
return !mTaskerMode;
}
@Override
protected BaseFragment getForegroundFragment() {
return mTaskerMode ? null : (mDetailsFragment = new DetailsFragment());
}
@Override
protected Drawable getTopFabDrawable() {
Drawable drawable = DrawableCompat.wrap(ContextCompat.getDrawable(getActivity(), R.drawable.ic_add));
DrawableCompat.setTint(drawable, Color.WHITE);
return drawable;
}
@Override
public int getSpanCount() {
int span = Utils.isTablet(getActivity()) ? Utils.getOrientation(getActivity()) ==
Configuration.ORIENTATION_LANDSCAPE ? 4 : 3 : Utils.getOrientation(getActivity()) ==
Configuration.ORIENTATION_LANDSCAPE ? 3 : 2;
if (itemsSize() != 0 && span > itemsSize()) {
span = itemsSize();
}
return span;
}
@Override
protected void init() {
super.init();
if (!isAdded()) return;
if (mTaskerMode) {
addViewPagerFragment(new TaskerToastFragment());
} else {
addViewPagerFragment(DescriptionFragment.newInstance(getString(R.string.profile_tasker),
getString(R.string.profile_tasker_summary)));
if (Utils.hasCMSDK()) {
addViewPagerFragment(ProfileTileFragment.newInstance(this));
}
}
if (mCommands != null) {
create(mCommands);
}
if (mDeleteDialog != null) {
mDeleteDialog.show();
}
if (mApplyDialog != null) {
mApplyDialog.show();
}
if (mExportProfile != null) {
showExportDialog();
}
if (mOptionsDialog != null) {
mOptionsDialog.show();
}
if (mDonateDialog != null) {
mDonateDialog.show();
}
if (mImportProfile != null) {
showImportDialog(mImportProfile);
}
}
@Override
protected void addItems(List<RecyclerViewItem> items) {
if (!mLoaded) {
mLoaded = true;
load(items);
}
}
private void reload() {
if (mLoader == null) {
getHandler().postDelayed(new Runnable() {
@Override
public void run() {
clearItems();
mLoader = new AsyncTask<Void, Void, List<RecyclerViewItem>>() {
@Override
protected void onPreExecute() {
super.onPreExecute();
showProgress();
}
@Override
protected List<RecyclerViewItem> doInBackground(Void... voids) {
List<RecyclerViewItem> items = new ArrayList<>();
load(items);
return items;
}
@Override
protected void onPostExecute(List<RecyclerViewItem> items) {
super.onPostExecute(items);
for (RecyclerViewItem item : items) {
addItem(item);
}
hideProgress();
mLoader = null;
}
};
mLoader.execute();
}
}, 250);
}
}
private void load(List<RecyclerViewItem> items) {
mProfiles = new Profiles(getActivity());
List<Profiles.ProfileItem> profileItems = mProfiles.getAllProfiles();
if (mTaskerMode && profileItems.size() == 0) {
Snackbar.make(getRootView(), R.string.no_profiles, Snackbar.LENGTH_LONG).show();
return;
}
for (int i = 0; i < profileItems.size(); i++) {
final int position = i;
final CardView cardView = new CardView(getActivity());
cardView.setOnMenuListener(new CardView.OnMenuListener() {
@Override
public void onMenuReady(final CardView cardView, PopupMenu popupMenu) {
Menu menu = popupMenu.getMenu();
menu.add(Menu.NONE, 0, Menu.NONE, getString(R.string.append));
menu.add(Menu.NONE, 1, Menu.NONE, getString(R.string.edit));
menu.add(Menu.NONE, 2, Menu.NONE, getString(R.string.details));
final MenuItem onBoot = menu.add(Menu.NONE, 3, Menu.NONE, getString(R.string.on_boot)).setCheckable(true);
onBoot.setChecked(mProfiles.getAllProfiles().get(position).isOnBootEnabled());
menu.add(Menu.NONE, 4, Menu.NONE, getString(R.string.export));
menu.add(Menu.NONE, 5, Menu.NONE, getString(R.string.delete));
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
public boolean onMenuItemClick(MenuItem item) {
List<Profiles.ProfileItem> items = mProfiles.getAllProfiles();
switch (item.getItemId()) {
case 0:
if (Utils.DONATED) {
Intent intent = new Intent(getActivity(), ProfileActivity.class);
intent.putExtra(ProfileActivity.POSITION_INTENT, position);
startActivityForResult(intent, 2);
} else {
mDonateDialog = ViewUtils.dialogDonate(getActivity());
mDonateDialog.show();
}
break;
case 1:
if (Utils.DONATED) {
Intent intent = new Intent(getActivity(), ProfileEditActivity.class);
intent.putExtra(ProfileEditActivity.POSITION_INTENT, position);
startActivityForResult(intent, 3);
} else {
mDonateDialog = ViewUtils.dialogDonate(getActivity());
mDonateDialog.show();
}
break;
case 2:
if (items.get(position).getName() != null) {
List<Profiles.ProfileItem.CommandItem> commands = items.get(position).getCommands();
if (commands.size() > 0) {
setForegroundText(items.get(position).getName().toUpperCase());
mDetailsFragment.setText(commands);
showForeground();
} else {
Utils.toast(R.string.profile_empty, getActivity());
}
}
break;
case 3:
onBoot.setChecked(!onBoot.isChecked());
items.get(position).enableOnBoot(onBoot.isChecked());
mProfiles.commit();
break;
case 4:
mExportProfile = items.get(position);
requestPermission(0, Manifest.permission.WRITE_EXTERNAL_STORAGE);
break;
case 5:
mDeleteDialog = ViewUtils.dialogBuilder(getString(R.string.sure_question),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
mProfiles.delete(position);
mProfiles.commit();
reload();
}
}, new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
mDeleteDialog = null;
}
}, getActivity());
mDeleteDialog.show();
break;
}
return false;
}
});
}
});
final DescriptionView descriptionView = new DescriptionView();
descriptionView.setSummary(profileItems.get(i).getName());
descriptionView.setOnItemClickListener(new RecyclerViewItem.OnItemClickListener() {
@Override
public void onClick(RecyclerViewItem item) {
if (mTaskerMode) {
mSelectDialog = ViewUtils.dialogBuilder(getString(R.string.select_question,
descriptionView.getSummary()), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
((ProfileTaskerActivity) getActivity()).finish(
descriptionView.getSummary().toString(),
mProfiles.getAllProfiles().get(position).getCommands());
}
}, new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
mSelectDialog = null;
}
}, getActivity());
mSelectDialog.show();
} else {
mApplyDialog = ViewUtils.dialogBuilder(getString(R.string.apply_question,
descriptionView.getSummary()), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
for (Profiles.ProfileItem.CommandItem command : mProfiles.getAllProfiles()
.get(position).getCommands()) {
CPUFreq.ApplyCpu applyCpu;
if (command.getCommand().startsWith("#") && ((applyCpu =
new CPUFreq.ApplyCpu(command.getCommand().substring(1)))
.toString() != null)) {
for (String applyCpuCommand : Service.getApplyCpu(applyCpu,
RootUtils.getSU())) {
Control.runSetting(applyCpuCommand, null, null, null);
}
} else {
Control.runSetting(command.getCommand(), null, null, null);
}
}
}
}, new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
mApplyDialog = null;
}
}, getActivity());
try {
mApplyDialog.show();
} catch (NullPointerException ignored) {
}
}
}
});
if (mTaskerMode) {
items.add(descriptionView);
} else {
cardView.addItem(descriptionView);
items.add(cardView);
}
}
if (!mTaskerMode) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(getActivity());
int appWidgetIds[] = appWidgetManager.getAppWidgetIds(new ComponentName(getActivity(), Widget.class));
appWidgetManager.notifyAppWidgetViewDataChanged(appWidgetIds, R.id.profile_list);
Tile.publishProfileTile(profileItems, getActivity());
}
}
@Override
protected void onTopFabClick() {
super.onTopFabClick();
mOptionsDialog = new Dialog(getActivity()).setItems(getResources().getStringArray(
R.array.profile_options), new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
switch (i) {
case 0:
startActivityForResult(new Intent(getActivity(), ProfileActivity.class), 0);
break;
case 1:
if (Utils.DONATED) {
Intent intent = new Intent(getActivity(), FilePickerActivity.class);
intent.putExtra(FilePickerActivity.PATH_INTENT, "/sdcard");
intent.putExtra(FilePickerActivity.EXTENSION_INTENT, ".json");
startActivityForResult(intent, 1);
} else {
mDonateDialog = ViewUtils.dialogDonate(getActivity())
.setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialog) {
mDonateDialog = null;
}
});
mDonateDialog.show();
}
break;
}
}
}).setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
mOptionsDialog = null;
}
});
mOptionsDialog.show();
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (data == null) return;
if (requestCode == 0 || requestCode == 2) {
LinkedHashMap<String, String> commandsList = new LinkedHashMap<>();
ArrayList<String> ids = data.getStringArrayListExtra(ProfileActivity.RESULT_ID_INTENT);
ArrayList<String> commands = data.getStringArrayListExtra(ProfileActivity.RESULT_COMMAND_INTENT);
for (int i = 0; i < ids.size(); i++) {
commandsList.put(ids.get(i), commands.get(i));
}
if (requestCode == 0) {
create(commandsList);
} else {
Profiles.ProfileItem profileItem = mProfiles.getAllProfiles().get(data.getIntExtra(
ProfileActivity.POSITION_INTENT, 0));
for (Profiles.ProfileItem.CommandItem commandItem : profileItem.getCommands()) {
if (ids.contains(commandItem.getPath())) {
profileItem.delete(commandItem);
}
}
for (String path : commandsList.keySet()) {
profileItem.putCommand(new Profiles.ProfileItem.CommandItem(
path, commandsList.get(path)));
}
mProfiles.commit();
}
} else if (requestCode == 1) {
ImportProfile importProfile = new ImportProfile(data.getStringExtra(
FilePickerActivity.RESULT_INTENT));
if (!importProfile.readable()) {
Utils.toast(R.string.import_malformed, getActivity());
return;
}
if (!importProfile.matchesVersion()) {
Utils.toast(R.string.import_wrong_version, getActivity());
return;
}
showImportDialog(importProfile);
} else if (requestCode == 3) {
reload();
}
}
private void showImportDialog(final ImportProfile importProfile) {
mImportProfile = importProfile;
ViewUtils.dialogEditText(null, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}, new ViewUtils.OnDialogEditTextListener() {
@Override
public void onClick(String text) {
if (text.isEmpty()) {
Utils.toast(R.string.name_empty, getActivity());
return;
}
for (Profiles.ProfileItem profileItem : mProfiles.getAllProfiles()) {
if (text.equals(profileItem.getName())) {
Utils.toast(getString(R.string.already_exists, text), getActivity());
return;
}
}
mProfiles.putProfile(text, importProfile.getResults());
mProfiles.commit();
reload();
}
}, getActivity()).setTitle(getString(R.string.name)).setOnDismissListener(
new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
mImportProfile = null;
}
}).show();
}
private void create(final LinkedHashMap<String, String> commands) {
mCommands = commands;
ViewUtils.dialogEditText(null, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}, new ViewUtils.OnDialogEditTextListener() {
@Override
public void onClick(String text) {
if (text.isEmpty()) {
Utils.toast(R.string.name_empty, getActivity());
return;
}
for (Profiles.ProfileItem profileItem : mProfiles.getAllProfiles()) {
if (text.equals(profileItem.getName())) {
Utils.toast(getString(R.string.already_exists, text), getActivity());
return;
}
}
mProfiles.putProfile(text, commands);
mProfiles.commit();
reload();
}
}, getActivity()).setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
mCommands = null;
}
}).setTitle(getString(R.string.name)).show();
}
@Override
public void onPermissionDenied(int request) {
super.onPermissionDenied(request);
if (request == 0) {
Utils.toast(R.string.permission_denied_write_storage, getActivity());
}
}
@Override
public void onPermissionGranted(int request) {
super.onPermissionGranted(request);
if (request == 0) {
showExportDialog();
}
}
private void showExportDialog() {
ViewUtils.dialogEditText(null, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
}, new ViewUtils.OnDialogEditTextListener() {
@Override
public void onClick(String text) {
if (text.isEmpty()) {
Utils.toast(R.string.name_empty, getActivity());
return;
}
if (new ExportProfile(mExportProfile, mProfiles.getVersion()).export(text)) {
Utils.toast(getString(R.string.exported_item, text, Utils.getInternalDataStorage()
+ "/profiles"), getActivity());
} else {
Utils.toast(getString(R.string.already_exists, text), getActivity());
}
}
}, getActivity()).setOnDismissListener(new DialogInterface.OnDismissListener() {
@Override
public void onDismiss(DialogInterface dialogInterface) {
mExportProfile = null;
}
}).setTitle(getString(R.string.name)).show();
}
@Override
public void onDestroy() {
super.onDestroy();
if (mLoader != null) {
mLoader.cancel(true);
mLoader = null;
}
mLoaded = false;
}
public static class DetailsFragment extends BaseFragment {
private TextView mCodeText;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_profile_details, container, false);
mCodeText = (TextView) rootView.findViewById(R.id.code_text);
return rootView;
}
private void setText(List<Profiles.ProfileItem.CommandItem> commands) {
StringBuilder commandsText = new StringBuilder();
for (Profiles.ProfileItem.CommandItem command : commands) {
CPUFreq.ApplyCpu applyCpu;
if (command.getCommand().startsWith("#")
& ((applyCpu =
new CPUFreq.ApplyCpu(command.getCommand().substring(1))).toString() != null)) {
for (String applyCpuCommand : Service.getApplyCpu(applyCpu, RootUtils.getSU())) {
commandsText.append(applyCpuCommand).append("\n");
}
} else {
commandsText.append(command.getCommand()).append("\n");
}
}
commandsText.setLength(commandsText.length() - 1);
if (mCodeText != null) {
mCodeText.setText(commandsText.toString());
}
}
}
public static class ProfileTileFragment extends BaseFragment {
public static ProfileTileFragment newInstance(ProfileFragment profileFragment) {
ProfileTileFragment fragment = new ProfileTileFragment();
fragment.mProfileFragment = profileFragment;
return fragment;
}
private ProfileFragment mProfileFragment;
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_profile_tile, container, false);
SwitchCompat switchCompat = (SwitchCompat) rootView.findViewById(R.id.switcher);
switchCompat.setChecked(Prefs.getBoolean("profiletile", false, getActivity()));
switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
Prefs.saveBoolean("profiletile", b, getActivity());
Tile.publishProfileTile(mProfileFragment.mProfiles.getAllProfiles(), getActivity());
}
});
return rootView;
}
}
public static class TaskerToastFragment extends BaseFragment {
@Nullable
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container,
@Nullable Bundle savedInstanceState) {
View rootView = inflater.inflate(R.layout.fragment_apply_on_boot, container, false);
((TextView) rootView.findViewById(R.id.title)).setText(getString(R.string.profile_tasker_toast));
SwitchCompat switchCompat = (SwitchCompat) rootView.findViewById(R.id.switcher);
switchCompat.setChecked(Prefs.getBoolean("showtaskertoast", true, getActivity()));
switchCompat.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean b) {
Prefs.saveBoolean("showtaskertoast", b, getActivity());
}
});
return rootView;
}
}
}