compose: use MessageLoaderHelper for quoted message loading (fixes MessageCompose)
This commit is contained in:
parent
b72dba67df
commit
2e9184f8e2
2 changed files with 83 additions and 116 deletions
|
@ -19,6 +19,7 @@ import android.content.ClipData;
|
|||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentSender;
|
||||
import android.content.IntentSender.SendIntentException;
|
||||
import android.content.Loader;
|
||||
import android.content.pm.ActivityInfo;
|
||||
|
@ -55,6 +56,7 @@ import com.fsck.k9.Identity;
|
|||
import com.fsck.k9.K9;
|
||||
import com.fsck.k9.Preferences;
|
||||
import com.fsck.k9.R;
|
||||
import com.fsck.k9.activity.MessageLoaderHelper.MessageLoaderCallbacks;
|
||||
import com.fsck.k9.activity.compose.ComposeCryptoStatus;
|
||||
import com.fsck.k9.activity.compose.ComposeCryptoStatus.AttachErrorState;
|
||||
import com.fsck.k9.activity.compose.ComposeCryptoStatus.SendErrorState;
|
||||
|
@ -89,6 +91,7 @@ import com.fsck.k9.mail.internet.MimeMessage;
|
|||
import com.fsck.k9.mail.internet.MimeUtility;
|
||||
import com.fsck.k9.mailstore.LocalBodyPart;
|
||||
import com.fsck.k9.mailstore.LocalMessage;
|
||||
import com.fsck.k9.mailstore.MessageViewInfo;
|
||||
import com.fsck.k9.message.ComposePgpInlineDecider;
|
||||
import com.fsck.k9.message.IdentityField;
|
||||
import com.fsck.k9.message.IdentityHeaderParser;
|
||||
|
@ -157,6 +160,9 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
|
||||
private static final int REQUEST_MASK_RECIPIENT_PRESENTER = (1<<8);
|
||||
private static final int REQUEST_MASK_MESSAGE_BUILDER = (2<<8);
|
||||
private static final int REQUEST_MASK_LOADER_HELPER = (3<<8);
|
||||
|
||||
private static final int INITIAL_MAX_LOADER_ID = 128;
|
||||
|
||||
/**
|
||||
* Regular expression to remove the first localized "Re:" prefix in subjects.
|
||||
|
@ -166,6 +172,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
*/
|
||||
private static final Pattern PREFIX = Pattern.compile("^AW[:\\s]\\s*", Pattern.CASE_INSENSITIVE);
|
||||
private QuotedMessagePresenter quotedMessagePresenter;
|
||||
private MessageLoaderHelper messageLoaderHelper;
|
||||
|
||||
/**
|
||||
* The account used for message composition.
|
||||
|
@ -196,7 +203,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
* have already been added from the restore of the view state.
|
||||
*/
|
||||
private boolean mSourceMessageProcessed = false;
|
||||
private int mMaxLoaderId = 0;
|
||||
private int mMaxLoaderId = INITIAL_MAX_LOADER_ID;
|
||||
|
||||
private RecipientPresenter recipientPresenter;
|
||||
private MessageBuilder currentMessageBuilder;
|
||||
|
@ -249,8 +256,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
*/
|
||||
private Action mAction;
|
||||
|
||||
private Listener mListener = new Listener();
|
||||
|
||||
private boolean mReadReceipt = false;
|
||||
|
||||
private TextView mChooseIdentityButton;
|
||||
|
@ -345,7 +350,6 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
if (UpgradeDatabases.actionUpgradeDatabases(this, getIntent())) {
|
||||
|
@ -507,18 +511,10 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
if (!mSourceMessageProcessed) {
|
||||
if (mAction == Action.REPLY || mAction == Action.REPLY_ALL ||
|
||||
mAction == Action.FORWARD || mAction == Action.EDIT_DRAFT) {
|
||||
/*
|
||||
* If we need to load the message we add ourself as a message listener here
|
||||
* so we can kick it off. Normally we add in onResume but we don't
|
||||
* want to reload the message every time the activity is resumed.
|
||||
* There is no harm in adding twice.
|
||||
*/
|
||||
MessagingController.getInstance(getApplication()).addListener(mListener);
|
||||
|
||||
final Account account = Preferences.getPreferences(this).getAccount(mMessageReference.getAccountUuid());
|
||||
final String folderName = mMessageReference.getFolderName();
|
||||
final String sourceMessageUid = mMessageReference.getUid();
|
||||
MessagingController.getInstance(getApplication()).loadMessageForView(account, folderName, sourceMessageUid, null);
|
||||
messageLoaderHelper = new MessageLoaderHelper(this, getLoaderManager(), getFragmentManager(),
|
||||
messageLoaderCallbacks);
|
||||
mHandler.sendEmptyMessage(MSG_PROGRESS_ON);
|
||||
messageLoaderHelper.asyncStartOrResumeLoadingMessage(mMessageReference);
|
||||
}
|
||||
|
||||
if (mAction != Action.EDIT_DRAFT) {
|
||||
|
@ -668,15 +664,15 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
MessagingController.getInstance(getApplication()).addListener(mListener);
|
||||
MessagingController.getInstance(this).addListener(messagingListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
MessagingController.getInstance(getApplication()).removeListener(mListener);
|
||||
MessagingController.getInstance(this).removeListener(messagingListener);
|
||||
|
||||
boolean isPausingOnConfigurationChange = (getChangingConfigurations() & ActivityInfo.CONFIG_ORIENTATION)
|
||||
== ActivityInfo.CONFIG_ORIENTATION;
|
||||
|
@ -731,7 +727,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
super.onRestoreInstanceState(savedInstanceState);
|
||||
|
||||
mAttachments.removeAllViews();
|
||||
mMaxLoaderId = 0;
|
||||
mMaxLoaderId = INITIAL_MAX_LOADER_ID;
|
||||
|
||||
mNumAttachmentsLoading = savedInstanceState.getInt(STATE_KEY_NUM_ATTACHMENTS_LOADING);
|
||||
mWaitingForAttachments = WaitingAction.NONE;
|
||||
|
@ -1150,6 +1146,12 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
return;
|
||||
}
|
||||
|
||||
if ((requestCode & REQUEST_MASK_LOADER_HELPER) == REQUEST_MASK_LOADER_HELPER) {
|
||||
requestCode ^= REQUEST_MASK_LOADER_HELPER;
|
||||
messageLoaderHelper.onActivityResult(requestCode, resultCode, data);
|
||||
return;
|
||||
}
|
||||
|
||||
if (resultCode != RESULT_OK) {
|
||||
return;
|
||||
}
|
||||
|
@ -1533,12 +1535,7 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
throw new IllegalStateException("tried to edit quoted message with no referenced message");
|
||||
}
|
||||
|
||||
// TODO - Should we check if mSourceMessageBody is already present and bypass the MessagingController call?
|
||||
MessagingController.getInstance(getApplication()).addListener(mListener);
|
||||
final Account account = Preferences.getPreferences(this).getAccount(mMessageReference.getAccountUuid());
|
||||
final String folderName = mMessageReference.getFolderName();
|
||||
final String sourceMessageUid = mMessageReference.getUid();
|
||||
MessagingController.getInstance(getApplication()).loadMessageForView(account, folderName, sourceMessageUid, null);
|
||||
messageLoaderHelper.asyncStartOrResumeLoadingMessage(mMessageReference);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -1943,67 +1940,88 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
}
|
||||
}
|
||||
|
||||
class Listener extends MessagingListener {
|
||||
private MessageLoaderCallbacks messageLoaderCallbacks = new MessageLoaderCallbacks() {
|
||||
@Override
|
||||
public void loadMessageForViewStarted(Account account, String folder, String uid) {
|
||||
if (mMessageReference == null || !mMessageReference.getUid().equals(uid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
mHandler.sendEmptyMessage(MSG_PROGRESS_ON);
|
||||
public void onMessageDataLoadFinished(LocalMessage message) {
|
||||
// nothing to do here, we don't care about message headers
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMessageForViewFinished(Account account, String folder, String uid) {
|
||||
if (mMessageReference == null || !mMessageReference.getUid().equals(uid)) {
|
||||
return;
|
||||
}
|
||||
|
||||
public void onMessageDataLoadFailed() {
|
||||
mHandler.sendEmptyMessage(MSG_PROGRESS_OFF);
|
||||
Toast.makeText(MessageCompose.this, R.string.status_invalid_id_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
if (mMessageReference == null || !mMessageReference.getUid().equals(uid)) {
|
||||
return;
|
||||
@Override
|
||||
public void onMessageViewInfoLoadFinished(LocalMessage localMessage, MessageViewInfo messageViewInfo) {
|
||||
mHandler.sendEmptyMessage(MSG_PROGRESS_OFF);
|
||||
loadLocalMessageForDisplay(localMessage, mAction);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onMessageViewInfoLoadFailed(LocalMessage localMessage) {
|
||||
mHandler.sendEmptyMessage(MSG_PROGRESS_OFF);
|
||||
Toast.makeText(MessageCompose.this, R.string.status_invalid_id_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setLoadingProgress(int current, int max) {
|
||||
// nvm - we don't have a progress bar
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startIntentSenderForMessageLoaderHelper(IntentSender si, int requestCode, Intent fillIntent,
|
||||
int flagsMask, int flagValues, int extraFlags) {
|
||||
try {
|
||||
requestCode |= REQUEST_MASK_LOADER_HELPER;
|
||||
startIntentSenderForResult(si, requestCode, fillIntent, flagsMask, flagValues, extraFlags);
|
||||
} catch (SendIntentException e) {
|
||||
Log.e(K9.LOG_TAG, "Irrecoverable error calling PendingIntent!", e);
|
||||
}
|
||||
}
|
||||
|
||||
final LocalMessage message = null; // TODO this isn't working at the moment!
|
||||
|
||||
@Override
|
||||
public void onDownloadErrorMessageNotFound() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
// We check to see if we've previously processed the source message since this
|
||||
// could be called when switching from HTML to text replies. If that happens, we
|
||||
// only want to update the UI with quoted text (which picks the appropriate
|
||||
// part).
|
||||
loadLocalMessageForDisplay(message, mAction);
|
||||
Toast.makeText(MessageCompose.this, R.string.status_invalid_id_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadMessageForViewFailed(Account account, String folder, String uid, Throwable t) {
|
||||
if (mMessageReference == null || !mMessageReference.getUid().equals(uid)) {
|
||||
return;
|
||||
}
|
||||
mHandler.sendEmptyMessage(MSG_PROGRESS_OFF);
|
||||
// TODO show network error
|
||||
public void onDownloadErrorNetworkError() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
Toast.makeText(MessageCompose.this, R.string.status_network_error, Toast.LENGTH_LONG).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
// TODO We miss callbacks for this listener if they happens while we are paused!
|
||||
public MessagingListener messagingListener = new MessagingListener() {
|
||||
|
||||
@Override
|
||||
public void messageUidChanged(Account account, String folder, String oldUid, String newUid) {
|
||||
// Track UID changes of the source message
|
||||
if (mMessageReference != null) {
|
||||
final Account sourceAccount = Preferences.getPreferences(MessageCompose.this)
|
||||
.getAccount(mMessageReference.getAccountUuid());
|
||||
final String sourceFolder = mMessageReference.getFolderName();
|
||||
final String sourceMessageUid = mMessageReference.getUid();
|
||||
if (mMessageReference == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (account.equals(sourceAccount) && (folder.equals(sourceFolder))) {
|
||||
if (oldUid.equals(sourceMessageUid)) {
|
||||
mMessageReference = mMessageReference.withModifiedUid(newUid);
|
||||
}
|
||||
}
|
||||
Account sourceAccount = Preferences.getPreferences(MessageCompose.this)
|
||||
.getAccount(mMessageReference.getAccountUuid());
|
||||
String sourceFolder = mMessageReference.getFolderName();
|
||||
String sourceMessageUid = mMessageReference.getUid();
|
||||
|
||||
boolean changedMessageIsCurrent =
|
||||
account.equals(sourceAccount) && folder.equals(sourceFolder) && oldUid.equals(sourceMessageUid);
|
||||
if (changedMessageIsCurrent) {
|
||||
mMessageReference = mMessageReference.withModifiedUid(newUid);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
@ -2804,57 +2804,6 @@ public class MessagingController implements Runnable {
|
|||
}
|
||||
}
|
||||
|
||||
public void loadMessageForView(final Account account, final String folder, final String uid,
|
||||
final MessagingListener listener) {
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.loadMessageForViewStarted(account, folder, uid);
|
||||
}
|
||||
threadPool.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
|
||||
try {
|
||||
LocalStore localStore = account.getLocalStore();
|
||||
LocalFolder localFolder = localStore.getFolder(folder);
|
||||
localFolder.open(Folder.OPEN_MODE_RW);
|
||||
|
||||
LocalMessage message = localFolder.getMessage(uid);
|
||||
if (message == null
|
||||
|| message.getId() == 0) {
|
||||
throw new IllegalArgumentException("Message not found: folder=" + folder + ", uid=" + uid);
|
||||
}
|
||||
// IMAP search results will usually need to be downloaded before viewing.
|
||||
// TODO: limit by account.getMaximumAutoDownloadMessageSize().
|
||||
if (!message.isSet(Flag.X_DOWNLOADED_FULL) &&
|
||||
!message.isSet(Flag.X_DOWNLOADED_PARTIAL)) {
|
||||
if (loadMessageRemoteSynchronous(account, folder, uid, listener, true)) {
|
||||
markMessageAsReadOnView(account, message);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
FetchProfile fp = new FetchProfile();
|
||||
fp.add(FetchProfile.Item.ENVELOPE);
|
||||
fp.add(FetchProfile.Item.BODY);
|
||||
localFolder.fetch(Collections.singletonList(message), fp, null);
|
||||
localFolder.close();
|
||||
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.loadMessageForViewFinished(account, folder, uid);
|
||||
}
|
||||
markMessageAsReadOnView(account, message);
|
||||
|
||||
} catch (Exception e) {
|
||||
for (MessagingListener l : getListeners(listener)) {
|
||||
l.loadMessageForViewFailed(account, folder, uid, e);
|
||||
}
|
||||
addErrorMessage(account, null, e);
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public LocalMessage loadMessage(Account account, String folderName, String uid) throws MessagingException {
|
||||
LocalStore localStore = account.getLocalStore();
|
||||
LocalFolder localFolder = localStore.getFolder(folderName);
|
||||
|
|
Loading…
Reference in a new issue