mirror of
https://github.com/M66B/FairEmail.git
synced 2026-04-01 06:38:29 +02:00
Allow saving attachments of drafts
This commit is contained in:
@@ -20,10 +20,15 @@ package eu.faircode.email;
|
||||
*/
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.res.Configuration;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.text.TextUtils;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
@@ -33,17 +38,37 @@ import android.widget.Toast;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.appcompat.app.ActionBar;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
import androidx.fragment.app.Fragment;
|
||||
import androidx.lifecycle.Lifecycle;
|
||||
import androidx.localbroadcastmanager.content.LocalBroadcastManager;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static android.app.Activity.RESULT_OK;
|
||||
|
||||
public class FragmentBase extends Fragment {
|
||||
private String title = null;
|
||||
private String subtitle = " ";
|
||||
private boolean finish = false;
|
||||
|
||||
private long message = -1;
|
||||
private long attachment = -1;
|
||||
|
||||
private static final int REQUEST_ATTACHMENT = 51;
|
||||
private static final int REQUEST_ATTACHMENTS = 52;
|
||||
|
||||
static final String ACTION_STORE_ATTACHMENT = BuildConfig.APPLICATION_ID + ".STORE_ATTACHMENT";
|
||||
static final String ACTION_STORE_ATTACHMENTS = BuildConfig.APPLICATION_ID + ".STORE_ATTACHMENTS";
|
||||
|
||||
protected void setTitle(int resid) {
|
||||
setTitle(getString(resid));
|
||||
}
|
||||
@@ -145,12 +170,21 @@ public class FragmentBase extends Fragment {
|
||||
getFragmentManager().popBackStack();
|
||||
finish = false;
|
||||
}
|
||||
|
||||
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext());
|
||||
IntentFilter iff = new IntentFilter();
|
||||
iff.addAction(ACTION_STORE_ATTACHMENT);
|
||||
iff.addAction(ACTION_STORE_ATTACHMENTS);
|
||||
lbm.registerReceiver(receiver, iff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
Log.i("Pause " + this);
|
||||
super.onPause();
|
||||
|
||||
LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext());
|
||||
lbm.unregisterReceiver(receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -159,6 +193,21 @@ public class FragmentBase extends Fragment {
|
||||
" request=" + requestCode + " result=" + resultCode);
|
||||
Log.logExtras(data);
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
try {
|
||||
switch (requestCode) {
|
||||
case REQUEST_ATTACHMENT:
|
||||
if (resultCode == RESULT_OK && data != null)
|
||||
onSaveAttachment(data);
|
||||
break;
|
||||
case REQUEST_ATTACHMENTS:
|
||||
if (resultCode == RESULT_OK && data != null)
|
||||
onSaveAttachments(data);
|
||||
break;
|
||||
}
|
||||
} catch (Throwable ex) {
|
||||
Log.e(ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -218,4 +267,186 @@ public class FragmentBase extends Fragment {
|
||||
void addBillingListener(ActivityBilling.IBillingListener listener) {
|
||||
((ActivityBilling) getActivity()).addBillingListener(listener, getViewLifecycleOwner());
|
||||
}
|
||||
|
||||
private BroadcastReceiver receiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
if (getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.STARTED)) {
|
||||
String action = intent.getAction();
|
||||
|
||||
if (ACTION_STORE_ATTACHMENT.equals(action))
|
||||
onStoreAttachment(intent);
|
||||
if (ACTION_STORE_ATTACHMENTS.equals(action))
|
||||
onStoreAttachments(intent);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private void onStoreAttachment(Intent intent) {
|
||||
attachment = intent.getLongExtra("id", -1);
|
||||
Intent create = new Intent(Intent.ACTION_CREATE_DOCUMENT);
|
||||
create.addCategory(Intent.CATEGORY_OPENABLE);
|
||||
create.setType(intent.getStringExtra("type"));
|
||||
create.putExtra(Intent.EXTRA_TITLE, intent.getStringExtra("name"));
|
||||
if (create.resolveActivity(getContext().getPackageManager()) == null)
|
||||
ToastEx.makeText(getContext(), R.string.title_no_saf, Toast.LENGTH_LONG).show();
|
||||
else
|
||||
startActivityForResult(Helper.getChooser(getContext(), create), REQUEST_ATTACHMENT);
|
||||
}
|
||||
|
||||
private void onStoreAttachments(Intent intent) {
|
||||
message = intent.getLongExtra("id", -1);
|
||||
Intent tree = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE);
|
||||
//tree.putExtra("android.content.extra.SHOW_ADVANCED", true);
|
||||
if (tree.resolveActivity(getContext().getPackageManager()) == null)
|
||||
ToastEx.makeText(getContext(), R.string.title_no_saf, Toast.LENGTH_LONG).show();
|
||||
else
|
||||
startActivityForResult(Helper.getChooser(getContext(), tree), REQUEST_ATTACHMENTS);
|
||||
}
|
||||
|
||||
private void onSaveAttachment(Intent data) {
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("id", attachment);
|
||||
args.putParcelable("uri", data.getData());
|
||||
|
||||
new SimpleTask<Void>() {
|
||||
@Override
|
||||
protected Void onExecute(Context context, Bundle args) throws Throwable {
|
||||
long id = args.getLong("id");
|
||||
Uri uri = args.getParcelable("uri");
|
||||
|
||||
if ("file".equals(uri.getScheme())) {
|
||||
Log.w("Save attachment uri=" + uri);
|
||||
throw new IllegalArgumentException(context.getString(R.string.title_no_stream));
|
||||
}
|
||||
|
||||
DB db = DB.getInstance(context);
|
||||
EntityAttachment attachment = db.attachment().getAttachment(id);
|
||||
if (attachment == null)
|
||||
return null;
|
||||
File file = attachment.getFile(context);
|
||||
|
||||
ParcelFileDescriptor pfd = null;
|
||||
OutputStream os = null;
|
||||
InputStream is = null;
|
||||
try {
|
||||
pfd = context.getContentResolver().openFileDescriptor(uri, "w");
|
||||
os = new FileOutputStream(pfd.getFileDescriptor());
|
||||
is = new FileInputStream(file);
|
||||
|
||||
byte[] buffer = new byte[Helper.BUFFER_SIZE];
|
||||
int read;
|
||||
while ((read = is.read(buffer)) != -1)
|
||||
os.write(buffer, 0, read);
|
||||
} finally {
|
||||
try {
|
||||
if (pfd != null)
|
||||
pfd.close();
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
}
|
||||
try {
|
||||
if (os != null)
|
||||
os.close();
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
}
|
||||
try {
|
||||
if (is != null)
|
||||
is.close();
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onExecuted(Bundle args, Void data) {
|
||||
ToastEx.makeText(getContext(), R.string.title_attachment_saved, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
if (ex instanceof IllegalArgumentException || ex instanceof FileNotFoundException)
|
||||
ToastEx.makeText(getContext(), ex.getMessage(), Toast.LENGTH_LONG).show();
|
||||
else
|
||||
Helper.unexpectedError(getFragmentManager(), ex);
|
||||
}
|
||||
}.execute(this, args, "attachment:save");
|
||||
}
|
||||
|
||||
private void onSaveAttachments(Intent data) {
|
||||
Bundle args = new Bundle();
|
||||
args.putLong("id", message);
|
||||
args.putParcelable("uri", data.getData());
|
||||
|
||||
new SimpleTask<Void>() {
|
||||
@Override
|
||||
protected Void onExecute(Context context, Bundle args) throws Throwable {
|
||||
long id = args.getLong("id");
|
||||
Uri uri = args.getParcelable("uri");
|
||||
|
||||
DB db = DB.getInstance(context);
|
||||
DocumentFile tree = DocumentFile.fromTreeUri(context, uri);
|
||||
List<EntityAttachment> attachments = db.attachment().getAttachments(id);
|
||||
for (EntityAttachment attachment : attachments) {
|
||||
File file = attachment.getFile(context);
|
||||
|
||||
String name = Helper.sanitizeFilename(attachment.name);
|
||||
if (TextUtils.isEmpty(name))
|
||||
name = Long.toString(attachment.id);
|
||||
DocumentFile document = tree.createFile(attachment.type, name);
|
||||
if (document == null)
|
||||
throw new FileNotFoundException(uri + ":" + name);
|
||||
|
||||
ParcelFileDescriptor pfd = null;
|
||||
OutputStream os = null;
|
||||
InputStream is = null;
|
||||
try {
|
||||
pfd = context.getContentResolver().openFileDescriptor(document.getUri(), "w");
|
||||
os = new FileOutputStream(pfd.getFileDescriptor());
|
||||
is = new FileInputStream(file);
|
||||
|
||||
byte[] buffer = new byte[Helper.BUFFER_SIZE];
|
||||
int read;
|
||||
while ((read = is.read(buffer)) != -1)
|
||||
os.write(buffer, 0, read);
|
||||
} finally {
|
||||
try {
|
||||
if (pfd != null)
|
||||
pfd.close();
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
}
|
||||
try {
|
||||
if (os != null)
|
||||
os.close();
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
}
|
||||
try {
|
||||
if (is != null)
|
||||
is.close();
|
||||
} catch (Throwable ex) {
|
||||
Log.w(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onExecuted(Bundle args, Void data) {
|
||||
ToastEx.makeText(getContext(), R.string.title_attachments_saved, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onException(Bundle args, Throwable ex) {
|
||||
Helper.unexpectedError(getFragmentManager(), ex);
|
||||
}
|
||||
}.execute(this, args, "attachments:save");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user