diff --git a/k9mail/src/main/java/com/fsck/k9/controller/MessagingController.java b/k9mail/src/main/java/com/fsck/k9/controller/MessagingController.java index 8b0cd1495..d0e339e1b 100644 --- a/k9mail/src/main/java/com/fsck/k9/controller/MessagingController.java +++ b/k9mail/src/main/java/com/fsck/k9/controller/MessagingController.java @@ -3144,40 +3144,8 @@ public class MessagingController implements Runnable { } } - /** - * Attempts to load the attachment specified by part from the given account and message. - * @param account - * @param message - * @param part - * @param listener - */ - public void loadAttachment( - final Account account, - final Message message, - final Part part, - final Object tag, - final MessagingListener listener) { - /* - * Check if the attachment has already been downloaded. If it has there's no reason to - * download it, so we just tell the listener that it's ready to go. - */ - - if (part.getBody() != null) { - for (MessagingListener l : getListeners(listener)) { - l.loadAttachmentStarted(account, message, part, tag, false); - } - - for (MessagingListener l : getListeners(listener)) { - l.loadAttachmentFinished(account, message, part, tag); - } - return; - } - - - - for (MessagingListener l : getListeners(listener)) { - l.loadAttachmentStarted(account, message, part, tag, true); - } + public void loadAttachment(final Account account, final LocalMessage message, final Part part, + final MessagingListener listener) { put("loadAttachment", listener, new Runnable() { @Override @@ -3185,32 +3153,29 @@ public class MessagingController implements Runnable { Folder remoteFolder = null; LocalFolder localFolder = null; try { - LocalStore localStore = account.getLocalStore(); + String folderName = message.getFolder().getName(); + + LocalStore localStore = account.getLocalStore(); + localFolder = localStore.getFolder(folderName); - List attachments = MessageExtractor.collectAttachments(message); - for (Part attachment : attachments) { - attachment.setBody(null); - } Store remoteStore = account.getRemoteStore(); - localFolder = localStore.getFolder(message.getFolder().getName()); - remoteFolder = remoteStore.getFolder(message.getFolder().getName()); + remoteFolder = remoteStore.getFolder(folderName); remoteFolder.open(Folder.OPEN_MODE_RW); - //FIXME: This is an ugly hack that won't be needed once the Message objects have been united. Message remoteMessage = remoteFolder.getMessage(message.getUid()); - MimeMessageHelper.setBody(remoteMessage, message.getBody()); remoteFolder.fetchPart(remoteMessage, part, null); - localFolder.addPartToMessage((LocalMessage) message, part); + localFolder.addPartToMessage(message, part); + for (MessagingListener l : getListeners(listener)) { - l.loadAttachmentFinished(account, message, part, tag); + l.loadAttachmentFinished(account, message, part); } } catch (MessagingException me) { if (K9.DEBUG) Log.v(K9.LOG_TAG, "Exception loading attachment", me); for (MessagingListener l : getListeners(listener)) { - l.loadAttachmentFailed(account, message, part, tag, me.getMessage()); + l.loadAttachmentFailed(account, message, part, me.getMessage()); } notifyUserIfCertificateProblem(context, me, account, true); addErrorMessage(account, null, me); diff --git a/k9mail/src/main/java/com/fsck/k9/controller/MessagingListener.java b/k9mail/src/main/java/com/fsck/k9/controller/MessagingListener.java index 9190fe422..5b6970d38 100644 --- a/k9mail/src/main/java/com/fsck/k9/controller/MessagingListener.java +++ b/k9mail/src/main/java/com/fsck/k9/controller/MessagingListener.java @@ -133,13 +133,9 @@ public class MessagingListener { public void setPushActive(Account account, String folderName, boolean enabled) {} - public void loadAttachmentStarted(Account account, Message message, Part part, Object tag, - boolean requiresDownload) {} + public void loadAttachmentFinished(Account account, Message message, Part part) {} - public void loadAttachmentFinished(Account account, Message message, Part part, Object tag) {} - - public void loadAttachmentFailed(Account account, Message message, Part part, Object tag, - String reason) {} + public void loadAttachmentFailed(Account account, Message message, Part part, String reason) {} diff --git a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalBodyPart.java b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalBodyPart.java index ebab22c60..ede69874d 100644 --- a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalBodyPart.java +++ b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalBodyPart.java @@ -7,15 +7,17 @@ import com.fsck.k9.mail.internet.MimeBodyPart; public class LocalBodyPart extends MimeBodyPart implements LocalPart { private final String accountUuid; + private final LocalMessage message; private final long messagePartId; private final String displayName; private final long size; private final boolean firstClassAttachment; - public LocalBodyPart(String accountUuid, long messagePartId, String displayName, long size, + public LocalBodyPart(String accountUuid, LocalMessage message, long messagePartId, String displayName, long size, boolean firstClassAttachment) throws MessagingException { super(); this.accountUuid = accountUuid; + this.message = message; this.messagePartId = messagePartId; this.displayName = displayName; this.size = size; @@ -46,4 +48,9 @@ public class LocalBodyPart extends MimeBodyPart implements LocalPart { public boolean isFirstClassAttachment() { return firstClassAttachment; } + + @Override + public LocalMessage getMessage() { + return message; + } } diff --git a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalFolder.java b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalFolder.java index 0d90f09a4..61e1b6ff0 100644 --- a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalFolder.java +++ b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalFolder.java @@ -689,7 +689,8 @@ public class LocalFolder extends Folder implements Serializable { String parentMimeType = parentPart.getMimeType(); if (parentMimeType.startsWith("multipart/")) { - BodyPart bodyPart = new LocalBodyPart(getAccountUuid(), id, displayName, size, firstClassAttachment); + BodyPart bodyPart = new LocalBodyPart(getAccountUuid(), message, id, displayName, size, + firstClassAttachment); ((Multipart) parentPart.getBody()).addBodyPart(bodyPart); part = bodyPart; } else if (parentMimeType.startsWith("message/")) { diff --git a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalPart.java b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalPart.java index 6fb9c50fd..134212812 100644 --- a/k9mail/src/main/java/com/fsck/k9/mailstore/LocalPart.java +++ b/k9mail/src/main/java/com/fsck/k9/mailstore/LocalPart.java @@ -7,4 +7,5 @@ public interface LocalPart { String getDisplayName(); long getSize(); boolean isFirstClassAttachment(); + LocalMessage getMessage(); } diff --git a/k9mail/src/main/java/com/fsck/k9/ui/messageview/AttachmentController.java b/k9mail/src/main/java/com/fsck/k9/ui/messageview/AttachmentController.java index 36c2c8be7..b5f2021ee 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/messageview/AttachmentController.java +++ b/k9mail/src/main/java/com/fsck/k9/ui/messageview/AttachmentController.java @@ -19,29 +19,44 @@ import android.os.Environment; import android.util.Log; import android.widget.Toast; +import com.fsck.k9.Account; import com.fsck.k9.K9; +import com.fsck.k9.Preferences; 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.mail.Message; +import com.fsck.k9.mail.Part; import com.fsck.k9.mail.internet.MimeUtility; import com.fsck.k9.mailstore.AttachmentViewInfo; +import com.fsck.k9.mailstore.LocalMessage; +import com.fsck.k9.mailstore.LocalPart; import org.apache.commons.io.IOUtils; public class AttachmentController { private final Context context; - private final SingleMessageView messageView; + private final MessagingController controller; + private final MessageViewFragment messageViewFragment; private final AttachmentViewInfo attachment; - AttachmentController(SingleMessageView messageView, AttachmentViewInfo attachment) { - this.context = messageView.getContext(); - this.messageView = messageView; + AttachmentController(MessagingController controller, MessageViewFragment messageViewFragment, + AttachmentViewInfo attachment) { + this.context = messageViewFragment.getContext(); + this.controller = controller; + this.messageViewFragment = messageViewFragment; this.attachment = attachment; } public void viewAttachment() { - new ViewAttachmentAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + if (needsDownloading()) { + downloadAndViewAttachment((LocalPart) attachment.part); + } else { + viewLocalAttachment(); + } } public void saveAttachment() { @@ -52,6 +67,60 @@ public class AttachmentController { saveAttachmentTo(new File(directory)); } + private boolean needsDownloading() { + return isPartMissing() && isLocalPart(); + } + + private boolean isPartMissing() { + return attachment.part.getBody() == null; + } + + private boolean isLocalPart() { + return attachment.part instanceof LocalPart; + } + + private void downloadAndViewAttachment(LocalPart localPart) { + downloadAttachment(localPart, new Runnable() { + @Override + public void run() { + viewLocalAttachment(); + } + }); + } + + private void downloadAndSaveAttachmentTo(LocalPart localPart, final File directory) { + downloadAttachment(localPart, new Runnable() { + @Override + public void run() { + saveAttachmentTo(directory); + } + }); + } + + private void downloadAttachment(LocalPart localPart, final Runnable attachmentDownloadedCallback) { + String accountUuid = localPart.getAccountUuid(); + Account account = Preferences.getPreferences(context).getAccount(accountUuid); + LocalMessage message = localPart.getMessage(); + + messageViewFragment.showAttachmentLoadingDialog(); + controller.loadAttachment(account, message, attachment.part, new MessagingListener() { + @Override + public void loadAttachmentFinished(Account account, Message message, Part part) { + messageViewFragment.hideAttachmentLoadingDialogOnMainThread(); + messageViewFragment.runOnMainThread(attachmentDownloadedCallback); + } + + @Override + public void loadAttachmentFailed(Account account, Message message, Part part, String reason) { + messageViewFragment.hideAttachmentLoadingDialogOnMainThread(); + } + }); + } + + private void viewLocalAttachment() { + new ViewAttachmentAsyncTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); + } + private void saveAttachmentTo(File directory) { boolean isExternalStorageMounted = Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED); if (!isExternalStorageMounted) { @@ -60,6 +129,14 @@ public class AttachmentController { return; } + if (needsDownloading()) { + downloadAndSaveAttachmentTo((LocalPart) attachment.part, directory); + } else { + saveLocalAttachmentTo(directory); + } + } + + private void saveLocalAttachmentTo(File directory) { //FIXME: write file in background thread try { File file = saveAttachmentWithUniqueFileName(directory); @@ -187,7 +264,7 @@ public class AttachmentController { } private void addUiIntentFlags(Intent intent) { - intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_WHEN_TASK_RESET); } private int getResolvedIntentActivitiesCount(Intent intent) { @@ -243,7 +320,7 @@ public class AttachmentController { @Override protected void onPreExecute() { - messageView.disableAttachmentViewButton(attachment); + messageViewFragment.disableAttachmentButtons(attachment); } @Override @@ -254,7 +331,7 @@ public class AttachmentController { @Override protected void onPostExecute(Intent intent) { viewAttachment(intent); - messageView.enableAttachmentViewButton(attachment); + messageViewFragment.enableAttachmentButtons(attachment); } private void viewAttachment(Intent intent) { diff --git a/k9mail/src/main/java/com/fsck/k9/ui/messageview/AttachmentView.java b/k9mail/src/main/java/com/fsck/k9/ui/messageview/AttachmentView.java index b93bb453a..2713da359 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/messageview/AttachmentView.java +++ b/k9mail/src/main/java/com/fsck/k9/ui/messageview/AttachmentView.java @@ -43,12 +43,14 @@ public class AttachmentView extends FrameLayout implements OnClickListener, OnLo return attachment; } - public void enableViewButton() { + public void enableButtons() { viewButton.setEnabled(true); + downloadButton.setEnabled(true); } - public void disableViewButton() { + public void disableButtons() { viewButton.setEnabled(false); + downloadButton.setEnabled(false); } public void setAttachment(AttachmentViewInfo attachment) throws MessagingException { diff --git a/k9mail/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.java b/k9mail/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.java index c91033128..67657f1c6 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.java +++ b/k9mail/src/main/java/com/fsck/k9/ui/messageview/MessageViewFragment.java @@ -663,6 +663,37 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF } } + public Context getContext() { + return mContext; + } + + public void disableAttachmentButtons(AttachmentViewInfo attachment) { + mMessageView.disableAttachmentButtons(attachment); + } + + public void enableAttachmentButtons(AttachmentViewInfo attachment) { + mMessageView.enableAttachmentButtons(attachment); + } + + public void runOnMainThread(Runnable runnable) { + handler.post(runnable); + } + + public void showAttachmentLoadingDialog() { + mMessageView.disableAttachmentButtons(); + showDialog(R.id.dialog_attachment_progress); + } + + public void hideAttachmentLoadingDialogOnMainThread() { + handler.post(new Runnable() { + @Override + public void run() { + removeDialog(R.id.dialog_attachment_progress); + mMessageView.enableAttachmentButtons(); + } + }); + } + public interface MessageViewFragmentListener { public void onForward(LocalMessage mMessage, PgpData mPgpData); public void disableDeleteAction(); @@ -760,7 +791,7 @@ public class MessageViewFragment extends Fragment implements ConfirmationDialogF } private AttachmentController getAttachmentController(AttachmentViewInfo attachment) { - return new AttachmentController(mMessageView, attachment); + return new AttachmentController(mController, this, attachment); } private class DownloadMessageListener extends MessagingListener { diff --git a/k9mail/src/main/java/com/fsck/k9/ui/messageview/SingleMessageView.java b/k9mail/src/main/java/com/fsck/k9/ui/messageview/SingleMessageView.java index a7f2abebf..433d0911b 100644 --- a/k9mail/src/main/java/com/fsck/k9/ui/messageview/SingleMessageView.java +++ b/k9mail/src/main/java/com/fsck/k9/ui/messageview/SingleMessageView.java @@ -500,6 +500,18 @@ public class SingleMessageView extends LinearLayout implements OnClickListener, } } + public void enableAttachmentButtons() { + for (AttachmentView attachmentView : attachments.values()) { + attachmentView.enableButtons(); + } + } + + public void disableAttachmentButtons() { + for (AttachmentView attachmentView : attachments.values()) { + attachmentView.disableButtons(); + } + } + public void showAllHeaders() { mHeaderContainer.onShowAdditionalHeaders(); } @@ -701,12 +713,12 @@ public class SingleMessageView extends LinearLayout implements OnClickListener, } } - public void enableAttachmentViewButton(AttachmentViewInfo attachment) { - getAttachmentView(attachment).enableViewButton(); + public void enableAttachmentButtons(AttachmentViewInfo attachment) { + getAttachmentView(attachment).enableButtons(); } - public void disableAttachmentViewButton(AttachmentViewInfo attachment) { - getAttachmentView(attachment).disableViewButton(); + public void disableAttachmentButtons(AttachmentViewInfo attachment) { + getAttachmentView(attachment).disableButtons(); } private AttachmentView getAttachmentView(AttachmentViewInfo attachment) {