Save drafts for recipients without an existing thread

- Save drafts without thread in draft database
- Clear drafts when deleting conversation(s), otherwise
  the drafts stay in the database and will reappear when a thread
  with the same threadId is created

Closes #1510
This commit is contained in:
AsamK 2015-01-04 00:25:35 +01:00 committed by Moxie Marlinspike
parent 20d43bbfcb
commit fe5fc411a7
3 changed files with 44 additions and 15 deletions

View File

@ -23,8 +23,6 @@ import android.content.Context;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.Intent; import android.content.Intent;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.net.Uri; import android.net.Uri;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
@ -92,7 +90,6 @@ import org.thoughtcrime.securesms.sms.OutgoingEncryptedMessage;
import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage; import org.thoughtcrime.securesms.sms.OutgoingEndSessionMessage;
import org.thoughtcrime.securesms.sms.OutgoingTextMessage; import org.thoughtcrime.securesms.sms.OutgoingTextMessage;
import org.thoughtcrime.securesms.util.BitmapDecodingException; import org.thoughtcrime.securesms.util.BitmapDecodingException;
import org.thoughtcrime.securesms.util.BitmapUtil;
import org.thoughtcrime.securesms.util.CharacterCalculator; import org.thoughtcrime.securesms.util.CharacterCalculator;
import org.thoughtcrime.securesms.util.Dialogs; import org.thoughtcrime.securesms.util.Dialogs;
import org.thoughtcrime.securesms.util.DirectoryHelper; import org.thoughtcrime.securesms.util.DirectoryHelper;
@ -538,6 +535,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
public void onClick(DialogInterface dialog, int which) { public void onClick(DialogInterface dialog, int which) {
if (threadId > 0) { if (threadId > 0) {
DatabaseFactory.getThreadDatabase(ConversationActivity.this).deleteConversation(threadId); DatabaseFactory.getThreadDatabase(ConversationActivity.this).deleteConversation(threadId);
threadId = -1;
finish(); finish();
} }
} }
@ -919,28 +917,34 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
} }
private void saveDraft() { private void saveDraft() {
if (this.threadId <= 0 || this.recipients == null || this.recipients.isEmpty()) if (this.recipients == null || this.recipients.isEmpty())
return; return;
final Drafts drafts = getDraftsForCurrentState(); final Drafts drafts = getDraftsForCurrentState();
final long thisThreadId = this.threadId; final long thisThreadId = this.threadId;
final MasterSecret thisMasterSecret = this.masterSecret.parcelClone(); final MasterSecret thisMasterSecret = this.masterSecret.parcelClone();
final int thisDistributionType = this.distributionType;
new AsyncTask<Void, Void, Void>() { new AsyncTask<Long, Void, Void>() {
@Override @Override
protected Void doInBackground(Void... params) { protected Void doInBackground(Long... params) {
MasterCipher masterCipher = new MasterCipher(thisMasterSecret);
DatabaseFactory.getDraftDatabase(ConversationActivity.this).insertDrafts(masterCipher, thisThreadId, drafts);
ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(ConversationActivity.this); ThreadDatabase threadDatabase = DatabaseFactory.getThreadDatabase(ConversationActivity.this);
DraftDatabase draftDatabase = DatabaseFactory.getDraftDatabase(ConversationActivity.this);
long threadId = params[0];
if (drafts.size() > 0) { if (drafts.size() > 0) {
threadDatabase.updateSnippet(thisThreadId, drafts.getSnippet(ConversationActivity.this), Types.BASE_DRAFT_TYPE); if (threadId == -1) threadId = threadDatabase.getThreadIdFor(getRecipients(), thisDistributionType);
} else {
threadDatabase.update(thisThreadId); draftDatabase.insertDrafts(new MasterCipher(thisMasterSecret), threadId, drafts);
threadDatabase.updateSnippet(threadId, drafts.getSnippet(ConversationActivity.this), Types.BASE_DRAFT_TYPE);
} else if (threadId > 0) {
threadDatabase.update(threadId);
} }
MemoryCleaner.clean(thisMasterSecret); MemoryCleaner.clean(thisMasterSecret);
return null; return null;
} }
}.execute(); }.execute(thisThreadId);
} }
private void calculateCharactersRemaining() { private void calculateCharactersRemaining() {

View File

@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.crypto.MasterCipher;
import java.util.LinkedList; import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.Set;
public class DraftDatabase extends Database { public class DraftDatabase extends Database {
@ -51,6 +52,27 @@ public class DraftDatabase extends Database {
db.delete(TABLE_NAME, THREAD_ID + " = ?", new String[] {threadId+""}); db.delete(TABLE_NAME, THREAD_ID + " = ?", new String[] {threadId+""});
} }
public void clearDrafts(Set<Long> threadIds) {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
StringBuilder where = new StringBuilder();
List<String> arguments = new LinkedList<>();
for (long threadId : threadIds) {
where.append(" OR ")
.append(THREAD_ID)
.append(" = ?");
arguments.add(String.valueOf(threadId));
}
db.delete(TABLE_NAME, where.toString().substring(4), arguments.toArray(new String[0]));
}
public void clearAllDrafts() {
SQLiteDatabase db = databaseHelper.getWritableDatabase();
db.delete(TABLE_NAME, null, null);
}
public List<Draft> getDrafts(MasterCipher masterCipher, long threadId) { public List<Draft> getDrafts(MasterCipher masterCipher, long threadId) {
SQLiteDatabase db = databaseHelper.getReadableDatabase(); SQLiteDatabase db = databaseHelper.getReadableDatabase();
List<Draft> results = new LinkedList<Draft>(); List<Draft> results = new LinkedList<Draft>();

View File

@ -290,6 +290,7 @@ public class ThreadDatabase extends Database {
public void deleteConversation(long threadId) { public void deleteConversation(long threadId) {
DatabaseFactory.getSmsDatabase(context).deleteThread(threadId); DatabaseFactory.getSmsDatabase(context).deleteThread(threadId);
DatabaseFactory.getMmsDatabase(context).deleteThread(threadId); DatabaseFactory.getMmsDatabase(context).deleteThread(threadId);
DatabaseFactory.getDraftDatabase(context).clearDrafts(threadId);
deleteThread(threadId); deleteThread(threadId);
notifyConversationListeners(threadId); notifyConversationListeners(threadId);
notifyConversationListListeners(); notifyConversationListListeners();
@ -299,6 +300,7 @@ public class ThreadDatabase extends Database {
public void deleteConversations(Set<Long> selectedConversations) { public void deleteConversations(Set<Long> selectedConversations) {
DatabaseFactory.getSmsDatabase(context).deleteThreads(selectedConversations); DatabaseFactory.getSmsDatabase(context).deleteThreads(selectedConversations);
DatabaseFactory.getMmsDatabase(context).deleteThreads(selectedConversations); DatabaseFactory.getMmsDatabase(context).deleteThreads(selectedConversations);
DatabaseFactory.getDraftDatabase(context).clearDrafts(selectedConversations);
deleteThreads(selectedConversations); deleteThreads(selectedConversations);
notifyConversationListeners(selectedConversations); notifyConversationListeners(selectedConversations);
notifyConversationListListeners(); notifyConversationListListeners();
@ -307,6 +309,7 @@ public class ThreadDatabase extends Database {
public void deleteAllConversations() { public void deleteAllConversations() {
DatabaseFactory.getSmsDatabase(context).deleteAllThreads(); DatabaseFactory.getSmsDatabase(context).deleteAllThreads();
DatabaseFactory.getMmsDatabase(context).deleteAllThreads(); DatabaseFactory.getMmsDatabase(context).deleteAllThreads();
DatabaseFactory.getDraftDatabase(context).clearAllDrafts();
deleteAllThreads(); deleteAllThreads();
} }