From bddacf6b646606d817cd0b6a07e03f01f30270e4 Mon Sep 17 00:00:00 2001 From: cketti Date: Sun, 22 Jan 2012 05:14:58 +0100 Subject: [PATCH] Use database ID to keep track of the current draft By using the database ID we avoid having to deal with the problem of changing UIDs. First the message has a local UID, then, when the upload to the server is completed, it gets a remote UID. --- src/com/fsck/k9/activity/MessageCompose.java | 58 ++++++++----------- .../k9/controller/MessagingController.java | 24 +++++++- src/com/fsck/k9/mail/store/LocalStore.java | 33 +++++++++++ 3 files changed, 80 insertions(+), 35 deletions(-) diff --git a/src/com/fsck/k9/activity/MessageCompose.java b/src/com/fsck/k9/activity/MessageCompose.java index fc870d9ba..48173b0a7 100644 --- a/src/com/fsck/k9/activity/MessageCompose.java +++ b/src/com/fsck/k9/activity/MessageCompose.java @@ -84,6 +84,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc private static final int DIALOG_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED = 2; private static final int DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY = 3; + private static final long INVALID_DRAFT_ID = MessagingController.INVALID_MESSAGE_ID; + private static final String ACTION_COMPOSE = "com.fsck.k9.intent.action.COMPOSE"; private static final String ACTION_REPLY = "com.fsck.k9.intent.action.REPLY"; private static final String ACTION_REPLY_ALL = "com.fsck.k9.intent.action.REPLY_ALL"; @@ -104,8 +106,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc "com.fsck.k9.activity.MessageCompose.QuotedTextShown"; private static final String STATE_KEY_SOURCE_MESSAGE_PROCED = "com.fsck.k9.activity.MessageCompose.stateKeySourceMessageProced"; - private static final String STATE_KEY_DRAFT_UID = - "com.fsck.k9.activity.MessageCompose.draftUid"; + private static final String STATE_KEY_DRAFT_ID = "com.fsck.k9.activity.MessageCompose.draftId"; private static final String STATE_KEY_HTML_QUOTE = "com.fsck.k9.activity.MessageCompose.HTMLQuote"; private static final String STATE_IDENTITY_CHANGED = "com.fsck.k9.activity.MessageCompose.identityChanged"; @@ -228,10 +229,11 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc private boolean mIgnoreOnStop = false; /** - * The draft uid of this message. This is used when saving drafts so that the same draft is - * overwritten instead of being created anew. This property is null until the first save. + * The database ID of this message's draft. This is used when saving drafts so the message in + * the database is updated instead of being created anew. This property is INVALID_DRAFT_ID + * until the first save. */ - private String mDraftUid; + private long mDraftId = INVALID_DRAFT_ID; private Handler mHandler = new Handler() { @Override @@ -893,7 +895,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc outState.putBoolean(STATE_KEY_BCC_SHOWN, mBccWrapper.getVisibility() == View.VISIBLE); outState.putSerializable(STATE_KEY_QUOTED_TEXT_MODE, mQuotedTextMode); outState.putBoolean(STATE_KEY_SOURCE_MESSAGE_PROCED, mSourceMessageProcessed); - outState.putString(STATE_KEY_DRAFT_UID, mDraftUid); + outState.putLong(STATE_KEY_DRAFT_ID, mDraftId); outState.putSerializable(STATE_IDENTITY, mIdentity); outState.putBoolean(STATE_IDENTITY_CHANGED, mIdentityChanged); outState.putSerializable(STATE_PGP_DATA, mPgpData); @@ -930,7 +932,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc mQuotedHTML.loadDataWithBaseURL("http://", mQuotedHtmlContent.getQuotedContent(), "text/html", "utf-8", null); } } - mDraftUid = savedInstanceState.getString(STATE_KEY_DRAFT_UID); + mDraftId = savedInstanceState.getLong(STATE_KEY_DRAFT_ID); mIdentity = (Identity)savedInstanceState.getSerializable(STATE_IDENTITY); mIdentityChanged = savedInstanceState.getBoolean(STATE_IDENTITY_CHANGED); mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA); @@ -1609,9 +1611,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } private void onDiscard() { - if (mDraftUid != null) { - MessagingController.getInstance(getApplication()).deleteDraft(mAccount, mDraftUid); - mDraftUid = null; + if (mDraftId != INVALID_DRAFT_ID) { + MessagingController.getInstance(getApplication()).deleteDraft(mAccount, mDraftId); + mDraftId = INVALID_DRAFT_ID; } mHandler.sendEmptyMessage(MSG_DISCARDED_DRAFT); mDraftNeedsSaving = false; @@ -1817,12 +1819,12 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } // test whether there is something to save - if (mDraftNeedsSaving || (mDraftUid != null)) { - final String previousDraftUid = mDraftUid; + if (mDraftNeedsSaving || (mDraftId != INVALID_DRAFT_ID)) { + final long previousDraftId = mDraftId; final Account previousAccount = mAccount; // make current message appear as new - mDraftUid = null; + mDraftId = INVALID_DRAFT_ID; // actual account switch mAccount = account; @@ -1832,13 +1834,13 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } saveMessage(); - if (previousDraftUid != null) { + if (previousDraftId != INVALID_DRAFT_ID) { if (K9.DEBUG) { Log.v(K9.LOG_TAG, "Account switch, deleting draft from previous account: " - + previousDraftUid); + + previousDraftId); } MessagingController.getInstance(getApplication()).deleteDraft(previousAccount, - previousDraftUid); + previousDraftId); } } else { mAccount = account; @@ -2264,7 +2266,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } else if (ACTION_EDIT_DRAFT.equals(action)) { String showQuotedTextMode = "NONE"; - mDraftUid = message.getUid(); + mDraftId = MessagingController.getInstance(getApplication()).getId(message); mSubjectView.setText(message.getSubject()); addAddresses(mToView, message.getRecipients(RecipientType.TO)); if (message.getRecipients(RecipientType.CC).length > 0) { @@ -2854,14 +2856,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc @Override public void messageUidChanged(Account account, String folder, String oldUid, String newUid) { - //TODO: is this really necessary here? mDraftUid is update after the call to MessagingController.saveDraft() - // Track UID changes of the draft message - if (account.equals(mAccount) && - folder.equals(mAccount.getDraftsFolderName()) && - oldUid.equals(mDraftUid)) { - mDraftUid = newUid; - } - // Track UID changes of the source message if (mMessageReference != null) { final Account sourceAccount = Preferences.getPreferences(MessageCompose.this).getAccount(mMessageReference.accountUuid); @@ -2957,9 +2951,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } MessagingController.getInstance(getApplication()).sendMessage(mAccount, message, null); - if (mDraftUid != null) { - MessagingController.getInstance(getApplication()).deleteDraft(mAccount, mDraftUid); - mDraftUid = null; + if (mDraftId != INVALID_DRAFT_ID) { + MessagingController.getInstance(getApplication()).deleteDraft(mAccount, mDraftId); + mDraftId = INVALID_DRAFT_ID; } return null; @@ -2983,9 +2977,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc /* * Save a draft */ - if (mDraftUid != null) { - message.setUid(mDraftUid); - } else if (ACTION_EDIT_DRAFT.equals(getIntent().getAction())) { + if (ACTION_EDIT_DRAFT.equals(getIntent().getAction())) { /* * We're saving a previously saved draft, so update the new message's uid * to the old message's uid. @@ -2996,8 +2988,8 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc } final MessagingController messagingController = MessagingController.getInstance(getApplication()); - Message draftMessage = messagingController.saveDraft(mAccount, message); - mDraftUid = draftMessage.getUid(); + Message draftMessage = messagingController.saveDraft(mAccount, message, mDraftId); + mDraftId = messagingController.getId(draftMessage); mHandler.sendEmptyMessage(MSG_SAVED_DRAFT); return null; diff --git a/src/com/fsck/k9/controller/MessagingController.java b/src/com/fsck/k9/controller/MessagingController.java index 2eedc119e..2aaa48ae1 100644 --- a/src/com/fsck/k9/controller/MessagingController.java +++ b/src/com/fsck/k9/controller/MessagingController.java @@ -79,6 +79,7 @@ import com.fsck.k9.mail.store.LocalStore.PendingCommand; * removed from the queue once the activity is no longer active. */ public class MessagingController implements Runnable { + public static final long INVALID_MESSAGE_ID = -1; /** * Immutable empty {@link String} array @@ -3303,12 +3304,13 @@ public class MessagingController implements Runnable { }); } - public void deleteDraft(final Account account, String uid) { + public void deleteDraft(final Account account, long id) { LocalFolder localFolder = null; try { LocalStore localStore = account.getLocalStore(); localFolder = localStore.getFolder(account.getDraftsFolderName()); localFolder.open(OpenMode.READ_WRITE); + String uid = localFolder.getMessageUidById(id); Message message = localFolder.getMessage(uid); if (message != null) { deleteMessages(new Message[] { message }, null); @@ -4059,12 +4061,18 @@ public class MessagingController implements Runnable { * @param message Message to save. * @return Message representing the entry in the local store. */ - public Message saveDraft(final Account account, final Message message) { + public Message saveDraft(final Account account, final Message message, long existingDraftId) { Message localMessage = null; try { LocalStore localStore = account.getLocalStore(); LocalFolder localFolder = localStore.getFolder(account.getDraftsFolderName()); localFolder.open(OpenMode.READ_WRITE); + + if (existingDraftId != INVALID_MESSAGE_ID) { + String uid = localFolder.getMessageUidById(existingDraftId); + message.setUid(uid); + } + // Save the message to the store. localFolder.appendMessages(new Message[] { message @@ -4089,6 +4097,18 @@ public class MessagingController implements Runnable { return localMessage; } + public long getId(Message message) { + long id; + if (message instanceof LocalMessage) { + id = ((LocalMessage) message).getId(); + } else { + Log.w(K9.LOG_TAG, "MessagingController.getId() called without a LocalMessage"); + id = INVALID_MESSAGE_ID; + } + + return id; + } + public boolean modeMismatch(Account.FolderMode aMode, Folder.FolderClass fMode) { if (aMode == Account.FolderMode.NONE || (aMode == Account.FolderMode.FIRST_CLASS && diff --git a/src/com/fsck/k9/mail/store/LocalStore.java b/src/com/fsck/k9/mail/store/LocalStore.java index 21d2865fb..abfa3ed1d 100644 --- a/src/com/fsck/k9/mail/store/LocalStore.java +++ b/src/com/fsck/k9/mail/store/LocalStore.java @@ -1798,6 +1798,39 @@ public class LocalStore extends Store implements Serializable { }); } + public String getMessageUidById(final long id) throws MessagingException { + try { + return database.execute(false, new DbCallback() { + @Override + public String doDbWork(final SQLiteDatabase db) throws WrappedException, UnavailableStorageException { + try { + open(OpenMode.READ_WRITE); + Cursor cursor = null; + + try { + cursor = db.rawQuery( + "SELECT uid FROM messages " + + "WHERE id = ? AND folder_id = ?", + new String[] { + Long.toString(id), Long.toString(mFolderId) + }); + if (!cursor.moveToNext()) { + return null; + } + return cursor.getString(0); + } finally { + Utility.closeQuietly(cursor); + } + } catch (MessagingException e) { + throw new WrappedException(e); + } + } + }); + } catch (WrappedException e) { + throw(MessagingException) e.getCause(); + } + } + @Override public Message getMessage(final String uid) throws MessagingException { try {