From 46826e857d365692d553aebfdb18b1b636e4a149 Mon Sep 17 00:00:00 2001 From: Patryk Kaczmarkiewicz Date: Tue, 24 Apr 2018 18:21:29 -0600 Subject: [PATCH 1/2] Implement Open-as --- .../Fragments/FileExplorerFragment.java | 127 ++++++++++++++++-- .../ca/pkay/rcloneexplorer/OpenAsDialog.java | 75 +++++++++++ app/src/main/res/layout/open_as_dialog.xml | 70 ++++++++++ app/src/main/res/menu/file_explorer.xml | 11 +- app/src/main/res/values/strings.xml | 6 + 5 files changed, 273 insertions(+), 16 deletions(-) create mode 100644 app/src/main/java/ca/pkay/rcloneexplorer/OpenAsDialog.java create mode 100644 app/src/main/res/layout/open_as_dialog.xml diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java index 80b5a29..5de20bf 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java @@ -28,7 +28,6 @@ import android.webkit.MimeTypeMap; import android.widget.RadioButton; import android.widget.RadioGroup; -import android.widget.TextView; import android.widget.Toast; import com.afollestad.materialdialogs.DialogAction; @@ -50,6 +49,7 @@ import ca.pkay.rcloneexplorer.FilePropertiesDialog; import ca.pkay.rcloneexplorer.Items.FileItem; import ca.pkay.rcloneexplorer.MainActivity; +import ca.pkay.rcloneexplorer.OpenAsDialog; import ca.pkay.rcloneexplorer.R; import ca.pkay.rcloneexplorer.Rclone; import ca.pkay.rcloneexplorer.RecyclerViewAdapters.FileExplorerRecyclerViewAdapter; @@ -71,6 +71,7 @@ public class FileExplorerFragment extends Fragment implements FileExplorerRecy private static final int EX_FILE_PICKER_UPLOAD_RESULT = 186; private static final int EX_FILE_PICKER_DOWNLOAD_RESULT = 204; private static final int STREAMING_INTENT_RESULT = 468; + private final int MAX_STREAMING_SIZE = 500000000; private String originalToolbarTitle; private List directoryContent; private Stack pathStack; @@ -89,6 +90,7 @@ public class FileExplorerFragment extends Fragment implements FileExplorerRecy private Boolean isInMoveMode; private SpeedDialView fab; private MenuItem menuPropertiesAction; + private MenuItem menuOpenAsAction; //private NetworkStateReceiver networkStateReceiver; private Context context; @@ -246,6 +248,7 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { super.onCreateOptionsMenu(menu, inflater); inflater.inflate(R.menu.file_explorer, menu); menuPropertiesAction = menu.findItem(R.id.action_file_properties); + menuOpenAsAction = menu.findItem(R.id.action_open_as); } @Override @@ -269,6 +272,9 @@ public boolean onOptionsItemSelected(MenuItem item) { case R.id.action_file_properties: showFileProperties(); return true; + case R.id.action_open_as: + showOpenAsDialog(); + return true; default: return super.onOptionsItemSelected(item); } @@ -285,6 +291,55 @@ public void onRefresh() { fetchDirectoryTask = new FetchDirectoryContent().execute(); } + private void showOpenAsDialog() { + OpenAsDialog openAsDialog = new OpenAsDialog(); + openAsDialog.setContext(context) + .setOnClickListener(new OpenAsDialog.OnClickListener() { + @Override + public void onClickText() { + if (recyclerViewAdapter.getNumberOfSelectedItems() == 1) { + FileItem fileItem = recyclerViewAdapter.getSelectedItems().get(0); + if (fileItem.getSize() < MAX_STREAMING_SIZE) { + new DownloadAndOpen(DownloadAndOpen.OPEN_AS_TEXT).execute(fileItem); + } else { + new MaterialDialog.Builder(context) + .title(R.string.max_streaming_size_exceeded) + .neutralText(R.string.okay_confirmation) + .show(); + } + } + } + @Override + public void onClickAudio() { + if (recyclerViewAdapter.getNumberOfSelectedItems() == 1) { + new StreamTask(StreamTask.OPEN_AS_AUDIO).execute(recyclerViewAdapter.getSelectedItems().get(0)); + } + } + @Override + public void onClickVideo() { + if (recyclerViewAdapter.getNumberOfSelectedItems() == 1) { + new StreamTask(StreamTask.OPEN_AS_VIDEO).execute(recyclerViewAdapter.getSelectedItems().get(0)); + } + } + @Override + public void onClickImage() { + FileItem fileItem = recyclerViewAdapter.getSelectedItems().get(0); + if (fileItem.getSize() < MAX_STREAMING_SIZE) { + new DownloadAndOpen(DownloadAndOpen.OPEN_AS_IMAGE).execute(fileItem); + } else { + new MaterialDialog.Builder(context) + .title(R.string.max_streaming_size_exceeded) + .neutralText(R.string.okay_confirmation) + .show(); + } + + } + }); + if (getFragmentManager() != null) { + openAsDialog.show(getFragmentManager(), "open as"); + } + } + private void showFileProperties() { if (!recyclerViewAdapter.isInSelectMode() || recyclerViewAdapter.getNumberOfSelectedItems() > 2) { return; @@ -565,7 +620,7 @@ public void onFileClicked(FileItem fileItem) { if (type != null && (type.startsWith("video/") || type.startsWith("audio/"))) { // stream video or audio new StreamTask().execute(fileItem); - } else if (fileItem.getSize() < 500000000){ + } else if (fileItem.getSize() < MAX_STREAMING_SIZE){ // download and open new DownloadAndOpen().execute(fileItem); } else { @@ -613,10 +668,16 @@ public void onFilesSelected(boolean longClick) { ((FragmentActivity) context).findViewById(R.id.file_rename).setAlpha(.5f); ((FragmentActivity) context).findViewById(R.id.file_rename).setClickable(false); menuPropertiesAction.setVisible(false); + menuOpenAsAction.setVisible(false); } else { ((FragmentActivity) context).findViewById(R.id.file_rename).setAlpha(1f); ((FragmentActivity) context).findViewById(R.id.file_rename).setClickable(true); menuPropertiesAction.setVisible(true); + if (recyclerViewAdapter.getSelectedItems().get(0).isDir()) { + menuOpenAsAction.setVisible(false); + } else { + menuOpenAsAction.setVisible(true); + } } } else if (!isInMoveMode) { ((FragmentActivity) context).setTitle(remoteType); @@ -1020,10 +1081,21 @@ protected void onPostExecute(Boolean result) { @SuppressLint("StaticFieldLeak") private class DownloadAndOpen extends AsyncTask { + public static final int OPEN_AS_TEXT = 1; + public static final int OPEN_AS_IMAGE = 2; + private int openAs; private MaterialDialog materialDialog; private String fileLocation; private Process process; + DownloadAndOpen() { + this(-1); + } + + DownloadAndOpen(int openAs) { + this.openAs = openAs; + } + private void cancelProcess() { process.destroy(); } @@ -1086,12 +1158,19 @@ protected void onPostExecute(Boolean status) { } Uri sharedFileUri = FileProvider.getUriForFile(context, "ca.pkay.rcloneexplorer.fileprovider", new File(fileLocation)); Intent intent = new Intent(Intent.ACTION_VIEW, sharedFileUri); - String extension = MimeTypeMap.getFileExtensionFromUrl(sharedFileUri.toString()); - String type = context.getContentResolver().getType(sharedFileUri); - if (extension == null || extension.trim().isEmpty()) { - intent.setDataAndType(sharedFileUri, "*/*"); - } else if (type == null || type.equals("application/octet-stream")) { - intent.setDataAndType(sharedFileUri, "*/*"); + + if (openAs == OPEN_AS_TEXT) { + intent.setDataAndType(sharedFileUri,"text/*"); + } else if (openAs == OPEN_AS_IMAGE) { + intent.setDataAndType(sharedFileUri, "image/*"); + } else { + String extension = MimeTypeMap.getFileExtensionFromUrl(sharedFileUri.toString()); + String type = context.getContentResolver().getType(sharedFileUri); + if (extension == null || extension.trim().isEmpty()) { + intent.setDataAndType(sharedFileUri, "*/*"); + } else if (type == null || type.equals("application/octet-stream")) { + intent.setDataAndType(sharedFileUri, "*/*"); + } } intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); startActivity(intent); @@ -1101,6 +1180,18 @@ protected void onPostExecute(Boolean status) { @SuppressLint("StaticFieldLeak") private class StreamTask extends AsyncTask { + public static final int OPEN_AS_VIDEO = 0; + public static final int OPEN_AS_AUDIO = 1; + private int openAs; + + StreamTask() { + this(-1); + } + + StreamTask(int openAs) { + this.openAs = openAs; + } + @Override protected Void doInBackground(FileItem... fileItems) { FileItem fileItem = fileItems[0]; @@ -1113,14 +1204,22 @@ protected Void doInBackground(FileItem... fileItems) { String url = "http://127.0.0.1:8080/" + fileItem.getName(); Intent intent = new Intent(Intent.ACTION_VIEW); - String extension = fileItem.getName().substring(fileItem.getName().lastIndexOf(".") + 1); - String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); - if (type != null && type.startsWith("audio/")) { - intent.setDataAndType(Uri.parse(url), "audio/*"); - } else if (type != null && type.startsWith("video/")) { + + // open as takes precedence + if (openAs == OPEN_AS_VIDEO) { intent.setDataAndType(Uri.parse(url), "video/*"); + } else if (openAs == OPEN_AS_AUDIO) { + intent.setDataAndType(Uri.parse(url), "audio/*"); } else { - intent.setData(Uri.parse(url)); + String extension = fileItem.getName().substring(fileItem.getName().lastIndexOf(".") + 1); + String type = MimeTypeMap.getSingleton().getMimeTypeFromExtension(extension); + if (type != null && type.startsWith("audio/")) { + intent.setDataAndType(Uri.parse(url), "audio/*"); + } else if (type != null && type.startsWith("video/")) { + intent.setDataAndType(Uri.parse(url), "video/*"); + } else { + intent.setData(Uri.parse(url)); + } } startActivityForResult(intent, STREAMING_INTENT_RESULT); return null; diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/OpenAsDialog.java b/app/src/main/java/ca/pkay/rcloneexplorer/OpenAsDialog.java new file mode 100644 index 0000000..1ed0240 --- /dev/null +++ b/app/src/main/java/ca/pkay/rcloneexplorer/OpenAsDialog.java @@ -0,0 +1,75 @@ +package ca.pkay.rcloneexplorer; + +import android.app.Dialog; +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; + +public class OpenAsDialog extends DialogFragment { + + public interface OnClickListener { + void onClickText(); + void onClickAudio(); + void onClickVideo(); + void onClickImage(); + } + + private Context context; + private View view; + private OnClickListener listener; + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + LayoutInflater inflater = getActivity().getLayoutInflater(); + view = inflater.inflate(R.layout.open_as_dialog, null); + setListeners(); + builder.setView(view); + return builder.create(); + } + + private void setListeners() { + view.findViewById(R.id.open_as_text).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onClickText(); + } + }); + + view.findViewById(R.id.open_as_audio).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onClickAudio(); + } + }); + + view.findViewById(R.id.open_as_video).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onClickVideo(); + } + }); + + view.findViewById(R.id.open_as_image).setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + listener.onClickImage(); + } + }); + } + + public OpenAsDialog setOnClickListener(OnClickListener l) { + listener = l; + return this; + } + + public OpenAsDialog setContext(Context context) { + this.context = context; + return this; + } +} diff --git a/app/src/main/res/layout/open_as_dialog.xml b/app/src/main/res/layout/open_as_dialog.xml new file mode 100644 index 0000000..cf17ba1 --- /dev/null +++ b/app/src/main/res/layout/open_as_dialog.xml @@ -0,0 +1,70 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/menu/file_explorer.xml b/app/src/main/res/menu/file_explorer.xml index 4c48263..6f38609 100644 --- a/app/src/main/res/menu/file_explorer.xml +++ b/app/src/main/res/menu/file_explorer.xml @@ -17,15 +17,22 @@ + + \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0f1172f..a2e2984 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -117,4 +117,10 @@ files uploaded files failed to upload Upload failed + Properties + Open as + Text + Audio + Video + Image From bf8849593e37f56323b89148b17f6ff5121446dc Mon Sep 17 00:00:00 2001 From: Patryk Kaczmarkiewicz Date: Tue, 24 Apr 2018 19:40:36 -0600 Subject: [PATCH 2/2] Create dialogs Use custom dialogs instead of depending on a library --- .idea/caches/build_file_checksums.ser | Bin 535 -> 535 bytes README.md | 1 - app/build.gradle | 1 - .../{ => Dialogs}/FilePropertiesDialog.java | 9 +- .../rcloneexplorer/Dialogs/InputDialog.java | 159 ++++++++++++++++ .../rcloneexplorer/Dialogs/LoadingDialog.java | 90 +++++++++ .../{ => Dialogs}/OpenAsDialog.java | 9 +- .../Fragments/FileExplorerFragment.java | 176 ++++++++++-------- .../ca/pkay/rcloneexplorer/MainActivity.java | 67 +++---- ...s_popup.xml => dialog_file_properties.xml} | 0 app/src/main/res/layout/dialog_input.xml | 14 ++ .../res/layout/dialog_loading_indicator.xml | 22 +++ ...{open_as_dialog.xml => dialog_open_as.xml} | 0 .../{sort_popup.xml => dialog_sort.xml} | 0 .../about_libraries_material_dialogs.xml | 13 -- app/src/main/res/values/strings.xml | 2 +- 16 files changed, 428 insertions(+), 135 deletions(-) rename app/src/main/java/ca/pkay/rcloneexplorer/{ => Dialogs}/FilePropertiesDialog.java (95%) create mode 100644 app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/InputDialog.java create mode 100644 app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/LoadingDialog.java rename app/src/main/java/ca/pkay/rcloneexplorer/{ => Dialogs}/OpenAsDialog.java (88%) rename app/src/main/res/layout/{file_properties_popup.xml => dialog_file_properties.xml} (100%) create mode 100644 app/src/main/res/layout/dialog_input.xml create mode 100644 app/src/main/res/layout/dialog_loading_indicator.xml rename app/src/main/res/layout/{open_as_dialog.xml => dialog_open_as.xml} (100%) rename app/src/main/res/layout/{sort_popup.xml => dialog_sort.xml} (100%) delete mode 100644 app/src/main/res/values/about_libraries_material_dialogs.xml diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser index 294ee55b8c943df1c257d70954d824ae0b668d56..75ce1a6d99d9afea78fe41c701ae6eff6f165734 100644 GIT binary patch delta 33 rcmV++0N($X1eXMmm<0ODvyiczY5@_Bpl=x2{U1Xmg8tMmM^d_Y1ndu! delta 33 rcmV++0N($X1eXMmm<0JE$m_A3Y5@_R#8P>6*s(J8$g_E{KK>SX473os diff --git a/README.md b/README.md index adc2cfd..8907c3f 100644 --- a/README.md +++ b/README.md @@ -42,7 +42,6 @@ Credits/Libraries - [Font Awesome Icons](https://fontawesome.com/) - The iconic SVG, font, and CSS toolkit - [Markdown View](https://github.com/falnatsheh/MarkdownView) - MarkdownView is an Android webview with the capablity of loading Markdown text or file and display it as HTML, it uses MarkdownJ and extends Android webview. - [Material Design Icons](https://github.com/Templarian/MaterialDesign) - 2200+ Material Design Icons from the Community -- [Material Dialogs](https://github.com/afollestad/material-dialogs) - A beautiful, fluid, and customizable dialogs API - [rclone](https://github.com/ncw/rclone) - "rsync for cloud storage" - [Toasty](https://github.com/GrenderG/Toasty) - The usual Toast, but with steroids - Icon made by [Smashicons](https://www.flaticon.com/authors/smashicons) from [Flaticon](https://www.flaticon.com) diff --git a/app/build.gradle b/app/build.gradle index c457504..a051750 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -30,7 +30,6 @@ dependencies { implementation "com.android.support:support-compat:27.1.1" implementation 'com.android.support.constraint:constraint-layout:1.1.0' implementation 'com.android.support:design:27.1.1' - implementation 'com.afollestad.material-dialogs:core:0.9.6.0' implementation "com.leinardi.android:speed-dial:1.0-alpha03" implementation 'ru.bartwell:exfilepicker:2.4' implementation "com.mikepenz:aboutlibraries:6.0.8" diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/FilePropertiesDialog.java b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/FilePropertiesDialog.java similarity index 95% rename from app/src/main/java/ca/pkay/rcloneexplorer/FilePropertiesDialog.java rename to app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/FilePropertiesDialog.java index 2afafec..b74b855 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/FilePropertiesDialog.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/FilePropertiesDialog.java @@ -1,4 +1,4 @@ -package ca.pkay.rcloneexplorer; +package ca.pkay.rcloneexplorer.Dialogs; import android.annotation.SuppressLint; import android.app.Dialog; @@ -10,6 +10,7 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; @@ -17,6 +18,8 @@ import android.widget.Toast; import ca.pkay.rcloneexplorer.Items.FileItem; +import ca.pkay.rcloneexplorer.R; +import ca.pkay.rcloneexplorer.Rclone; import es.dmoral.toasty.Toasty; public class FilePropertiesDialog extends DialogFragment { @@ -40,8 +43,8 @@ public FilePropertiesDialog() { public Dialog onCreateDialog(Bundle savedInstanceState) { asyncTasks = new AsyncTask[2]; AlertDialog.Builder builder = new AlertDialog.Builder(context); - LayoutInflater inflater = getActivity().getLayoutInflater(); - view = inflater.inflate(R.layout.file_properties_popup, null); + LayoutInflater inflater = ((FragmentActivity)context).getLayoutInflater(); + view = inflater.inflate(R.layout.dialog_file_properties, null); ((TextView)view.findViewById(R.id.filename)).setText(fileItem.getName()); ((TextView)view.findViewById(R.id.file_modtime)).setText(fileItem.getHumanReadableModTime()); diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/InputDialog.java b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/InputDialog.java new file mode 100644 index 0000000..88453c6 --- /dev/null +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/InputDialog.java @@ -0,0 +1,159 @@ +package ca.pkay.rcloneexplorer.Dialogs; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.EditText; +import android.widget.TextView; + +import ca.pkay.rcloneexplorer.R; + +public class InputDialog extends DialogFragment { + + public interface OnPositive { + void onPositive(String input); + } + + private Context context; + private EditText editText; + private String title; + private int titleId; + private String message; + private int messageId; + private String positiveText; + private int positiveTextId; + private String negativeText; + private int negativeTextId; + private String filledText; + private int inputType; + private OnPositive onPositiveListener; + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + LayoutInflater inflater = ((FragmentActivity)context).getLayoutInflater(); + View view = inflater.inflate(R.layout.dialog_input, null); + editText = view.findViewById(R.id.dialog_input); + builder.setView(view); + if (title != null) { + builder.setTitle(title); + } else if (titleId > 1) { + builder.setTitle(titleId); + } + if (message != null) { + builder.setMessage(message); + } else if (messageId > 1) { + builder.setMessage(messageId); + } + if (positiveText != null) { + builder.setPositiveButton(positiveText, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String input = editText.getText().toString(); + onPositiveListener.onPositive(input); + } + }); + } else if (positiveTextId > 1) { + builder.setPositiveButton(positiveTextId, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + String input = editText.getText().toString(); + onPositiveListener.onPositive(input); + } + }); + } + if (negativeText != null) { + builder.setNegativeButton(negativeText, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + } else if (negativeTextId > 1) { + builder.setNegativeButton(negativeTextId, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + + } + }); + } + if (filledText != null) { + editText.setText(filledText, TextView.BufferType.EDITABLE); + editText.setSelection(editText.getText().length()); + } + if (inputType > 0) { + editText.setInputType(inputType); + } + + return builder.create(); + } + + public InputDialog setContext(Context context) { + this.context = context; + return this; + } + + public InputDialog setFilledText(String text) { + filledText = text; + return this; + } + + public InputDialog setInputType(int type) { + inputType = type; + return this; + } + + public InputDialog setTitle(String title) { + this.title = title; + return this; + } + + public InputDialog setTitle(int id) { + this.titleId = id; + return this; + } + + public InputDialog setMessage(String message) { + this.message = message; + return this; + } + + public InputDialog setMessage(int id) { + this.messageId = id; + return this; + } + + public InputDialog setPositiveButton(String text) { + positiveText = text; + return this; + } + + public InputDialog setPositiveButton(int id) { + positiveTextId = id; + return this; + } + + public InputDialog setNegativeButton(String text) { + negativeText = text; + return this; + } + + public InputDialog setNegativeButton(int id) { + negativeTextId = id; + return this; + } + + public InputDialog setOnPositiveListener(OnPositive l) { + onPositiveListener = l; + return this; + } + +} diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/LoadingDialog.java b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/LoadingDialog.java new file mode 100644 index 0000000..bd3eedb --- /dev/null +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/LoadingDialog.java @@ -0,0 +1,90 @@ +package ca.pkay.rcloneexplorer.Dialogs; + +import android.app.Dialog; +import android.content.Context; +import android.content.DialogInterface; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; +import android.support.v7.app.AlertDialog; +import android.view.LayoutInflater; +import android.view.View; + +import ca.pkay.rcloneexplorer.R; + +public class LoadingDialog extends DialogFragment { + + public interface OnNegative { + void onNegative(); + } + + + private Context context; + private OnNegative onNegativeListener; + private Boolean cancelable; + private String title; + private int titleId; + private String negativeText; + + public LoadingDialog() { + cancelable = false; + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + AlertDialog.Builder builder = new AlertDialog.Builder(context); + LayoutInflater inflater = ((FragmentActivity)context).getLayoutInflater(); + View view = inflater.inflate(R.layout.dialog_loading_indicator, null); + builder.setCancelable(cancelable); + if (title != null) { + builder.setTitle(title); + } else if (titleId > 0) { + builder.setTitle(titleId); + } + if (negativeText != null) { + builder.setNegativeButton(negativeText, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + onNegativeListener.onNegative(); + } + }); + } + builder.setView(view); + return builder.create(); + } + + public LoadingDialog setContext(Context context) { + this.context = context; + return this; + } + + public LoadingDialog setTitle(String title) { + this.title = title; + return this; + } + + public LoadingDialog setTitle(int id) { + titleId = id; + return this; + } + + + public LoadingDialog setNegativeButton(String text) { + negativeText = text; + return this; + } + + + public LoadingDialog setCanCancel(Boolean cancelable) { + this.cancelable = cancelable; + return this; + } + + + public LoadingDialog setOnNegativeListener(OnNegative l) { + onNegativeListener = l; + return this; + } +} diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/OpenAsDialog.java b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/OpenAsDialog.java similarity index 88% rename from app/src/main/java/ca/pkay/rcloneexplorer/OpenAsDialog.java rename to app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/OpenAsDialog.java index 1ed0240..66384c9 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/OpenAsDialog.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Dialogs/OpenAsDialog.java @@ -1,14 +1,17 @@ -package ca.pkay.rcloneexplorer; +package ca.pkay.rcloneexplorer.Dialogs; import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.DialogFragment; +import android.support.v4.app.FragmentActivity; import android.support.v7.app.AlertDialog; import android.view.LayoutInflater; import android.view.View; +import ca.pkay.rcloneexplorer.R; + public class OpenAsDialog extends DialogFragment { public interface OnClickListener { @@ -26,8 +29,8 @@ public interface OnClickListener { @Override public Dialog onCreateDialog(Bundle savedInstanceState) { AlertDialog.Builder builder = new AlertDialog.Builder(context); - LayoutInflater inflater = getActivity().getLayoutInflater(); - view = inflater.inflate(R.layout.open_as_dialog, null); + LayoutInflater inflater = ((FragmentActivity)context).getLayoutInflater(); + view = inflater.inflate(R.layout.dialog_open_as, null); setListeners(); builder.setView(view); return builder.create(); diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java index 5de20bf..7538942 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java @@ -30,8 +30,6 @@ import android.widget.RadioGroup; import android.widget.Toast; -import com.afollestad.materialdialogs.DialogAction; -import com.afollestad.materialdialogs.MaterialDialog; import com.leinardi.android.speeddial.SpeedDialActionItem; import com.leinardi.android.speeddial.SpeedDialOverlayLayout; import com.leinardi.android.speeddial.SpeedDialView; @@ -45,11 +43,13 @@ import java.util.Stack; import ca.pkay.rcloneexplorer.BreadcrumbView; +import ca.pkay.rcloneexplorer.Dialogs.InputDialog; +import ca.pkay.rcloneexplorer.Dialogs.LoadingDialog; import ca.pkay.rcloneexplorer.FileComparators; -import ca.pkay.rcloneexplorer.FilePropertiesDialog; +import ca.pkay.rcloneexplorer.Dialogs.FilePropertiesDialog; import ca.pkay.rcloneexplorer.Items.FileItem; import ca.pkay.rcloneexplorer.MainActivity; -import ca.pkay.rcloneexplorer.OpenAsDialog; +import ca.pkay.rcloneexplorer.Dialogs.OpenAsDialog; import ca.pkay.rcloneexplorer.R; import ca.pkay.rcloneexplorer.Rclone; import ca.pkay.rcloneexplorer.RecyclerViewAdapters.FileExplorerRecyclerViewAdapter; @@ -144,6 +144,9 @@ public void onCreate(@Nullable Bundle savedInstanceState) { remoteType = getArguments().getString(ARG_REMOTE_TYPE); path = "//" + getArguments().getString(ARG_REMOTE); } + if (getContext() == null) { + return; + } originalToolbarTitle = ((FragmentActivity) context).getTitle().toString(); ((FragmentActivity) context).setTitle(remoteType); setHasOptionsMenu(true); @@ -302,9 +305,10 @@ public void onClickText() { if (fileItem.getSize() < MAX_STREAMING_SIZE) { new DownloadAndOpen(DownloadAndOpen.OPEN_AS_TEXT).execute(fileItem); } else { - new MaterialDialog.Builder(context) - .title(R.string.max_streaming_size_exceeded) - .neutralText(R.string.okay_confirmation) + new AlertDialog.Builder(context) + .setMessage(R.string.max_streaming_size_exceeded) + .setNeutralButton(R.string.okay_confirmation, null) + .create() .show(); } } @@ -327,9 +331,10 @@ public void onClickImage() { if (fileItem.getSize() < MAX_STREAMING_SIZE) { new DownloadAndOpen(DownloadAndOpen.OPEN_AS_IMAGE).execute(fileItem); } else { - new MaterialDialog.Builder(context) - .title(R.string.max_streaming_size_exceeded) - .neutralText(R.string.okay_confirmation) + new AlertDialog.Builder(context) + .setMessage(R.string.max_streaming_size_exceeded) + .setNeutralButton(R.string.okay_confirmation, null) + .create() .show(); } @@ -463,7 +468,7 @@ private void showSortMenu() { } else { return; } - final View view = inflater.inflate(R.layout.sort_popup, null); + final View view = inflater.inflate(R.layout.dialog_sort, null); builder.setView(view) .setTitle(R.string.sort) .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { @@ -624,9 +629,10 @@ public void onFileClicked(FileItem fileItem) { // download and open new DownloadAndOpen().execute(fileItem); } else { - new MaterialDialog.Builder(context) - .title(R.string.max_streaming_size_exceeded) - .neutralText(R.string.okay_confirmation) + new AlertDialog.Builder(context) + .setMessage(R.string.max_streaming_size_exceeded) + .setNeutralButton(R.string.okay_confirmation, null) + .create() .show(); } } @@ -751,20 +757,20 @@ private void deleteClicked() { String title = "Delete " + deleteList.size(); String content = (deleteList.size() == 1) ? deleteList.get(0).getName() + " will be deleted" : ""; title += (deleteList.size() > 1) ? " items?" : " item?"; - new MaterialDialog.Builder(context) - .title(title) - .content(content) - .icon(getResources().getDrawable(R.drawable.ic_warning)) - .negativeText(getResources().getString(R.string.cancel)) - .positiveText(getResources().getString(R.string.delete)) - .onPositive(new MaterialDialog.SingleButtonCallback() { + AlertDialog.Builder builder = new AlertDialog.Builder(context) + .setTitle(title) + .setNegativeButton(getResources().getString(R.string.cancel), null) + .setPositiveButton(getResources().getString(R.string.delete), new DialogInterface.OnClickListener() { @Override - public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + public void onClick(DialogInterface dialog, int which) { recyclerViewAdapter.cancelSelection(); new DeleteFilesTask().execute(deleteList); } - }) - .show(); + }); + if (!content.trim().isEmpty()) { + builder.setMessage(content); + } + builder.create().show(); } private void renameClicked() { @@ -774,28 +780,32 @@ private void renameClicked() { List list = recyclerViewAdapter.getSelectedItems(); final FileItem renameItem = list.get(0); - - new MaterialDialog.Builder(context) - .title(R.string.rename_file) - .content(R.string.type_new_file_name) - .input(null, renameItem.getName(), new MaterialDialog.InputCallback() { - @Override - public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { - if (renameItem.getName().equals(input.toString())) { - return; - } - recyclerViewAdapter.cancelSelection(); - String newFilePath; - if (path.equals("//" + remote)) { - newFilePath = input.toString(); - } else { - newFilePath = path + "/" + input; + if (getFragmentManager() != null) { + new InputDialog() + .setContext(context) + .setTitle(R.string.rename_file) + .setMessage(R.string.type_new_file_name) + .setNegativeButton(R.string.cancel) + .setPositiveButton(R.string.okay_confirmation) + .setFilledText(renameItem.getName()) + .setOnPositiveListener(new InputDialog.OnPositive() { + @Override + public void onPositive(String input) { + if (renameItem.getName().equals(input)) { + return; + } + recyclerViewAdapter.cancelSelection(); + String newFilePath; + if (path.equals("//" + remote)) { + newFilePath = input; + } else { + newFilePath = path + "/" + input; + } + new RenameFileTask().execute(renameItem.getPath(), newFilePath); } - new RenameFileTask().execute(renameItem.getPath(), newFilePath); - } - }) - .negativeText(getResources().getString(R.string.cancel)) - .show(); + }) + .show(getFragmentManager(), "input dialog"); + } } private void downloadClicked() { @@ -826,26 +836,30 @@ private void moveClicked() { } private void onCreateNewDirectory() { - new MaterialDialog.Builder(context) - .title(R.string.create_new_folder) - .content(R.string.type_new_folder_name) - .negativeText(getResources().getString(R.string.cancel)) - .input(null, null, new MaterialDialog.InputCallback() { - @Override - public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { - if (input.toString().trim().length() == 0) { - return; - } - String newDir; - if (path.equals("//" + remote)) { - newDir = input.toString(); - } else { - newDir = path + "/" + input.toString(); + if (getFragmentManager() != null) { + new InputDialog() + .setContext(context) + .setTitle(R.string.create_new_folder) + .setMessage(R.string.type_new_folder_name) + .setNegativeButton(R.string.cancel) + .setPositiveButton(R.string.okay_confirmation) + .setOnPositiveListener(new InputDialog.OnPositive() { + @Override + public void onPositive(String input) { + if (input.trim().length() == 0) { + return; + } + String newDir; + if (path.equals("//" + remote)) { + newDir = input; + } else { + newDir = path + "/" + input; + } + new MakeDirectoryTask().execute(newDir); } - new MakeDirectoryTask().execute(newDir); - } - }) - .show(); + }) + .show(getFragmentManager(), "input dialog"); + } } private void onUploadFiles() { @@ -1084,7 +1098,7 @@ private class DownloadAndOpen extends AsyncTask { public static final int OPEN_AS_TEXT = 1; public static final int OPEN_AS_IMAGE = 2; private int openAs; - private MaterialDialog materialDialog; + private LoadingDialog loadingDialog; private String fileLocation; private Process process; @@ -1103,20 +1117,22 @@ private void cancelProcess() { @Override protected void onPreExecute() { super.onPreExecute(); - materialDialog = new MaterialDialog.Builder(context) - .title(R.string.loading_file) - .content(R.string.please_wait) - .cancelable(false) - .progress(true, 0) - .negativeText(getResources().getString(R.string.cancel)) - .onNegative(new MaterialDialog.SingleButtonCallback() { - @Override - public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { - cancelProcess(); - cancel(true); - } - }) - .show(); + + loadingDialog = new LoadingDialog() + .setContext(context) + .setCanCancel(false) + .setTitle(getString(R.string.loading_file)) + .setNegativeButton(getResources().getString(R.string.cancel)) + .setOnNegativeListener(new LoadingDialog.OnNegative() { + @Override + public void onNegative() { + cancelProcess(); + cancel(true); + } + }); + if (getFragmentManager() != null) { + loadingDialog.show(getFragmentManager(), "loading dialog"); + } } @Override @@ -1152,7 +1168,7 @@ protected Boolean doInBackground(FileItem... fileItems) { @Override protected void onPostExecute(Boolean status) { super.onPostExecute(status); - materialDialog.cancel(); + loadingDialog.dismiss(); if (!status) { return; } diff --git a/app/src/main/java/ca/pkay/rcloneexplorer/MainActivity.java b/app/src/main/java/ca/pkay/rcloneexplorer/MainActivity.java index 77577e9..1ded884 100644 --- a/app/src/main/java/ca/pkay/rcloneexplorer/MainActivity.java +++ b/app/src/main/java/ca/pkay/rcloneexplorer/MainActivity.java @@ -30,12 +30,12 @@ import android.view.View; import android.widget.Toast; -import com.afollestad.materialdialogs.MaterialDialog; - import java.io.File; import java.io.IOException; import ca.pkay.rcloneexplorer.BroadcastReceivers.NetworkStateReceiver; +import ca.pkay.rcloneexplorer.Dialogs.InputDialog; +import ca.pkay.rcloneexplorer.Dialogs.LoadingDialog; import ca.pkay.rcloneexplorer.Fragments.FileExplorerFragment; import ca.pkay.rcloneexplorer.Fragments.RemotesFragment; import ca.pkay.rcloneexplorer.Items.RemoteItem; @@ -201,17 +201,20 @@ public void onClick(DialogInterface dialogInterface, int i) { private void askForConfigPassword() { findViewById(R.id.locked_config).setVisibility(View.VISIBLE); - new MaterialDialog.Builder(this) - .title(R.string.config_password_protected) - .content(R.string.please_enter_password) - .inputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD) - .input(null, null, new MaterialDialog.InputCallback() { + new InputDialog() + .setContext(context) + .setTitle(R.string.config_password_protected) + .setMessage(R.string.please_enter_password) + .setNegativeButton(R.string.cancel) + .setPositiveButton(R.string.okay_confirmation) + .setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD) + .setOnPositiveListener(new InputDialog.OnPositive() { @Override - public void onInput(@NonNull MaterialDialog dialog, CharSequence input) { - new DecryptConfig().execute(input.toString()); + public void onPositive(String input) { + new DecryptConfig().execute(input); } }) - .show(); + .show(getSupportFragmentManager(), "input dialog"); } public void importConfigFile() { @@ -242,17 +245,16 @@ public void onRemoteClick(RemoteItem remote) { @SuppressLint("StaticFieldLeak") private class CreateRcloneBinary extends AsyncTask { - private MaterialDialog dialog; + private LoadingDialog loadingDialog; @Override protected void onPreExecute() { super.onPreExecute(); - dialog = new MaterialDialog.Builder(context) - .title(R.string.creating_rclone_binary) - .content(R.string.please_wait) - .progress(true, 0) - .cancelable(false) - .show(); + loadingDialog = new LoadingDialog() + .setContext(context) + .setTitle(R.string.creating_rclone_binary) + .setCanCancel(false); + loadingDialog.show(getSupportFragmentManager(), "loading dialog"); } @Override @@ -274,7 +276,7 @@ protected void onPostExecute(Boolean success) { finish(); System.exit(0); } - dialog.dismiss(); + loadingDialog.dismiss(); startRemotesFragment(); } } @@ -282,18 +284,17 @@ protected void onPostExecute(Boolean success) { @SuppressLint("StaticFieldLeak") private class CopyConfigFile extends AsyncTask { - private MaterialDialog dialog; + private LoadingDialog loadingDialog; @Override protected void onPreExecute() { super.onPreExecute(); findViewById(R.id.locked_config).setVisibility(View.GONE); - dialog = new MaterialDialog.Builder(context) - .title(R.string.copying_rclone_config) - .content(R.string.please_wait) - .progress(true, 0) - .cancelable(false) - .show(); + loadingDialog = new LoadingDialog() + .setContext(context) + .setTitle(R.string.copying_rclone_config) + .setCanCancel(false); + loadingDialog.show(getSupportFragmentManager(), "loading dialog"); } @Override @@ -310,7 +311,7 @@ protected Boolean doInBackground(Uri... uris) { @Override protected void onPostExecute(Boolean success) { super.onPostExecute(success); - dialog.dismiss(); + loadingDialog.dismiss(); if (!success) { return; } @@ -325,16 +326,16 @@ protected void onPostExecute(Boolean success) { @SuppressLint("StaticFieldLeak") private class DecryptConfig extends AsyncTask { - private MaterialDialog dialog; + private LoadingDialog loadingDialog; @Override protected void onPreExecute() { super.onPreExecute(); - dialog = new MaterialDialog.Builder(context) - .title(R.string.working) - .content(R.string.please_wait) - .cancelable(false) - .show(); + loadingDialog = new LoadingDialog() + .setContext(context) + .setTitle(R.string.working) + .setCanCancel(false); + loadingDialog.show(getSupportFragmentManager(), "loading dialog"); } @Override @@ -345,7 +346,7 @@ protected Boolean doInBackground(String... strings) { @Override protected void onPostExecute(Boolean success) { super.onPostExecute(success); - dialog.dismiss(); + loadingDialog.dismiss(); if (!success) { Toasty.error(context, getString(R.string.error_unlocking_config), Toast.LENGTH_LONG, true).show(); askForConfigPassword(); diff --git a/app/src/main/res/layout/file_properties_popup.xml b/app/src/main/res/layout/dialog_file_properties.xml similarity index 100% rename from app/src/main/res/layout/file_properties_popup.xml rename to app/src/main/res/layout/dialog_file_properties.xml diff --git a/app/src/main/res/layout/dialog_input.xml b/app/src/main/res/layout/dialog_input.xml new file mode 100644 index 0000000..8c1f7f3 --- /dev/null +++ b/app/src/main/res/layout/dialog_input.xml @@ -0,0 +1,14 @@ + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_loading_indicator.xml b/app/src/main/res/layout/dialog_loading_indicator.xml new file mode 100644 index 0000000..9005478 --- /dev/null +++ b/app/src/main/res/layout/dialog_loading_indicator.xml @@ -0,0 +1,22 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/open_as_dialog.xml b/app/src/main/res/layout/dialog_open_as.xml similarity index 100% rename from app/src/main/res/layout/open_as_dialog.xml rename to app/src/main/res/layout/dialog_open_as.xml diff --git a/app/src/main/res/layout/sort_popup.xml b/app/src/main/res/layout/dialog_sort.xml similarity index 100% rename from app/src/main/res/layout/sort_popup.xml rename to app/src/main/res/layout/dialog_sort.xml diff --git a/app/src/main/res/values/about_libraries_material_dialogs.xml b/app/src/main/res/values/about_libraries_material_dialogs.xml deleted file mode 100644 index 9e24303..0000000 --- a/app/src/main/res/values/about_libraries_material_dialogs.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - Aidan Follestad - https://aidanfollestad.com/ - Material Dialogs - A beautiful, fluid, and customizable dialogs API. - - https://github.com/afollestad/material-dialogs/ - MIT - true - https://github.com/afollestad/material-dialogs/ - \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a2e2984..1587628 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -80,7 +80,7 @@ File(s) moved File(s) deleted New folder created - Error retrieving directory content + Error retrieving directory message Error retrieving remotes Error deleting a file Error creating a directory