package com.amaze.filemanager.fragments.preference_fragments;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.AppCompatEditText;
import android.text.Editable;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.widget.EditText;
import android.widget.Toast;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import com.amaze.filemanager.R;
import com.amaze.filemanager.activities.MainActivity;
import com.amaze.filemanager.activities.PreferencesActivity;
import com.amaze.filemanager.ui.views.preference.PathSwitchPreference;
import com.amaze.filemanager.utils.BookSorter;
import com.amaze.filemanager.utils.OTGUtil;
import com.amaze.filemanager.utils.SimpleTextWatcher;
import com.amaze.filemanager.utils.TinyDB;
import com.amaze.filemanager.utils.color.ColorUsage;
import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import static com.amaze.filemanager.activities.MainActivity.dataUtils;
/**
* @author Emmanuel
* on 17/4/2017, at 22:49.
*/
public class FoldersPref extends PreferenceFragment implements Preference.OnPreferenceClickListener {
public static final String KEY = "name path list";
public static final String KEY_SHORTCUT_PREF = "add_shortcut";
private SharedPreferences sharedPrefs;
private PreferencesActivity activity;
private Map<Preference, Integer> position = new HashMap<>();
private ArrayList<Shortcut> currentValue;
private String numbPreferenceListener = null;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
activity = (PreferencesActivity) getActivity();
//If dataUtils is null then there's no simple way to restore it,
//except letting MainActivity deal with it
if(dataUtils == null) {
Intent i = new Intent(getActivity(), MainActivity.class);
startActivity(i);
}
// Load the preferences from an XML resource
addPreferencesFromResource(R.xml.folders_prefs);
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(activity);
currentValue = castStringListToTrioList(TinyDB.getList(sharedPrefs, String.class, KEY,
getValue()));
findPreference(KEY_SHORTCUT_PREF).setOnPreferenceClickListener(this);
for (int i = 0; i < currentValue.size(); i++) {
PathSwitchPreference p = new PathSwitchPreference(getActivity());
p.setTitle(currentValue.get(i).name);
p.setSummary(currentValue.get(i).directory);
p.setChecked(currentValue.get(i).enabled);
p.setOnPreferenceClickListener(this);
position.put(p, i);
getPreferenceScreen().addPreference(p);
}
}
@Override
public boolean onPreferenceClick(final Preference preference) {
if (sharedPrefs != null) activity.setChanged();
if (preference instanceof PathSwitchPreference) {
PathSwitchPreference p = (PathSwitchPreference) preference;
switch (p.getLastItemClicked()) {
case PathSwitchPreference.EDIT:
loadEditDialog((PathSwitchPreference) preference);
break;
case PathSwitchPreference.SWITCH:
if(numbPreferenceListener != null
&& numbPreferenceListener.equals(p.toString())) {
numbPreferenceListener = null;
return false;
}
Shortcut currentShortcut = currentValue.get(position.get(p));
if(currentShortcut.autodisabled) {
if(isRoot(currentShortcut.directory)) {
boolean showIfRoot = sharedPrefs.getBoolean(Preffrag.PREFERENCE_ROOTMODE, false);
if(!showIfRoot) {
Toast.makeText(getActivity(), R.string.rootfailure, Toast.LENGTH_SHORT).show();
numbPreferenceListener = p.toString();
p.setChecked(false);
} else {
currentShortcut = new Shortcut(p.getTitle().toString(),
p.getSummary().toString(), Shortcut.FALSE);
}
} else if(isHidden(currentShortcut.directory)) {
boolean showIfHidden = sharedPrefs.getBoolean(Preffrag.PREFERENCE_SHOW_HIDDENFILES, false);
if(!showIfHidden) {
Toast.makeText(getActivity(), R.string.hiddenfailure, Toast.LENGTH_SHORT).show();
numbPreferenceListener = p.toString();
p.setChecked(false);
} else {
currentShortcut = new Shortcut(p.getTitle().toString(),
p.getSummary().toString(), Shortcut.FALSE);
}
} else {
currentShortcut = new Shortcut(p.getTitle().toString(),
p.getSummary().toString(), Shortcut.FALSE);
}
}
if(!currentShortcut.autodisabled) {
Shortcut shortcut = new Shortcut(p.getTitle().toString(), p.getSummary().toString(),
p.isChecked() ? Shortcut.TRUE : Shortcut.FALSE);
currentValue.set(position.get(p), shortcut);
TinyDB.putList(sharedPrefs, KEY, castTrioListToStringList(currentValue));
}
break;
case PathSwitchPreference.DELETE:
loadDeleteDialog(preference);
break;
}
} else if(preference.getKey().equals(KEY_SHORTCUT_PREF)) {
if(getPreferenceScreen().getPreferenceCount() >= findPreference(KEY_SHORTCUT_PREF).getOrder())
findPreference(KEY_SHORTCUT_PREF).setOrder(getPreferenceScreen().getPreferenceCount()+10);
loadCreateDialog();
}
return false;
}
public static ArrayList<Shortcut> castStringListToTrioList(ArrayList<String> arrayList) {
ArrayList<Shortcut> newList = new ArrayList<>(arrayList.size());
for(String s : arrayList) {
newList.add(new Shortcut(s));
}
return newList;
}
protected static ArrayList<String> castTrioListToStringList(ArrayList<Shortcut> arrayList) {
ArrayList<String> newList = new ArrayList<>(arrayList.size());
for(Shortcut s : arrayList) {
newList.add(s.toRestorableString());
}
return newList;
}
public static boolean canShortcutTo(String dir, SharedPreferences pref) {
File f = new File(dir);
boolean showIfHidden = pref.getBoolean(Preffrag.PREFERENCE_SHOW_HIDDENFILES, false),
isDirSelfOrParent = dir.endsWith("/.") || dir.endsWith("/.."),
showIfRoot = pref.getBoolean(Preffrag.PREFERENCE_ROOTMODE, false);
return f.exists() && f.isDirectory()
&& (!f.isHidden() || (showIfHidden && !isDirSelfOrParent))
&& (!isRoot(dir) || showIfRoot);
// TODO: 2/5/2017 use another system that doesn't create new object
}
private static boolean isRoot(String dir) {// TODO: 5/5/2017 hardcoding root might lead to problems down the line
return !dir.contains(OTGUtil.PREFIX_OTG) && !dir.startsWith("/storage");
}
private static boolean isHidden(String dir) {
// TODO: 2/5/2017 use another system that doesn't create new object
File f = new File(dir);
return f.isHidden();
}
private ArrayList<String> getValue() {
ArrayList<String> dflt = new ArrayList<>();
ArrayList<String[]> books = dataUtils.getBooks();
if (books != null && books.size() > 0) {
Collections.sort(books, new BookSorter());
for (String[] file : books) {
dflt.add(new Shortcut(file[0], file[1], Shortcut.TRUE).toRestorableString());
}
}
return dflt;
}
private void loadCreateDialog() {
int fab_skin = activity.getColorPreference().getColor(ColorUsage.ACCENT);
LayoutInflater li = LayoutInflater.from(activity);
final View v = li.inflate(R.layout.dialog_twoedittexts, null);// TODO: 29/4/2017 make this null not null
((TextInputLayout) v.findViewById(R.id.text_input1)).setHint(getString(R.string.name));
((TextInputLayout) v.findViewById(R.id.text_input2)).setHint(getString(R.string.directory));
final AppCompatEditText editText1 = ((AppCompatEditText) v.findViewById(R.id.text1)),
editText2 = ((AppCompatEditText) v.findViewById(R.id.text2));
final MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
.title(R.string.create_shortcut)
.theme(activity.getAppTheme().getMaterialDialogTheme())
.positiveColor(fab_skin)
.positiveText(R.string.create)
.negativeColor(fab_skin)
.negativeText(android.R.string.cancel)
.customView(v, false)
.build();
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(false);
disableButtonIfTitleEmpty(editText1, dialog);
disableButtonIfNotPath(editText2, dialog);
dialog.getActionButton(DialogAction.POSITIVE)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
PathSwitchPreference p = new PathSwitchPreference(getActivity());
p.setTitle(editText1.getText());
p.setSummary(editText2.getText());
p.setOnPreferenceClickListener(FoldersPref.this);
position.put(p, currentValue.size());
getPreferenceScreen().addPreference(p);
Shortcut shortcut = new Shortcut(editText1.getText().toString(),
editText2.getText().toString(), Shortcut.TRUE);
currentValue.add(shortcut);
TinyDB.putList(sharedPrefs, KEY, castTrioListToStringList(currentValue));
dialog.dismiss();
}
});
dialog.show();
}
private void loadEditDialog(final PathSwitchPreference p) {
int fab_skin = activity.getColorPreference().getColor(ColorUsage.ACCENT);
LayoutInflater li = LayoutInflater.from(activity);
final View v = li.inflate(R.layout.dialog_twoedittexts, null);// TODO: 29/4/2017 make this null not null
((TextInputLayout) v.findViewById(R.id.text_input1)).setHint(getString(R.string.name));
((TextInputLayout) v.findViewById(R.id.text_input2)).setHint(getString(R.string.directory));
final EditText editText1 = ((EditText) v.findViewById(R.id.text1)),
editText2 = ((EditText) v.findViewById(R.id.text2));
editText1.setText(p.getTitle());
editText2.setText(p.getSummary());
final MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
.title(R.string.edit_shortcut)
.theme(activity.getAppTheme().getMaterialDialogTheme())
.positiveColor(fab_skin)
.positiveText(getString(R.string.edit).toUpperCase())// TODO: 29/4/2017 don't use toUpperCase()
.negativeColor(fab_skin)
.negativeText(android.R.string.cancel)
.customView(v, false)
.build();
dialog.getActionButton(DialogAction.POSITIVE)
.setEnabled(canShortcutTo(editText2.getText().toString(), sharedPrefs));
disableButtonIfTitleEmpty(editText1, dialog);
disableButtonIfNotPath(editText2, dialog);
dialog.getActionButton(DialogAction.POSITIVE)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
p.setTitle(editText1.getText());
p.setSummary(editText2.getText());
Shortcut shortcut = new Shortcut(editText1.getText().toString(),
editText2.getText().toString(),
p.isChecked()?Shortcut.TRUE:Shortcut.FALSE);
dataUtils.getBooks().set(position.get(p), new String[] {shortcut.name, shortcut.directory});
currentValue.set(position.get(p), shortcut);
TinyDB.putList(sharedPrefs, KEY, castTrioListToStringList(currentValue));
dialog.dismiss();
}
});
dialog.show();
}
private void loadDeleteDialog(final Preference p) {
int fab_skin = activity.getColorPreference().getColor(ColorUsage.ACCENT);
final MaterialDialog dialog = new MaterialDialog.Builder(getActivity())
.title(R.string.questiondelete_shortcut)
.theme(activity.getAppTheme().getMaterialDialogTheme())
.positiveColor(fab_skin)
.positiveText(getString(R.string.delete).toUpperCase())// TODO: 29/4/2017 don't use toUpperCase()
.negativeColor(fab_skin)
.negativeText(android.R.string.cancel)
.build();
dialog.getActionButton(DialogAction.POSITIVE)
.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
getPreferenceScreen().removePreference(p);
currentValue.remove((int) position.get(p));
TinyDB.putList(sharedPrefs, KEY, castTrioListToStringList(currentValue));
dialog.dismiss();
}
});
dialog.show();
}
private void disableButtonIfNotPath(EditText path, final MaterialDialog dialog) {
path.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void afterTextChanged(Editable s) {
dialog.getActionButton(DialogAction.POSITIVE)
.setEnabled(canShortcutTo(s.toString(), sharedPrefs));
}
});
}
private void disableButtonIfTitleEmpty(final EditText title, final MaterialDialog dialog) {
title.addTextChangedListener(new SimpleTextWatcher() {
@Override
public void afterTextChanged(Editable s) {
dialog.getActionButton(DialogAction.POSITIVE).setEnabled(title.length() > 0);
}
});
}
/**
* Contains 2 Strings and a boolean
*/
public static class Shortcut {
/**
* For explanation check TinyDB.DIVIDER
*/
static final String DIVIDER = "‚‗‗‚";
/**
* AUTOFALSE is set when a value has been changed to false not by the user but by changing
* a setting that doesn't allow access to the folder anymore. MUST NOT let user change from
* AUTOFALSE to TRUE or FALSE.
*/
public static final String TRUE = "T", FALSE = "F", AUTOFALSE = "AF";
public final String name;
public final String directory;
public final boolean enabled;
public final boolean autodisabled;
Shortcut(String name, String directory, String enabled) {
this.name = name;
this.directory = directory;
this.enabled = enabled.equals(TRUE);
this.autodisabled = enabled.equals(AUTOFALSE);
}
Shortcut(String divided) {
String[] div = TextUtils.split(divided, DIVIDER);
this.name = div[0];
this.directory = div[1];
this.enabled = div[2].equals(TRUE);
this.autodisabled = div[2].equals(AUTOFALSE);
}
String toRestorableString() {
return name + DIVIDER + directory + DIVIDER + (enabled ? TRUE:(autodisabled? AUTOFALSE:FALSE));
}
public String toString() {
return "(" + name + ", " + directory + ", " + enabled + (autodisabled? "[AUTODISABLED]":"") + ")";
}
}
}