package me.ccrama.redditslide.Fragments;
import android.Manifest;
import android.app.Activity;
import android.app.Dialog;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.v4.app.ActivityCompat;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
import android.support.v7.app.AppCompatActivity;
import android.text.InputType;
import android.view.View;
import com.afollestad.materialdialogs.DialogAction;
import com.afollestad.materialdialogs.MaterialDialog;
import java.io.File;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import me.ccrama.redditslide.R;
/**
* @author Aidan Follestad (afollestad)
*/
public class FolderChooserDialogCreate extends DialogFragment implements MaterialDialog.ListCallback {
private final static String DEFAULT_TAG = "[MD_FOLDER_SELECTOR]";
private File parentFolder;
private File[] parentContents;
private boolean canGoUp = true;
private FolderCallback mCallback;
String createdFile;
public interface FolderCallback {
void onFolderSelection(@NonNull FolderChooserDialogCreate dialog, @NonNull File folder);
}
public FolderChooserDialogCreate() {
}
String[] getContentsArray() {
if (parentContents == null) return new String[]{};
String[] results = new String[parentContents.length + (canGoUp ? 1 : 0)];
if (canGoUp) results[0] = "...";
for (int i = 0; i < parentContents.length; i++)
results[canGoUp ? i + 1 : i] = parentContents[i].getName();
return results;
}
File[] listFiles() {
File[] contents = parentFolder.listFiles();
List<File> results = new ArrayList<>();
if (contents != null) {
for (File fi : contents) {
if (fi.isDirectory()) results.add(fi);
}
Collections.sort(results, new FolderSorter());
return results.toArray(new File[results.size()]);
}
return null;
}
@SuppressWarnings("ConstantConditions")
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M &&
ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) !=
PackageManager.PERMISSION_GRANTED) {
return new MaterialDialog.Builder(getActivity())
.title(com.afollestad.materialdialogs.commons.R.string.md_error_label)
.content(com.afollestad.materialdialogs.commons.R.string.md_storage_perm_error)
.positiveText(android.R.string.ok)
.build();
}
if (getArguments() == null || !getArguments().containsKey("builder"))
throw new IllegalStateException("You must create a FolderChooserDialog using the Builder.");
if (!getArguments().containsKey("current_path"))
getArguments().putString("current_path", getBuilder().mInitialPath);
parentFolder = new File(getArguments().getString("current_path"));
parentContents = listFiles();
return new MaterialDialog.Builder(getActivity())
.title(parentFolder.getAbsolutePath())
.items(getContentsArray())
.itemsCallback(this)
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
mCallback.onFolderSelection(FolderChooserDialogCreate.this, parentFolder);
}
})
.onNegative(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
}
})
.onNeutral(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
new MaterialDialog.Builder(getActivity())
.title(R.string.create_folder)
.inputType(InputType.TYPE_TEXT_VARIATION_VISIBLE_PASSWORD)
.input(getContext().getString(R.string.folder_name), "", false, new MaterialDialog.InputCallback() {
@Override
public void onInput(@NonNull MaterialDialog dialog, CharSequence input) {
createdFile = input.toString();
}
})
.alwaysCallInputCallback()
.negativeText(getBuilder().mCancelButton)
.positiveText(R.string.btn_create)
.onNegative(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
dialog.dismiss();
}
})
.onPositive(new MaterialDialog.SingleButtonCallback() {
@Override
public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) {
File toCreate = new File(parentFolder.getPath() + File.separator + createdFile);
toCreate.mkdir();
dialog.dismiss();
mCallback.onFolderSelection(FolderChooserDialogCreate.this, toCreate);
}
}).show();
}
})
.autoDismiss(false)
.positiveText(getBuilder().mChooseButton)
.negativeText(getBuilder().mCancelButton)
.neutralText(R.string.create_folder)
.build();
}
@Override
public void onSelection(MaterialDialog materialDialog, View view, int i, CharSequence s) {
if (canGoUp && i == 0) {
parentFolder = parentFolder.getParentFile();
if (parentFolder.getAbsolutePath().equals("/storage/emulated"))
parentFolder = parentFolder.getParentFile();
canGoUp = parentFolder.getParent() != null;
} else {
parentFolder = parentContents[canGoUp ? i - 1 : i];
canGoUp = true;
if (parentFolder.getAbsolutePath().equals("/storage/emulated"))
parentFolder = Environment.getExternalStorageDirectory();
}
parentContents = listFiles();
MaterialDialog dialog = (MaterialDialog) getDialog();
dialog.setTitle(parentFolder.getAbsolutePath());
getArguments().putString("current_path", parentFolder.getAbsolutePath());
dialog.setItems(getContentsArray());
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
mCallback = (FolderCallback) activity;
}
public void show(FragmentActivity context) {
final String tag = getBuilder().mTag;
Fragment frag = context.getSupportFragmentManager().findFragmentByTag(tag);
if (frag != null) {
((DialogFragment) frag).dismiss();
context.getSupportFragmentManager().beginTransaction()
.remove(frag).commit();
}
show(context.getSupportFragmentManager(), tag);
}
public static class Builder implements Serializable {
@NonNull
protected final transient AppCompatActivity mContext;
@StringRes
protected int mChooseButton;
@StringRes
protected int mCancelButton;
protected String mInitialPath;
protected String mTag;
public <ActivityType extends AppCompatActivity & FolderCallback> Builder(@NonNull ActivityType context) {
mContext = context;
mChooseButton = com.afollestad.materialdialogs.commons.R.string.md_choose_label;
mCancelButton = android.R.string.cancel;
mInitialPath = Environment.getExternalStorageDirectory().getAbsolutePath();
}
@NonNull
public Builder chooseButton(@StringRes int text) {
mChooseButton = text;
return this;
}
@NonNull
public Builder cancelButton(@StringRes int text) {
mCancelButton = text;
return this;
}
@NonNull
public Builder initialPath(@Nullable String initialPath) {
if (initialPath == null)
initialPath = File.separator;
mInitialPath = initialPath;
return this;
}
@NonNull
public Builder tag(@Nullable String tag) {
if (tag == null)
tag = DEFAULT_TAG;
mTag = tag;
return this;
}
@NonNull
public FolderChooserDialogCreate build() {
FolderChooserDialogCreate dialog = new FolderChooserDialogCreate();
Bundle args = new Bundle();
args.putSerializable("builder", this);
dialog.setArguments(args);
return dialog;
}
@NonNull
public FolderChooserDialogCreate show() {
FolderChooserDialogCreate dialog = build();
dialog.show(mContext);
return dialog;
}
}
@SuppressWarnings("ConstantConditions")
@NonNull
private Builder getBuilder() {
return (Builder) getArguments().getSerializable("builder");
}
private static class FolderSorter implements Comparator<File> {
@Override
public int compare(File lhs, File rhs) {
return lhs.getName().compareTo(rhs.getName());
}
}
}