mirror of
https://github.com/moparisthebest/k-9
synced 2024-11-30 05:02:26 -05:00
Move functionality from AttachmentView to AttachmentController
This commit is contained in:
parent
087238f507
commit
8fce9e3654
@ -0,0 +1,26 @@
|
||||
package com.fsck.k9.mailstore;
|
||||
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.fsck.k9.mail.Part;
|
||||
|
||||
|
||||
public class AttachmentViewInfo {
|
||||
public final String mimeType;
|
||||
public final String displayName;
|
||||
public final long size;
|
||||
public final Uri uri;
|
||||
public final boolean firstClassAttachment;
|
||||
public final Part part;
|
||||
|
||||
public AttachmentViewInfo(String mimeType, String displayName, long size, Uri uri, boolean firstClassAttachment,
|
||||
Part part) {
|
||||
this.mimeType = mimeType;
|
||||
this.displayName = displayName;
|
||||
this.size = size;
|
||||
this.uri = uri;
|
||||
this.firstClassAttachment = firstClassAttachment;
|
||||
this.part = part;
|
||||
}
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
package com.fsck.k9.mailstore;
|
||||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.mail.Address;
|
||||
@ -11,7 +12,9 @@ import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.helper.HtmlConverter;
|
||||
import com.fsck.k9.mail.internet.MessageExtractor;
|
||||
import com.fsck.k9.mail.internet.MimeHeader;
|
||||
import com.fsck.k9.mail.internet.MimeMultipart;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mail.internet.Viewable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -118,35 +121,6 @@ public class LocalMessageExtractor {
|
||||
}
|
||||
}
|
||||
|
||||
public static ViewableContainer extractPartsFromDraft(Message message)
|
||||
throws MessagingException {
|
||||
|
||||
Body body = message.getBody();
|
||||
if (message.isMimeType("multipart/mixed") && body instanceof MimeMultipart) {
|
||||
MimeMultipart multipart = (MimeMultipart) body;
|
||||
|
||||
ViewableContainer container;
|
||||
int count = multipart.getCount();
|
||||
if (count >= 1) {
|
||||
// The first part is either a text/plain or a multipart/alternative
|
||||
BodyPart firstPart = multipart.getBodyPart(0);
|
||||
container = extractTextual(firstPart);
|
||||
|
||||
// The rest should be attachments
|
||||
for (int i = 1; i < count; i++) {
|
||||
BodyPart bodyPart = multipart.getBodyPart(i);
|
||||
container.attachments.add(bodyPart);
|
||||
}
|
||||
} else {
|
||||
container = new ViewableContainer("", "", new ArrayList<Part>());
|
||||
}
|
||||
|
||||
return container;
|
||||
}
|
||||
|
||||
return extractTextual(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Use the contents of a {@link com.fsck.k9.mail.internet.Viewable} to create the HTML to be displayed.
|
||||
*
|
||||
@ -471,6 +445,58 @@ public class LocalMessageExtractor {
|
||||
public static MessageViewInfo decodeMessageForView(Context context, Message message) throws MessagingException {
|
||||
//TODO: Modify extractTextAndAttachments() to only extract the text type (plain vs. HTML) we currently need.
|
||||
ViewableContainer viewable = LocalMessageExtractor.extractTextAndAttachments(context, message);
|
||||
return new MessageViewInfo(viewable.html, viewable.attachments, message);
|
||||
List<AttachmentViewInfo> attachments = extractAttachmentInfos(viewable.attachments);
|
||||
return new MessageViewInfo(viewable.html, attachments, message);
|
||||
}
|
||||
|
||||
private static List<AttachmentViewInfo> extractAttachmentInfos(List<Part> attachmentParts)
|
||||
throws MessagingException {
|
||||
|
||||
List<AttachmentViewInfo> attachments = new ArrayList<AttachmentViewInfo>();
|
||||
for (Part part : attachmentParts) {
|
||||
attachments.add(extractAttachmentInfo(part));
|
||||
}
|
||||
|
||||
return attachments;
|
||||
}
|
||||
|
||||
private static AttachmentViewInfo extractAttachmentInfo(Part part) throws MessagingException {
|
||||
boolean firstClassAttachment = true;
|
||||
|
||||
String mimeType = part.getMimeType();
|
||||
String contentTypeHeader = MimeUtility.unfoldAndDecode(part.getContentType());
|
||||
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
|
||||
|
||||
String name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
|
||||
if (name == null) {
|
||||
name = MimeUtility.getHeaderParameter(contentTypeHeader, "name");
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
firstClassAttachment = false;
|
||||
String extension = MimeUtility.getExtensionByMimeType(mimeType);
|
||||
name = "noname" + ((extension != null) ? "." + extension : "");
|
||||
}
|
||||
|
||||
// Inline parts with a content-id are almost certainly components of an HTML message
|
||||
// not attachments. Only show them if the user pressed the button to show more
|
||||
// attachments.
|
||||
if (contentDisposition != null &&
|
||||
MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)") &&
|
||||
part.getHeader(MimeHeader.HEADER_CONTENT_ID) != null) {
|
||||
firstClassAttachment = false;
|
||||
}
|
||||
|
||||
long size = 0;
|
||||
String sizeParam = MimeUtility.getHeaderParameter(contentDisposition, "size");
|
||||
if (sizeParam != null) {
|
||||
try {
|
||||
size = Integer.parseInt(sizeParam);
|
||||
} catch (NumberFormatException e) { /* ignore */ }
|
||||
}
|
||||
|
||||
Uri uri = Uri.parse("dummy://this.needs.fixing"); //FIXME
|
||||
|
||||
return new AttachmentViewInfo(mimeType, name, size, uri, firstClassAttachment, part);
|
||||
}
|
||||
}
|
||||
|
@ -5,15 +5,14 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.Part;
|
||||
|
||||
|
||||
public class MessageViewInfo {
|
||||
public final String text;
|
||||
public final List<Part> attachments;
|
||||
public final List<AttachmentViewInfo> attachments;
|
||||
public final Message message;
|
||||
|
||||
public MessageViewInfo(String text, List<Part> attachments, Message message) {
|
||||
public MessageViewInfo(String text, List<AttachmentViewInfo> attachments, Message message) {
|
||||
this.text = text;
|
||||
this.attachments = Collections.unmodifiableList(attachments);
|
||||
this.message = message;
|
||||
|
@ -0,0 +1,259 @@
|
||||
package com.fsck.k9.ui.messageview;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
import android.util.Log;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.cache.TemporaryAttachmentStore;
|
||||
import com.fsck.k9.helper.FileHelper;
|
||||
import com.fsck.k9.helper.MediaScannerNotifier;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mailstore.AttachmentViewInfo;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
|
||||
public class AttachmentController {
|
||||
private final Context context;
|
||||
private final SingleMessageView messageView;
|
||||
private final AttachmentViewInfo attachment;
|
||||
|
||||
AttachmentController(SingleMessageView messageView, AttachmentViewInfo attachment) {
|
||||
this.context = messageView.getContext();
|
||||
this.messageView = messageView;
|
||||
this.attachment = attachment;
|
||||
}
|
||||
|
||||
public void viewAttachment() {
|
||||
new ViewAttachmentAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
public void saveAttachment() {
|
||||
saveAttachmentTo(K9.getAttachmentDefaultPath());
|
||||
}
|
||||
|
||||
public void saveAttachmentTo(String directory) {
|
||||
saveAttachmentTo(new File(directory));
|
||||
}
|
||||
|
||||
private void saveAttachmentTo(File directory) {
|
||||
boolean isExternalStorageMounted = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
|
||||
if (!isExternalStorageMounted) {
|
||||
String message = context.getString(R.string.message_view_status_attachment_not_saved);
|
||||
displayMessageToUser(message);
|
||||
return;
|
||||
}
|
||||
|
||||
//FIXME: write file in background thread
|
||||
try {
|
||||
File file = saveAttachmentWithUniqueFileName(directory);
|
||||
|
||||
displayAttachmentSavedMessage(file.toString());
|
||||
|
||||
MediaScannerNotifier.notify(context, file);
|
||||
} catch (IOException ioe) {
|
||||
if (K9.DEBUG) {
|
||||
Log.e(K9.LOG_TAG, "Error saving attachment", ioe);
|
||||
}
|
||||
displayAttachmentNotSavedMessage();
|
||||
}
|
||||
}
|
||||
|
||||
private File saveAttachmentWithUniqueFileName(File directory) throws IOException {
|
||||
String filename = FileHelper.sanitizeFilename(attachment.displayName);
|
||||
File file = FileHelper.createUniqueFile(directory, filename);
|
||||
|
||||
writeAttachmentToStorage(file);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private void writeAttachmentToStorage(File file) throws IOException {
|
||||
InputStream in = context.getContentResolver().openInputStream(attachment.uri);
|
||||
try {
|
||||
OutputStream out = new FileOutputStream(file);
|
||||
try {
|
||||
IOUtils.copy(in, out);
|
||||
out.flush();
|
||||
} finally {
|
||||
out.close();
|
||||
}
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
private Intent getBestViewIntentAndSaveFileIfNecessary() {
|
||||
String displayName = attachment.displayName;
|
||||
String inferredMimeType = MimeUtility.getMimeTypeByExtension(displayName);
|
||||
|
||||
IntentAndResolvedActivitiesCount resolvedIntentInfo;
|
||||
String mimeType = attachment.mimeType;
|
||||
if (MimeUtility.isDefaultMimeType(mimeType)) {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(inferredMimeType);
|
||||
} else {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(mimeType);
|
||||
if (!resolvedIntentInfo.hasResolvedActivities() && !inferredMimeType.equals(mimeType)) {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(inferredMimeType);
|
||||
}
|
||||
}
|
||||
|
||||
if (!resolvedIntentInfo.hasResolvedActivities()) {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(MimeUtility.DEFAULT_ATTACHMENT_MIME_TYPE);
|
||||
}
|
||||
|
||||
Intent viewIntent;
|
||||
if (resolvedIntentInfo.hasResolvedActivities() && resolvedIntentInfo.containsFileUri()) {
|
||||
try {
|
||||
File tempFile = TemporaryAttachmentStore.getFileForWriting(context, displayName);
|
||||
writeAttachmentToStorage(tempFile);
|
||||
viewIntent = createViewIntentForFileUri(resolvedIntentInfo.getMimeType(), Uri.fromFile(tempFile));
|
||||
} catch (IOException e) {
|
||||
if (K9.DEBUG) {
|
||||
Log.e(K9.LOG_TAG, "Error while saving attachment to use file:// URI with ACTION_VIEW Intent", e);
|
||||
}
|
||||
viewIntent = createViewIntentForAttachmentProviderUri(MimeUtility.DEFAULT_ATTACHMENT_MIME_TYPE);
|
||||
}
|
||||
} else {
|
||||
viewIntent = resolvedIntentInfo.getIntent();
|
||||
}
|
||||
|
||||
return viewIntent;
|
||||
}
|
||||
|
||||
private IntentAndResolvedActivitiesCount getBestViewIntentForMimeType(String mimeType) {
|
||||
Intent contentUriIntent = createViewIntentForAttachmentProviderUri(mimeType);
|
||||
int contentUriActivitiesCount = getResolvedIntentActivitiesCount(contentUriIntent);
|
||||
|
||||
if (contentUriActivitiesCount > 0) {
|
||||
return new IntentAndResolvedActivitiesCount(contentUriIntent, contentUriActivitiesCount);
|
||||
}
|
||||
|
||||
File tempFile = TemporaryAttachmentStore.getFile(context, attachment.displayName);
|
||||
Uri tempFileUri = Uri.fromFile(tempFile);
|
||||
Intent fileUriIntent = createViewIntentForFileUri(mimeType, tempFileUri);
|
||||
int fileUriActivitiesCount = getResolvedIntentActivitiesCount(fileUriIntent);
|
||||
|
||||
if (fileUriActivitiesCount > 0) {
|
||||
return new IntentAndResolvedActivitiesCount(fileUriIntent, fileUriActivitiesCount);
|
||||
}
|
||||
|
||||
return new IntentAndResolvedActivitiesCount(contentUriIntent, contentUriActivitiesCount);
|
||||
}
|
||||
|
||||
private Intent createViewIntentForAttachmentProviderUri(String mimeType) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(attachment.uri, mimeType);
|
||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
addUiIntentFlags(intent);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
private Intent createViewIntentForFileUri(String mimeType, Uri uri) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(uri, mimeType);
|
||||
addUiIntentFlags(intent);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
private void addUiIntentFlags(Intent intent) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
||||
}
|
||||
|
||||
private int getResolvedIntentActivitiesCount(Intent intent) {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
|
||||
List<ResolveInfo> resolveInfos =
|
||||
packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
|
||||
return resolveInfos.size();
|
||||
}
|
||||
|
||||
private void displayAttachmentSavedMessage(final String filename) {
|
||||
String message = context.getString(R.string.message_view_status_attachment_saved, filename);
|
||||
displayMessageToUser(message);
|
||||
}
|
||||
|
||||
private void displayAttachmentNotSavedMessage() {
|
||||
String message = context.getString(R.string.message_view_status_attachment_not_saved);
|
||||
displayMessageToUser(message);
|
||||
}
|
||||
|
||||
private void displayMessageToUser(String message) {
|
||||
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
private static class IntentAndResolvedActivitiesCount {
|
||||
private Intent intent;
|
||||
private int activitiesCount;
|
||||
|
||||
IntentAndResolvedActivitiesCount(Intent intent, int activitiesCount) {
|
||||
this.intent = intent;
|
||||
this.activitiesCount = activitiesCount;
|
||||
}
|
||||
|
||||
public Intent getIntent() {
|
||||
return intent;
|
||||
}
|
||||
|
||||
public boolean hasResolvedActivities() {
|
||||
return activitiesCount > 0;
|
||||
}
|
||||
|
||||
public String getMimeType() {
|
||||
return intent.getType();
|
||||
}
|
||||
|
||||
public boolean containsFileUri() {
|
||||
return "file".equals(intent.getData().getScheme());
|
||||
}
|
||||
}
|
||||
|
||||
private class ViewAttachmentAsyncTask extends AsyncTask<Void, Void, Intent> {
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
messageView.disableAttachmentViewButton(attachment);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent doInBackground(Void... params) {
|
||||
return getBestViewIntentAndSaveFileIfNecessary();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Intent intent) {
|
||||
viewAttachment(intent);
|
||||
messageView.enableAttachmentViewButton(attachment);
|
||||
}
|
||||
|
||||
private void viewAttachment(Intent intent) {
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Log.e(K9.LOG_TAG, "Could not display attachment of type " + attachment.mimeType, e);
|
||||
|
||||
String message = context.getString(R.string.message_view_no_viewer, attachment.mimeType);
|
||||
displayMessageToUser(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +1,10 @@
|
||||
package com.fsck.k9.ui.messageview;
|
||||
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.ActivityNotFoundException;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Environment;
|
||||
import android.util.AttributeSet;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.view.View.OnLongClickListener;
|
||||
@ -23,124 +12,50 @@ import android.widget.Button;
|
||||
import android.widget.FrameLayout;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.cache.TemporaryAttachmentStore;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.helper.FileHelper;
|
||||
import com.fsck.k9.helper.MediaScannerNotifier;
|
||||
import com.fsck.k9.helper.SizeFormatter;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MimeHeader;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mailstore.AttachmentViewInfo;
|
||||
|
||||
|
||||
public class AttachmentView extends FrameLayout implements OnClickListener, OnLongClickListener {
|
||||
private Context context;
|
||||
private Message message;
|
||||
private Part part;
|
||||
private Account account;
|
||||
private MessagingController controller;
|
||||
private MessagingListener listener;
|
||||
private AttachmentFileDownloadCallback callback;
|
||||
private AttachmentViewInfo attachment;
|
||||
private AttachmentViewCallback callback;
|
||||
|
||||
private Button viewButton;
|
||||
private Button downloadButton;
|
||||
|
||||
private String name;
|
||||
private String contentType;
|
||||
private long size;
|
||||
|
||||
|
||||
public AttachmentView(Context context, AttributeSet attrs, int defStyle) {
|
||||
super(context, attrs, defStyle);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public AttachmentView(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public AttachmentView(Context context) {
|
||||
super(context);
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
public void setButtonsEnabled(boolean enabled) {
|
||||
viewButton.setEnabled(enabled);
|
||||
downloadButton.setEnabled(enabled);
|
||||
public AttachmentViewInfo getAttachment() {
|
||||
return attachment;
|
||||
}
|
||||
|
||||
/**
|
||||
* Populates this view with information about the attachment.
|
||||
* <p>
|
||||
* This method also decides which attachments are displayed when the "show attachments" button
|
||||
* is pressed, and which attachments are only displayed after the "show more attachments"
|
||||
* button was pressed.<br>
|
||||
* Inline attachments with content ID and unnamed attachments fall into the second category.
|
||||
* </p>
|
||||
*
|
||||
* @return {@code true} for a regular attachment. {@code false} for attachments that should be initially hidden.
|
||||
*/
|
||||
public boolean populateFromPart(Part part, Message message, Account account,
|
||||
MessagingController controller, MessagingListener listener) throws MessagingException {
|
||||
public void enableViewButton() {
|
||||
viewButton.setEnabled(true);
|
||||
}
|
||||
|
||||
this.part = part;
|
||||
this.message = message;
|
||||
this.account = account;
|
||||
this.controller = controller;
|
||||
this.listener = listener;
|
||||
public void disableViewButton() {
|
||||
viewButton.setEnabled(false);
|
||||
}
|
||||
|
||||
boolean firstClassAttachment = extractAttachmentInformation(part);
|
||||
public void setAttachment(AttachmentViewInfo attachment) throws MessagingException {
|
||||
this.attachment = attachment;
|
||||
|
||||
displayAttachmentInformation();
|
||||
|
||||
return firstClassAttachment;
|
||||
}
|
||||
|
||||
//TODO: extract this code to a helper class
|
||||
private boolean extractAttachmentInformation(Part part) throws MessagingException {
|
||||
boolean firstClassAttachment = true;
|
||||
|
||||
contentType = part.getMimeType();
|
||||
String contentTypeHeader = MimeUtility.unfoldAndDecode(part.getContentType());
|
||||
String contentDisposition = MimeUtility.unfoldAndDecode(part.getDisposition());
|
||||
|
||||
name = MimeUtility.getHeaderParameter(contentTypeHeader, "name");
|
||||
if (name == null) {
|
||||
name = MimeUtility.getHeaderParameter(contentDisposition, "filename");
|
||||
}
|
||||
|
||||
if (name == null) {
|
||||
firstClassAttachment = false;
|
||||
String extension = MimeUtility.getExtensionByMimeType(contentType);
|
||||
name = "noname" + ((extension != null) ? "." + extension : "");
|
||||
}
|
||||
|
||||
// Inline parts with a content-id are almost certainly components of an HTML message
|
||||
// not attachments. Only show them if the user pressed the button to show more
|
||||
// attachments.
|
||||
if (contentDisposition != null &&
|
||||
MimeUtility.getHeaderParameter(contentDisposition, null).matches("^(?i:inline)")
|
||||
&& part.getHeader(MimeHeader.HEADER_CONTENT_ID) != null) {
|
||||
firstClassAttachment = false;
|
||||
}
|
||||
|
||||
String sizeParam = MimeUtility.getHeaderParameter(contentDisposition, "size");
|
||||
if (sizeParam != null) {
|
||||
try {
|
||||
size = Integer.parseInt(sizeParam);
|
||||
} catch (NumberFormatException e) { /* ignore */ }
|
||||
}
|
||||
|
||||
return firstClassAttachment;
|
||||
}
|
||||
|
||||
private void displayAttachmentInformation() {
|
||||
@ -149,7 +64,7 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
|
||||
viewButton = (Button) findViewById(R.id.view);
|
||||
downloadButton = (Button) findViewById(R.id.download);
|
||||
|
||||
if (size > K9.MAX_ATTACHMENT_DOWNLOAD_SIZE) {
|
||||
if (attachment.size > K9.MAX_ATTACHMENT_DOWNLOAD_SIZE) {
|
||||
viewButton.setVisibility(View.GONE);
|
||||
downloadButton.setVisibility(View.GONE);
|
||||
}
|
||||
@ -158,8 +73,8 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
|
||||
downloadButton.setOnClickListener(this);
|
||||
downloadButton.setOnLongClickListener(this);
|
||||
|
||||
attachmentName.setText(name);
|
||||
attachmentInfo.setText(SizeFormatter.formatSize(context, size));
|
||||
attachmentName.setText(attachment.displayName);
|
||||
attachmentInfo.setText(SizeFormatter.formatSize(getContext(), attachment.size));
|
||||
|
||||
ImageView thumbnail = (ImageView) findViewById(R.id.attachment_icon);
|
||||
new LoadAndDisplayThumbnailAsyncTask(thumbnail).execute();
|
||||
@ -169,11 +84,11 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
|
||||
public void onClick(View view) {
|
||||
switch (view.getId()) {
|
||||
case R.id.view: {
|
||||
onViewButtonClicked();
|
||||
onViewButtonClick();
|
||||
break;
|
||||
}
|
||||
case R.id.download: {
|
||||
onSaveButtonClicked();
|
||||
onSaveButtonClick();
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -182,231 +97,29 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
|
||||
@Override
|
||||
public boolean onLongClick(View view) {
|
||||
if (view.getId() == R.id.download) {
|
||||
callback.pickDirectoryToSaveAttachmentTo(this);
|
||||
onSaveButtonLongClick();
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void onViewButtonClicked() {
|
||||
if (message != null) {
|
||||
controller.loadAttachment(account, message, part, new Object[] {false, this}, listener);
|
||||
}
|
||||
private void onViewButtonClick() {
|
||||
callback.onViewAttachment(attachment);
|
||||
}
|
||||
|
||||
private void onSaveButtonClicked() {
|
||||
boolean isExternalStorageMounted = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED);
|
||||
if (!isExternalStorageMounted) {
|
||||
String message = context.getString(R.string.message_view_status_attachment_not_saved);
|
||||
displayMessageToUser(message);
|
||||
return;
|
||||
private void onSaveButtonClick() {
|
||||
callback.onSaveAttachment(attachment);
|
||||
}
|
||||
|
||||
if (message != null) {
|
||||
controller.loadAttachment(account, message, part, new Object[] {true, this}, listener);
|
||||
}
|
||||
private void onSaveButtonLongClick() {
|
||||
callback.onSaveAttachmentToUserProvidedDirectory(attachment);
|
||||
}
|
||||
|
||||
public void writeFile() {
|
||||
writeFile(new File(K9.getAttachmentDefaultPath()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the attachment as file in the given directory
|
||||
*/
|
||||
public void writeFile(File directory) {
|
||||
try {
|
||||
File file = saveAttachmentWithUniqueFileName(directory);
|
||||
|
||||
displayAttachmentSavedMessage(file.toString());
|
||||
|
||||
MediaScannerNotifier.notify(context, file);
|
||||
} catch (IOException ioe) {
|
||||
if (K9.DEBUG) {
|
||||
Log.e(K9.LOG_TAG, "Error saving attachment", ioe);
|
||||
}
|
||||
displayAttachmentNotSavedMessage();
|
||||
}
|
||||
}
|
||||
|
||||
private File saveAttachmentWithUniqueFileName(File directory) throws IOException {
|
||||
String filename = FileHelper.sanitizeFilename(name);
|
||||
File file = FileHelper.createUniqueFile(directory, filename);
|
||||
|
||||
writeAttachmentToStorage(file);
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
private void writeAttachmentToStorage(File file) throws IOException {
|
||||
//FIXME
|
||||
throw new RuntimeException("temporarily disabled");
|
||||
// Uri uri = AttachmentProvider.getAttachmentUri(account, part.getAttachmentId());
|
||||
// InputStream in = context.getContentResolver().openInputStream(uri);
|
||||
// try {
|
||||
// OutputStream out = new FileOutputStream(file);
|
||||
// try {
|
||||
// IOUtils.copy(in, out);
|
||||
// out.flush();
|
||||
// } finally {
|
||||
// out.close();
|
||||
// }
|
||||
// } finally {
|
||||
// in.close();
|
||||
// }
|
||||
}
|
||||
|
||||
public void showFile() {
|
||||
new ViewAttachmentAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR);
|
||||
}
|
||||
|
||||
private Intent getBestViewIntentAndSaveFileIfNecessary() {
|
||||
String inferredMimeType = MimeUtility.getMimeTypeByExtension(name);
|
||||
|
||||
IntentAndResolvedActivitiesCount resolvedIntentInfo;
|
||||
if (MimeUtility.isDefaultMimeType(contentType)) {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(inferredMimeType);
|
||||
} else {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(contentType);
|
||||
if (!resolvedIntentInfo.hasResolvedActivities() && !inferredMimeType.equals(contentType)) {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(inferredMimeType);
|
||||
}
|
||||
}
|
||||
|
||||
if (!resolvedIntentInfo.hasResolvedActivities()) {
|
||||
resolvedIntentInfo = getBestViewIntentForMimeType(MimeUtility.DEFAULT_ATTACHMENT_MIME_TYPE);
|
||||
}
|
||||
|
||||
Intent viewIntent;
|
||||
if (resolvedIntentInfo.hasResolvedActivities() && resolvedIntentInfo.containsFileUri()) {
|
||||
try {
|
||||
File tempFile = TemporaryAttachmentStore.getFileForWriting(context, name);
|
||||
writeAttachmentToStorage(tempFile);
|
||||
viewIntent = createViewIntentForFileUri(resolvedIntentInfo.getMimeType(), Uri.fromFile(tempFile));
|
||||
} catch (IOException e) {
|
||||
if (K9.DEBUG) {
|
||||
Log.e(K9.LOG_TAG, "Error while saving attachment to use file:// URI with ACTION_VIEW Intent", e);
|
||||
}
|
||||
viewIntent = createViewIntentForAttachmentProviderUri(MimeUtility.DEFAULT_ATTACHMENT_MIME_TYPE);
|
||||
}
|
||||
} else {
|
||||
viewIntent = resolvedIntentInfo.getIntent();
|
||||
}
|
||||
|
||||
return viewIntent;
|
||||
}
|
||||
|
||||
private IntentAndResolvedActivitiesCount getBestViewIntentForMimeType(String mimeType) {
|
||||
Intent contentUriIntent = createViewIntentForAttachmentProviderUri(mimeType);
|
||||
int contentUriActivitiesCount = getResolvedIntentActivitiesCount(contentUriIntent);
|
||||
|
||||
if (contentUriActivitiesCount > 0) {
|
||||
return new IntentAndResolvedActivitiesCount(contentUriIntent, contentUriActivitiesCount);
|
||||
}
|
||||
|
||||
File tempFile = TemporaryAttachmentStore.getFile(context, name);
|
||||
Uri tempFileUri = Uri.fromFile(tempFile);
|
||||
Intent fileUriIntent = createViewIntentForFileUri(mimeType, tempFileUri);
|
||||
int fileUriActivitiesCount = getResolvedIntentActivitiesCount(fileUriIntent);
|
||||
|
||||
if (fileUriActivitiesCount > 0) {
|
||||
return new IntentAndResolvedActivitiesCount(fileUriIntent, fileUriActivitiesCount);
|
||||
}
|
||||
|
||||
return new IntentAndResolvedActivitiesCount(contentUriIntent, contentUriActivitiesCount);
|
||||
}
|
||||
|
||||
private Intent createViewIntentForAttachmentProviderUri(String mimeType) {
|
||||
//FIXME
|
||||
throw new RuntimeException("temporarily disabled");
|
||||
// Uri uri = AttachmentProvider.getAttachmentUriForViewing(account, part.getAttachmentId(), mimeType, name);
|
||||
//
|
||||
// Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
// intent.setDataAndType(uri, mimeType);
|
||||
// intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||
// addUiIntentFlags(intent);
|
||||
//
|
||||
// return intent;
|
||||
}
|
||||
|
||||
private Intent createViewIntentForFileUri(String mimeType, Uri uri) {
|
||||
Intent intent = new Intent(Intent.ACTION_VIEW);
|
||||
intent.setDataAndType(uri, mimeType);
|
||||
addUiIntentFlags(intent);
|
||||
|
||||
return intent;
|
||||
}
|
||||
|
||||
private void addUiIntentFlags(Intent intent) {
|
||||
intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET);
|
||||
}
|
||||
|
||||
private int getResolvedIntentActivitiesCount(Intent intent) {
|
||||
PackageManager packageManager = context.getPackageManager();
|
||||
|
||||
List<ResolveInfo> resolveInfos =
|
||||
packageManager.queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY);
|
||||
|
||||
return resolveInfos.size();
|
||||
}
|
||||
|
||||
private void displayAttachmentSavedMessage(final String filename) {
|
||||
String message = context.getString(R.string.message_view_status_attachment_saved, filename);
|
||||
displayMessageToUser(message);
|
||||
}
|
||||
|
||||
private void displayAttachmentNotSavedMessage() {
|
||||
String message = context.getString(R.string.message_view_status_attachment_not_saved);
|
||||
displayMessageToUser(message);
|
||||
}
|
||||
|
||||
private void displayMessageToUser(String message) {
|
||||
Toast.makeText(context, message, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
public void setCallback(AttachmentFileDownloadCallback callback) {
|
||||
public void setCallback(AttachmentViewCallback callback) {
|
||||
this.callback = callback;
|
||||
}
|
||||
|
||||
|
||||
public interface AttachmentFileDownloadCallback {
|
||||
/**
|
||||
* This method is called to ask the user to pick a directory to save the attachment to.
|
||||
* <p/>
|
||||
* After the user has selected a directory, the implementation of this interface has to call
|
||||
* {@link #writeFile(File)} on the object supplied as argument in order for the attachment to be saved.
|
||||
*/
|
||||
public void pickDirectoryToSaveAttachmentTo(AttachmentView caller);
|
||||
}
|
||||
|
||||
|
||||
private static class IntentAndResolvedActivitiesCount {
|
||||
private Intent intent;
|
||||
private int activitiesCount;
|
||||
|
||||
IntentAndResolvedActivitiesCount(Intent intent, int activitiesCount) {
|
||||
this.intent = intent;
|
||||
this.activitiesCount = activitiesCount;
|
||||
}
|
||||
|
||||
public Intent getIntent() {
|
||||
return intent;
|
||||
}
|
||||
|
||||
public boolean hasResolvedActivities() {
|
||||
return activitiesCount > 0;
|
||||
}
|
||||
|
||||
public String getMimeType() {
|
||||
return intent.getType();
|
||||
}
|
||||
|
||||
public boolean containsFileUri() {
|
||||
return "file".equals(intent.getData().getScheme());
|
||||
}
|
||||
}
|
||||
|
||||
private class LoadAndDisplayThumbnailAsyncTask extends AsyncTask<Void, Void, Bitmap> {
|
||||
private final ImageView thumbnail;
|
||||
|
||||
@ -445,34 +158,4 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private class ViewAttachmentAsyncTask extends AsyncTask<Void, Void, Intent> {
|
||||
|
||||
@Override
|
||||
protected void onPreExecute() {
|
||||
viewButton.setEnabled(false);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Intent doInBackground(Void... params) {
|
||||
return getBestViewIntentAndSaveFileIfNecessary();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPostExecute(Intent intent) {
|
||||
viewAttachment(intent);
|
||||
viewButton.setEnabled(true);
|
||||
}
|
||||
|
||||
private void viewAttachment(Intent intent) {
|
||||
try {
|
||||
context.startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
Log.e(K9.LOG_TAG, "Could not display attachment of type " + contentType, e);
|
||||
|
||||
String message = context.getString(R.string.message_view_no_viewer, contentType);
|
||||
displayMessageToUser(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,11 @@
|
||||
package com.fsck.k9.ui.messageview;
|
||||
|
||||
|
||||
import com.fsck.k9.mailstore.AttachmentViewInfo;
|
||||
|
||||
|
||||
interface AttachmentViewCallback {
|
||||
void onViewAttachment(AttachmentViewInfo attachment);
|
||||
void onSaveAttachment(AttachmentViewInfo attachment);
|
||||
void onSaveAttachmentToUserProvidedDirectory(AttachmentViewInfo attachment);
|
||||
}
|
@ -1,20 +1,19 @@
|
||||
package com.fsck.k9.ui.messageview;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Locale;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.Fragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.app.LoaderManager.LoaderCallbacks;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.Loader;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.app.DialogFragment;
|
||||
import android.app.FragmentManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.ContextThemeWrapper;
|
||||
@ -32,7 +31,6 @@ import com.fsck.k9.R;
|
||||
import com.fsck.k9.activity.ChooseFolder;
|
||||
import com.fsck.k9.activity.MessageReference;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.fragment.ConfirmationDialogFragment;
|
||||
import com.fsck.k9.fragment.ConfirmationDialogFragment.ConfirmationDialogFragmentListener;
|
||||
@ -40,21 +38,18 @@ import com.fsck.k9.fragment.ProgressDialogFragment;
|
||||
import com.fsck.k9.helper.FileBrowserHelper;
|
||||
import com.fsck.k9.helper.FileBrowserHelper.FileBrowserFailOverCallback;
|
||||
import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mailstore.AttachmentViewInfo;
|
||||
import com.fsck.k9.mailstore.LocalMessage;
|
||||
import com.fsck.k9.mailstore.MessageViewInfo;
|
||||
import com.fsck.k9.ui.message.DecodeMessageLoader;
|
||||
import com.fsck.k9.ui.message.LocalMessageLoader;
|
||||
import com.fsck.k9.ui.messageview.AttachmentView.AttachmentFileDownloadCallback;
|
||||
import com.fsck.k9.view.MessageHeader;
|
||||
|
||||
import org.openintents.openpgp.OpenPgpSignatureResult;
|
||||
|
||||
|
||||
public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
ConfirmationDialogFragmentListener {
|
||||
public class MessageViewFragment extends Fragment implements OnClickListener, ConfirmationDialogFragmentListener,
|
||||
AttachmentViewCallback {
|
||||
|
||||
private static final String ARG_REFERENCE = "reference";
|
||||
|
||||
@ -86,16 +81,8 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
private MessageReference mMessageReference;
|
||||
private LocalMessage mMessage;
|
||||
private MessagingController mController;
|
||||
private Listener mListener = new Listener();
|
||||
private MessageViewHandler mHandler = new MessageViewHandler();
|
||||
private LayoutInflater mLayoutInflater;
|
||||
|
||||
/** this variable is used to save the calling AttachmentView
|
||||
* until the onActivityResult is called.
|
||||
* => with this reference we can identity the caller
|
||||
*/
|
||||
private AttachmentView attachmentTmpStore;
|
||||
|
||||
/**
|
||||
* Used to temporarily store the destination folder for refile operations if a confirmation
|
||||
* dialog is shown.
|
||||
@ -116,49 +103,9 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
private LoaderCallbacks<LocalMessage> localMessageLoaderCallback = new LocalMessageLoaderCallback();
|
||||
private LoaderCallbacks<MessageViewInfo> decodeMessageLoaderCallback = new DecodeMessageLoaderCallback();
|
||||
private MessageViewInfo messageViewInfo;
|
||||
private AttachmentViewInfo currentAttachmentViewInfo;
|
||||
|
||||
|
||||
class MessageViewHandler extends Handler {
|
||||
|
||||
public void progress(final boolean progress) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
setProgress(progress);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/* A helper for a set of "show a toast" methods */
|
||||
private void showToast(final String message, final int toastLength) {
|
||||
post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(getActivity(), message, toastLength).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void networkError() {
|
||||
// FIXME: This is a hack. Fix the Handler madness!
|
||||
Context context = getActivity();
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
showToast(context.getString(R.string.status_network_error), Toast.LENGTH_LONG);
|
||||
}
|
||||
|
||||
public void fetchingAttachment() {
|
||||
Context context = getActivity();
|
||||
if (context == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
showToast(context.getString(R.string.message_view_fetching_attachment_toast), Toast.LENGTH_SHORT);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
@ -195,33 +142,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
|
||||
mMessageView = (SingleMessageView) view.findViewById(R.id.message_view);
|
||||
|
||||
//set a callback for the attachment view. With this callback the attachmentview
|
||||
//request the start of a filebrowser activity.
|
||||
mMessageView.setAttachmentCallback(new AttachmentFileDownloadCallback() {
|
||||
|
||||
@Override
|
||||
public void pickDirectoryToSaveAttachmentTo(final AttachmentView caller) {
|
||||
FileBrowserHelper.getInstance()
|
||||
.showFileBrowserActivity(MessageViewFragment.this,
|
||||
null,
|
||||
ACTIVITY_CHOOSE_DIRECTORY,
|
||||
callback);
|
||||
attachmentTmpStore = caller;
|
||||
}
|
||||
|
||||
FileBrowserFailOverCallback callback = new FileBrowserFailOverCallback() {
|
||||
|
||||
@Override
|
||||
public void onPathEntered(String path) {
|
||||
attachmentTmpStore.writeFile(new File(path));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// canceled, do nothing
|
||||
}
|
||||
};
|
||||
});
|
||||
mMessageView.setAttachmentCallback(this);
|
||||
|
||||
mMessageView.initialize(this, new OnClickListener() {
|
||||
@Override
|
||||
@ -246,7 +167,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
messageReference = (MessageReference) savedInstanceState.get(STATE_MESSAGE_REFERENCE);
|
||||
} else {
|
||||
Bundle args = getArguments();
|
||||
messageReference = (MessageReference) args.getParcelable(ARG_REFERENCE);
|
||||
messageReference = args.getParcelable(ARG_REFERENCE);
|
||||
}
|
||||
|
||||
displayMessage(messageReference, (mPgpData == null));
|
||||
@ -316,7 +237,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
|
||||
private void showMessage(MessageViewInfo messageContainer) {
|
||||
try {
|
||||
mMessageView.setMessage(mAccount, messageContainer, mPgpData, mController, mListener);
|
||||
mMessageView.setMessage(mAccount, messageContainer, mPgpData);
|
||||
mMessageView.setShowDownloadButton(mMessage);
|
||||
} catch (MessagingException e) {
|
||||
Log.e(K9.LOG_TAG, "Error while trying to display message", e);
|
||||
@ -474,13 +395,13 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
|
||||
switch (requestCode) {
|
||||
case ACTIVITY_CHOOSE_DIRECTORY: {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
if (data != null) {
|
||||
// obtain the filename
|
||||
Uri fileUri = data.getData();
|
||||
if (fileUri != null) {
|
||||
String filePath = fileUri.getPath();
|
||||
if (filePath != null) {
|
||||
attachmentTmpStore.writeFile(new File(filePath));
|
||||
getAttachmentController(currentAttachmentViewInfo).saveAttachmentTo(filePath);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -535,7 +456,8 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
return;
|
||||
}
|
||||
mMessageView.downloadRemainderButton().setEnabled(false);
|
||||
mController.loadMessageForViewRemote(mAccount, mMessageReference.folderName, mMessageReference.uid, mListener);
|
||||
//FIXME
|
||||
// mController.loadMessageForViewRemote(mAccount, mMessageReference.folderName, mMessageReference.uid, mListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -576,89 +498,6 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
destFolderName, null);
|
||||
}
|
||||
|
||||
class Listener extends MessagingListener {
|
||||
@Override
|
||||
public void loadMessageForViewHeadersAvailable(final Account account, String folder, String uid,
|
||||
final Message message) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMessageForViewBodyAvailable(final Account account, String folder,
|
||||
String uid, final Message message) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMessageForViewFailed(Account account, String folder, String uid, final Throwable t) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMessageForViewFinished(Account account, String folder, String uid, final Message message) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMessageForViewStarted(Account account, String folder, String uid) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAttachmentStarted(Account account, Message message, Part part, Object tag, final boolean requiresDownload) {
|
||||
if (mMessage != message) {
|
||||
return;
|
||||
}
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMessageView.setAttachmentsEnabled(false);
|
||||
showDialog(R.id.dialog_attachment_progress);
|
||||
if (requiresDownload) {
|
||||
mHandler.fetchingAttachment();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAttachmentFinished(Account account, Message message, Part part, final Object tag) {
|
||||
if (mMessage != message) {
|
||||
return;
|
||||
}
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMessageView.setAttachmentsEnabled(true);
|
||||
removeDialog(R.id.dialog_attachment_progress);
|
||||
Object[] params = (Object[]) tag;
|
||||
boolean download = (Boolean) params[0];
|
||||
AttachmentView attachment = (AttachmentView) params[1];
|
||||
if (download) {
|
||||
attachment.writeFile();
|
||||
} else {
|
||||
attachment.showFile();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadAttachmentFailed(Account account, Message message, Part part, Object tag, String reason) {
|
||||
if (mMessage != message) {
|
||||
return;
|
||||
}
|
||||
mHandler.post(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
mMessageView.setAttachmentsEnabled(true);
|
||||
removeDialog(R.id.dialog_attachment_progress);
|
||||
mHandler.networkError();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Used by MessageOpenPgpView
|
||||
*/
|
||||
@ -668,7 +507,7 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
PgpData data = new PgpData();
|
||||
data.setDecryptedData(decryptedData);
|
||||
data.setSignatureResult(signatureResult);
|
||||
mMessageView.setMessage(mAccount, messageViewInfo, data, mController, mListener);
|
||||
mMessageView.setMessage(mAccount, messageViewInfo, data);
|
||||
} catch (MessagingException e) {
|
||||
Log.e(K9.LOG_TAG, "displayMessageBody failed", e);
|
||||
}
|
||||
@ -860,4 +699,41 @@ public class MessageViewFragment extends Fragment implements OnClickListener,
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onViewAttachment(AttachmentViewInfo attachment) {
|
||||
//TODO: check if we have to download the attachment first
|
||||
|
||||
getAttachmentController(attachment).viewAttachment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveAttachment(AttachmentViewInfo attachment) {
|
||||
//TODO: check if we have to download the attachment first
|
||||
|
||||
getAttachmentController(attachment).saveAttachment();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveAttachmentToUserProvidedDirectory(final AttachmentViewInfo attachment) {
|
||||
//TODO: check if we have to download the attachment first
|
||||
|
||||
currentAttachmentViewInfo = attachment;
|
||||
FileBrowserHelper.getInstance().showFileBrowserActivity(MessageViewFragment.this, null,
|
||||
ACTIVITY_CHOOSE_DIRECTORY, new FileBrowserFailOverCallback() {
|
||||
@Override
|
||||
public void onPathEntered(String path) {
|
||||
getAttachmentController(attachment).saveAttachmentTo(path);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCancel() {
|
||||
// Do nothing
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private AttachmentController getAttachmentController(AttachmentViewInfo attachment) {
|
||||
return new AttachmentController(mMessageView, attachment);
|
||||
}
|
||||
}
|
||||
|
@ -5,6 +5,8 @@ import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.Fragment;
|
||||
@ -39,8 +41,6 @@ import android.widget.Toast;
|
||||
import com.fsck.k9.Account;
|
||||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.controller.MessagingController;
|
||||
import com.fsck.k9.controller.MessagingListener;
|
||||
import com.fsck.k9.crypto.PgpData;
|
||||
import com.fsck.k9.helper.ClipboardManager;
|
||||
import com.fsck.k9.helper.Contacts;
|
||||
@ -52,12 +52,11 @@ import com.fsck.k9.mail.Address;
|
||||
import com.fsck.k9.mail.Flag;
|
||||
import com.fsck.k9.mail.Message;
|
||||
import com.fsck.k9.mail.MessagingException;
|
||||
import com.fsck.k9.mail.Part;
|
||||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mailstore.AttachmentViewInfo;
|
||||
import com.fsck.k9.mailstore.MessageViewInfo;
|
||||
import com.fsck.k9.provider.AttachmentProvider.AttachmentProviderColumns;
|
||||
|
||||
import com.fsck.k9.ui.messageview.AttachmentView.AttachmentFileDownloadCallback;
|
||||
import com.fsck.k9.view.MessageHeader;
|
||||
import com.fsck.k9.view.MessageHeader.OnLayoutChangedListener;
|
||||
import com.fsck.k9.view.MessageWebView;
|
||||
@ -103,11 +102,12 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
private Button mDownloadRemainder;
|
||||
private LayoutInflater mInflater;
|
||||
private Contacts mContacts;
|
||||
private AttachmentFileDownloadCallback attachmentCallback;
|
||||
private AttachmentViewCallback attachmentCallback;
|
||||
private View mAttachmentsContainer;
|
||||
private SavedState mSavedState;
|
||||
private ClipboardManager mClipboardManager;
|
||||
private String mText;
|
||||
private Map<AttachmentViewInfo, AttachmentView> attachments = new HashMap<AttachmentViewInfo, AttachmentView>();
|
||||
|
||||
|
||||
public void initialize(Fragment fragment, OnClickListener flagListener) {
|
||||
@ -497,8 +497,8 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
return mHeaderContainer.additionalHeadersVisible();
|
||||
}
|
||||
|
||||
public void setMessage(Account account, MessageViewInfo messageViewInfo, PgpData pgpData,
|
||||
MessagingController controller, MessagingListener listener) throws MessagingException {
|
||||
public void setMessage(Account account, MessageViewInfo messageViewInfo, PgpData pgpData)
|
||||
throws MessagingException {
|
||||
resetView();
|
||||
|
||||
String text = null;
|
||||
@ -517,9 +517,8 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
mText = text;
|
||||
|
||||
mHasAttachments = !messageViewInfo.attachments.isEmpty();
|
||||
|
||||
if (mHasAttachments) {
|
||||
renderAttachments(messageViewInfo, account, controller, listener);
|
||||
renderAttachments(messageViewInfo);
|
||||
}
|
||||
|
||||
mHiddenAttachments.setVisibility(View.GONE);
|
||||
@ -593,30 +592,15 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
mMessageContentView.setVisibility(show ? View.VISIBLE : View.GONE);
|
||||
}
|
||||
|
||||
public void setAttachmentsEnabled(boolean enabled) {
|
||||
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
||||
AttachmentView attachment = (AttachmentView) mAttachments.getChildAt(i);
|
||||
attachment.setButtonsEnabled(enabled);
|
||||
}
|
||||
}
|
||||
|
||||
public void removeAllAttachments() {
|
||||
for (int i = 0, count = mAttachments.getChildCount(); i < count; i++) {
|
||||
mAttachments.removeView(mAttachments.getChildAt(i));
|
||||
}
|
||||
}
|
||||
|
||||
public void renderAttachments(MessageViewInfo messageContainer, Account account, MessagingController controller,
|
||||
MessagingListener listener) throws MessagingException {
|
||||
|
||||
for (Part attachment : messageContainer.attachments) {
|
||||
public void renderAttachments(MessageViewInfo messageContainer) throws MessagingException {
|
||||
for (AttachmentViewInfo attachment : messageContainer.attachments) {
|
||||
AttachmentView view = (AttachmentView) mInflater.inflate(R.layout.message_view_attachment, null);
|
||||
view.setCallback(attachmentCallback);
|
||||
view.setAttachment(attachment);
|
||||
|
||||
boolean isFirstClassAttachment = view.populateFromPart(attachment, messageContainer.message, account,
|
||||
controller, listener);
|
||||
attachments.put(attachment, view);
|
||||
|
||||
if (isFirstClassAttachment) {
|
||||
if (attachment.firstClassAttachment) {
|
||||
addAttachment(view);
|
||||
} else {
|
||||
addHiddenAttachment(view);
|
||||
@ -667,12 +651,7 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
mHeaderContainer.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public AttachmentView.AttachmentFileDownloadCallback getAttachmentCallback() {
|
||||
return attachmentCallback;
|
||||
}
|
||||
|
||||
public void setAttachmentCallback(
|
||||
AttachmentView.AttachmentFileDownloadCallback attachmentCallback) {
|
||||
public void setAttachmentCallback(AttachmentViewCallback attachmentCallback) {
|
||||
this.attachmentCallback = attachmentCallback;
|
||||
}
|
||||
|
||||
@ -711,6 +690,18 @@ public class SingleMessageView extends LinearLayout implements OnClickListener,
|
||||
}
|
||||
}
|
||||
|
||||
public void enableAttachmentViewButton(AttachmentViewInfo attachment) {
|
||||
getAttachmentView(attachment).enableViewButton();
|
||||
}
|
||||
|
||||
public void disableAttachmentViewButton(AttachmentViewInfo attachment) {
|
||||
getAttachmentView(attachment).disableViewButton();
|
||||
}
|
||||
|
||||
private AttachmentView getAttachmentView(AttachmentViewInfo attachment) {
|
||||
return attachments.get(attachment);
|
||||
}
|
||||
|
||||
static class SavedState extends BaseSavedState {
|
||||
boolean attachmentViewVisible;
|
||||
boolean hiddenAttachmentsVisible;
|
||||
|
Loading…
Reference in New Issue
Block a user