1
0
mirror of https://github.com/moparisthebest/k-9 synced 2025-03-01 09:01:47 -05:00

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.
This commit is contained in:
cketti 2012-01-22 05:14:58 +01:00
parent 96f827d291
commit bddacf6b64
3 changed files with 80 additions and 35 deletions

View File

@ -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_REFUSE_TO_SAVE_DRAFT_MARKED_ENCRYPTED = 2;
private static final int DIALOG_CONTINUE_WITHOUT_PUBLIC_KEY = 3; 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_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 = "com.fsck.k9.intent.action.REPLY";
private static final String ACTION_REPLY_ALL = "com.fsck.k9.intent.action.REPLY_ALL"; 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"; "com.fsck.k9.activity.MessageCompose.QuotedTextShown";
private static final String STATE_KEY_SOURCE_MESSAGE_PROCED = private static final String STATE_KEY_SOURCE_MESSAGE_PROCED =
"com.fsck.k9.activity.MessageCompose.stateKeySourceMessageProced"; "com.fsck.k9.activity.MessageCompose.stateKeySourceMessageProced";
private static final String STATE_KEY_DRAFT_UID = private static final String STATE_KEY_DRAFT_ID = "com.fsck.k9.activity.MessageCompose.draftId";
"com.fsck.k9.activity.MessageCompose.draftUid";
private static final String STATE_KEY_HTML_QUOTE = "com.fsck.k9.activity.MessageCompose.HTMLQuote"; private static final String STATE_KEY_HTML_QUOTE = "com.fsck.k9.activity.MessageCompose.HTMLQuote";
private static final String STATE_IDENTITY_CHANGED = private static final String STATE_IDENTITY_CHANGED =
"com.fsck.k9.activity.MessageCompose.identityChanged"; "com.fsck.k9.activity.MessageCompose.identityChanged";
@ -228,10 +229,11 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
private boolean mIgnoreOnStop = false; private boolean mIgnoreOnStop = false;
/** /**
* The draft uid of this message. This is used when saving drafts so that the same draft is * The database ID of this message's draft. This is used when saving drafts so the message in
* overwritten instead of being created anew. This property is null until the first save. * 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() { private Handler mHandler = new Handler() {
@Override @Override
@ -893,7 +895,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
outState.putBoolean(STATE_KEY_BCC_SHOWN, mBccWrapper.getVisibility() == View.VISIBLE); outState.putBoolean(STATE_KEY_BCC_SHOWN, mBccWrapper.getVisibility() == View.VISIBLE);
outState.putSerializable(STATE_KEY_QUOTED_TEXT_MODE, mQuotedTextMode); outState.putSerializable(STATE_KEY_QUOTED_TEXT_MODE, mQuotedTextMode);
outState.putBoolean(STATE_KEY_SOURCE_MESSAGE_PROCED, mSourceMessageProcessed); 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.putSerializable(STATE_IDENTITY, mIdentity);
outState.putBoolean(STATE_IDENTITY_CHANGED, mIdentityChanged); outState.putBoolean(STATE_IDENTITY_CHANGED, mIdentityChanged);
outState.putSerializable(STATE_PGP_DATA, mPgpData); 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); 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); mIdentity = (Identity)savedInstanceState.getSerializable(STATE_IDENTITY);
mIdentityChanged = savedInstanceState.getBoolean(STATE_IDENTITY_CHANGED); mIdentityChanged = savedInstanceState.getBoolean(STATE_IDENTITY_CHANGED);
mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA); mPgpData = (PgpData) savedInstanceState.getSerializable(STATE_PGP_DATA);
@ -1609,9 +1611,9 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
} }
private void onDiscard() { private void onDiscard() {
if (mDraftUid != null) { if (mDraftId != INVALID_DRAFT_ID) {
MessagingController.getInstance(getApplication()).deleteDraft(mAccount, mDraftUid); MessagingController.getInstance(getApplication()).deleteDraft(mAccount, mDraftId);
mDraftUid = null; mDraftId = INVALID_DRAFT_ID;
} }
mHandler.sendEmptyMessage(MSG_DISCARDED_DRAFT); mHandler.sendEmptyMessage(MSG_DISCARDED_DRAFT);
mDraftNeedsSaving = false; mDraftNeedsSaving = false;
@ -1817,12 +1819,12 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
} }
// test whether there is something to save // test whether there is something to save
if (mDraftNeedsSaving || (mDraftUid != null)) { if (mDraftNeedsSaving || (mDraftId != INVALID_DRAFT_ID)) {
final String previousDraftUid = mDraftUid; final long previousDraftId = mDraftId;
final Account previousAccount = mAccount; final Account previousAccount = mAccount;
// make current message appear as new // make current message appear as new
mDraftUid = null; mDraftId = INVALID_DRAFT_ID;
// actual account switch // actual account switch
mAccount = account; mAccount = account;
@ -1832,13 +1834,13 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
} }
saveMessage(); saveMessage();
if (previousDraftUid != null) { if (previousDraftId != INVALID_DRAFT_ID) {
if (K9.DEBUG) { if (K9.DEBUG) {
Log.v(K9.LOG_TAG, "Account switch, deleting draft from previous account: " Log.v(K9.LOG_TAG, "Account switch, deleting draft from previous account: "
+ previousDraftUid); + previousDraftId);
} }
MessagingController.getInstance(getApplication()).deleteDraft(previousAccount, MessagingController.getInstance(getApplication()).deleteDraft(previousAccount,
previousDraftUid); previousDraftId);
} }
} else { } else {
mAccount = account; mAccount = account;
@ -2264,7 +2266,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
} else if (ACTION_EDIT_DRAFT.equals(action)) { } else if (ACTION_EDIT_DRAFT.equals(action)) {
String showQuotedTextMode = "NONE"; String showQuotedTextMode = "NONE";
mDraftUid = message.getUid(); mDraftId = MessagingController.getInstance(getApplication()).getId(message);
mSubjectView.setText(message.getSubject()); mSubjectView.setText(message.getSubject());
addAddresses(mToView, message.getRecipients(RecipientType.TO)); addAddresses(mToView, message.getRecipients(RecipientType.TO));
if (message.getRecipients(RecipientType.CC).length > 0) { if (message.getRecipients(RecipientType.CC).length > 0) {
@ -2854,14 +2856,6 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
@Override @Override
public void messageUidChanged(Account account, String folder, String oldUid, String newUid) { 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 // Track UID changes of the source message
if (mMessageReference != null) { if (mMessageReference != null) {
final Account sourceAccount = Preferences.getPreferences(MessageCompose.this).getAccount(mMessageReference.accountUuid); 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); MessagingController.getInstance(getApplication()).sendMessage(mAccount, message, null);
if (mDraftUid != null) { if (mDraftId != INVALID_DRAFT_ID) {
MessagingController.getInstance(getApplication()).deleteDraft(mAccount, mDraftUid); MessagingController.getInstance(getApplication()).deleteDraft(mAccount, mDraftId);
mDraftUid = null; mDraftId = INVALID_DRAFT_ID;
} }
return null; return null;
@ -2983,9 +2977,7 @@ public class MessageCompose extends K9Activity implements OnClickListener, OnFoc
/* /*
* Save a draft * Save a draft
*/ */
if (mDraftUid != null) { if (ACTION_EDIT_DRAFT.equals(getIntent().getAction())) {
message.setUid(mDraftUid);
} else if (ACTION_EDIT_DRAFT.equals(getIntent().getAction())) {
/* /*
* We're saving a previously saved draft, so update the new message's uid * We're saving a previously saved draft, so update the new message's uid
* to the old 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()); final MessagingController messagingController = MessagingController.getInstance(getApplication());
Message draftMessage = messagingController.saveDraft(mAccount, message); Message draftMessage = messagingController.saveDraft(mAccount, message, mDraftId);
mDraftUid = draftMessage.getUid(); mDraftId = messagingController.getId(draftMessage);
mHandler.sendEmptyMessage(MSG_SAVED_DRAFT); mHandler.sendEmptyMessage(MSG_SAVED_DRAFT);
return null; return null;

View File

@ -79,6 +79,7 @@ import com.fsck.k9.mail.store.LocalStore.PendingCommand;
* removed from the queue once the activity is no longer active. * removed from the queue once the activity is no longer active.
*/ */
public class MessagingController implements Runnable { public class MessagingController implements Runnable {
public static final long INVALID_MESSAGE_ID = -1;
/** /**
* Immutable empty {@link String} array * 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; LocalFolder localFolder = null;
try { try {
LocalStore localStore = account.getLocalStore(); LocalStore localStore = account.getLocalStore();
localFolder = localStore.getFolder(account.getDraftsFolderName()); localFolder = localStore.getFolder(account.getDraftsFolderName());
localFolder.open(OpenMode.READ_WRITE); localFolder.open(OpenMode.READ_WRITE);
String uid = localFolder.getMessageUidById(id);
Message message = localFolder.getMessage(uid); Message message = localFolder.getMessage(uid);
if (message != null) { if (message != null) {
deleteMessages(new Message[] { message }, null); deleteMessages(new Message[] { message }, null);
@ -4059,12 +4061,18 @@ public class MessagingController implements Runnable {
* @param message Message to save. * @param message Message to save.
* @return Message representing the entry in the local store. * @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; Message localMessage = null;
try { try {
LocalStore localStore = account.getLocalStore(); LocalStore localStore = account.getLocalStore();
LocalFolder localFolder = localStore.getFolder(account.getDraftsFolderName()); LocalFolder localFolder = localStore.getFolder(account.getDraftsFolderName());
localFolder.open(OpenMode.READ_WRITE); localFolder.open(OpenMode.READ_WRITE);
if (existingDraftId != INVALID_MESSAGE_ID) {
String uid = localFolder.getMessageUidById(existingDraftId);
message.setUid(uid);
}
// Save the message to the store. // Save the message to the store.
localFolder.appendMessages(new Message[] { localFolder.appendMessages(new Message[] {
message message
@ -4089,6 +4097,18 @@ public class MessagingController implements Runnable {
return localMessage; 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) { public boolean modeMismatch(Account.FolderMode aMode, Folder.FolderClass fMode) {
if (aMode == Account.FolderMode.NONE if (aMode == Account.FolderMode.NONE
|| (aMode == Account.FolderMode.FIRST_CLASS && || (aMode == Account.FolderMode.FIRST_CLASS &&

View File

@ -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<String>() {
@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 @Override
public Message getMessage(final String uid) throws MessagingException { public Message getMessage(final String uid) throws MessagingException {
try { try {