Skip to content

Commit 0762004

Browse files
authored
Merge pull request #53 from kaczmarkiewiczp/dev
Stable release
2 parents b40305d + 90d8382 commit 0762004

23 files changed

+781
-165
lines changed

.idea/assetWizardSettings.xml

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
0 Bytes
Binary file not shown.

README.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@ Features
1414

1515
Limitations
1616
------------
17-
- Does not support password protected rclone config files (future release)
1817
- Does not support adding or editting remotes from the app (planned feature)
1918

2019
Screenshots

app/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ android {
66
applicationId "ca.pkay.rcloneexplorer"
77
minSdkVersion 21
88
targetSdkVersion 27
9-
versionCode 6
10-
versionName "1.0.2-beta"
9+
versionCode 7
10+
versionName "1.1.0"
1111
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
1212
}
1313
buildTypes {

app/src/main/assets/changelog.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
### 1.1.0
2+
* **New:** Support password protected configurations
3+
* **New:** Calculate file MD5 & SHA1
4+
* **Fix:** Copy rclone and config file in the background
5+
6+
***
7+
18
### 1.0.2-beta
29
* **New:** Sort dialog
310
* **New:** Toast confirmation messages
Lines changed: 199 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,199 @@
1+
package ca.pkay.rcloneexplorer;
2+
3+
import android.annotation.SuppressLint;
4+
import android.app.Dialog;
5+
import android.content.ClipData;
6+
import android.content.ClipboardManager;
7+
import android.content.Context;
8+
import android.content.DialogInterface;
9+
import android.os.AsyncTask;
10+
import android.os.Bundle;
11+
import android.support.annotation.NonNull;
12+
import android.support.v4.app.DialogFragment;
13+
import android.support.v7.app.AlertDialog;
14+
import android.view.LayoutInflater;
15+
import android.view.View;
16+
import android.widget.TextView;
17+
import android.widget.Toast;
18+
19+
import ca.pkay.rcloneexplorer.Items.FileItem;
20+
import es.dmoral.toasty.Toasty;
21+
22+
public class FilePropertiesDialog extends DialogFragment {
23+
24+
private FileItem fileItem;
25+
private String remote;
26+
private View view;
27+
private Rclone rclone;
28+
private AsyncTask[] asyncTasks;
29+
private String md5String;
30+
private String sha1String;
31+
private Context context;
32+
33+
@NonNull
34+
@Override
35+
public Dialog onCreateDialog(Bundle savedInstanceState) {
36+
asyncTasks = new AsyncTask[2];
37+
AlertDialog.Builder builder = new AlertDialog.Builder(context);
38+
LayoutInflater inflater = getActivity().getLayoutInflater();
39+
view = inflater.inflate(R.layout.file_properties_popup, null);
40+
41+
((TextView)view.findViewById(R.id.filename)).setText(fileItem.getName());
42+
((TextView)view.findViewById(R.id.file_modtime)).setText(fileItem.getHumanReadableModTime());
43+
if (fileItem.isDir()) {
44+
view.findViewById(R.id.file_size).setVisibility(View.GONE);
45+
view.findViewById(R.id.file_size_label).setVisibility(View.GONE);
46+
47+
view.findViewById(R.id.file_md5_container).setVisibility(View.GONE);
48+
view.findViewById(R.id.file_sha1_container).setVisibility(View.GONE);
49+
view.findViewById(R.id.hash_separator).setVisibility(View.GONE);
50+
} else {
51+
view.findViewById(R.id.file_size).setVisibility(View.VISIBLE);
52+
view.findViewById(R.id.file_size_label).setVisibility(View.VISIBLE);
53+
((TextView)view.findViewById(R.id.file_size)).setText(fileItem.getHumanReadableSize());
54+
55+
view.findViewById(R.id.file_md5_container).setVisibility(View.VISIBLE);
56+
view.findViewById(R.id.file_sha1_container).setVisibility(View.VISIBLE);
57+
view.findViewById(R.id.hash_separator).setVisibility(View.VISIBLE);
58+
59+
view.findViewById(R.id.file_md5_container).setOnClickListener(new View.OnClickListener() {
60+
@Override
61+
public void onClick(View v) {
62+
calculateMD5();
63+
}
64+
});
65+
view.findViewById(R.id.file_sha1_container).setOnClickListener(new View.OnClickListener() {
66+
@Override
67+
public void onClick(View v) {
68+
calculateSHA1();
69+
}
70+
});
71+
}
72+
73+
builder.setView(view)
74+
.setPositiveButton(R.string.ok, null);
75+
return builder.create();
76+
}
77+
78+
public FilePropertiesDialog setContext(Context context) {
79+
this.context = context;
80+
return this;
81+
}
82+
83+
public FilePropertiesDialog setFile(FileItem fileItem) {
84+
this.fileItem = fileItem;
85+
return this;
86+
}
87+
88+
public FilePropertiesDialog setRemote(String remote) {
89+
this.remote = remote;
90+
return this;
91+
}
92+
93+
public FilePropertiesDialog setRclone(Rclone rclone) {
94+
this.rclone = rclone;
95+
return this;
96+
}
97+
98+
private void calculateMD5() {
99+
// md5 already calculated
100+
if (md5String != null && !md5String.isEmpty()) {
101+
ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
102+
ClipData clipData = ClipData.newPlainText("Copied hash", md5String);
103+
((TextView)view.findViewById(R.id.file_md5)).setTextIsSelectable(true);
104+
if (clipboardManager == null) {
105+
return;
106+
}
107+
clipboardManager.setPrimaryClip(clipData);
108+
Toasty.info(context, getString(R.string.hash_copied_confirmation), Toast.LENGTH_SHORT, true).show();
109+
} else { // calculate md5
110+
if (asyncTasks[0] != null) {
111+
asyncTasks[0].cancel(true);
112+
}
113+
asyncTasks[0] = new CalculateMD5().execute();
114+
}
115+
}
116+
117+
private void calculateSHA1() {
118+
// sha1 already calculated
119+
if (sha1String != null && !sha1String.isEmpty()) {
120+
ClipboardManager clipboardManager = (ClipboardManager) context.getSystemService(Context.CLIPBOARD_SERVICE);
121+
ClipData clipData = ClipData.newPlainText("Copied hash", sha1String);
122+
((TextView)view.findViewById(R.id.file_sha1)).setTextIsSelectable(true);
123+
if (clipboardManager == null) {
124+
return;
125+
}
126+
clipboardManager.setPrimaryClip(clipData);
127+
Toasty.info(context, getString(R.string.hash_copied_confirmation), Toast.LENGTH_SHORT, true).show();
128+
} else { // calculate sha1
129+
if (asyncTasks[1] != null) {
130+
asyncTasks[1].cancel(true);
131+
}
132+
asyncTasks[1] = new CalculateSHA1().execute();
133+
}
134+
}
135+
136+
@Override
137+
public void onDismiss(DialogInterface dialog) {
138+
super.onDismiss(dialog);
139+
for (AsyncTask asyncTask : asyncTasks) {
140+
if (asyncTask != null) {
141+
asyncTask.cancel(true);
142+
}
143+
}
144+
}
145+
146+
@SuppressLint("StaticFieldLeak")
147+
private class CalculateMD5 extends AsyncTask<Void, Void, String> {
148+
149+
@Override
150+
protected void onPreExecute() {
151+
super.onPreExecute();
152+
((TextView)view.findViewById(R.id.file_md5)).setText(R.string.calculating);
153+
}
154+
155+
@Override
156+
protected String doInBackground(Void... voids) {
157+
return rclone.calculateMD5(remote, fileItem);
158+
}
159+
160+
@Override
161+
protected void onPostExecute(String md5) {
162+
super.onPostExecute(md5);
163+
((TextView)view.findViewById(R.id.file_md5)).setText(md5);
164+
165+
if (!md5.equals(getString(R.string.hash_error)) && !md5.equals(getString(R.string.hash_unsupported))) {
166+
md5String = md5;
167+
} else {
168+
md5String = null;
169+
}
170+
}
171+
}
172+
173+
@SuppressLint("StaticFieldLeak")
174+
private class CalculateSHA1 extends AsyncTask<Void, Void, String> {
175+
176+
@Override
177+
protected void onPreExecute() {
178+
super.onPreExecute();
179+
((TextView)view.findViewById(R.id.file_sha1)).setText(R.string.calculating);
180+
}
181+
182+
@Override
183+
protected String doInBackground(Void... voids) {
184+
return rclone.calculateSHA1(remote, fileItem);
185+
}
186+
187+
@Override
188+
protected void onPostExecute(String sha1) {
189+
super.onPostExecute(sha1);
190+
((TextView)view.findViewById(R.id.file_sha1)).setText(sha1);
191+
192+
if (!sha1.equals(getString(R.string.hash_error)) && !sha1.equals(getString(R.string.hash_unsupported))) {
193+
sha1String = sha1;
194+
} else {
195+
sha1String = null;
196+
}
197+
}
198+
}
199+
}

app/src/main/java/ca/pkay/rcloneexplorer/Fragments/FileExplorerFragment.java

Lines changed: 10 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@
4747

4848
import ca.pkay.rcloneexplorer.BreadcrumbView;
4949
import ca.pkay.rcloneexplorer.FileComparators;
50+
import ca.pkay.rcloneexplorer.FilePropertiesDialog;
5051
import ca.pkay.rcloneexplorer.Items.FileItem;
5152
import ca.pkay.rcloneexplorer.MainActivity;
5253
import ca.pkay.rcloneexplorer.R;
@@ -289,28 +290,14 @@ private void showFileProperties() {
289290
return;
290291
}
291292
FileItem fileItem = recyclerViewAdapter.getSelectedItems().get(0);
292-
AlertDialog.Builder builder = new AlertDialog.Builder(context);
293-
LayoutInflater inflater;
294-
if (getActivity() != null) {
295-
inflater = getActivity().getLayoutInflater();
296-
} else {
297-
return;
293+
FilePropertiesDialog filePropertiesDialog = new FilePropertiesDialog()
294+
.setContext(context)
295+
.setFile(fileItem)
296+
.setRclone(rclone)
297+
.setRemote(remote);
298+
if (getFragmentManager() != null) {
299+
filePropertiesDialog.show(getFragmentManager(), "file properties");
298300
}
299-
final View view = inflater.inflate(R.layout.file_properties_popup, null);
300-
builder.setView(view)
301-
.setPositiveButton(R.string.ok, null);
302-
AlertDialog dialog = builder.create();
303-
((TextView)view.findViewById(R.id.filename)).setText(fileItem.getName());
304-
((TextView)view.findViewById(R.id.file_modtime)).setText(fileItem.getHumanReadableModTime());
305-
if (fileItem.isDir()) {
306-
view.findViewById(R.id.file_size).setVisibility(View.GONE);
307-
view.findViewById(R.id.file_size_label).setVisibility(View.GONE);
308-
} else {
309-
view.findViewById(R.id.file_size).setVisibility(View.VISIBLE);
310-
view.findViewById(R.id.file_size_label).setVisibility(View.VISIBLE);
311-
((TextView)view.findViewById(R.id.file_size)).setText(fileItem.getHumanReadableSize());
312-
}
313-
dialog.show();
314301
}
315302

316303
private void setFabClickListeners() {
@@ -755,6 +742,7 @@ private void downloadClicked() {
755742
exFilePicker.setUseFirstItemAsUpEnabled(true);
756743
exFilePicker.setChoiceType(ExFilePicker.ChoiceType.DIRECTORIES);
757744
exFilePicker.setCanChooseOnlyOneItem(true);
745+
exFilePicker.setQuitButtonEnabled(true);
758746
exFilePicker.start(this, EX_FILE_PICKER_DOWNLOAD_RESULT);
759747
}
760748

@@ -800,6 +788,7 @@ private void onUploadFiles() {
800788
ExFilePicker exFilePicker = new ExFilePicker();
801789
exFilePicker.setUseFirstItemAsUpEnabled(true);
802790
exFilePicker.setChoiceType(ExFilePicker.ChoiceType.ALL);
791+
exFilePicker.setQuitButtonEnabled(true);
803792
exFilePicker.start(this, EX_FILE_PICKER_UPLOAD_RESULT);
804793
}
805794

0 commit comments

Comments
 (0)