From 4289576da0f272cde0a36ba1db046fd4cefc82bb Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 21 Sep 2018 11:53:54 +0000 Subject: [PATCH] Browse messages on server, improvements Fixes #115 --- .../email/BoundaryCallbackMessages.java | 133 +++++--- .../java/eu/faircode/email/DaoMessage.java | 3 - .../eu/faircode/email/FragmentFolder.java | 4 +- .../eu/faircode/email/FragmentMessages.java | 162 ++++------ .../main/java/eu/faircode/email/Helper.java | 20 +- .../main/java/eu/faircode/email/JobDaily.java | 5 - .../eu/faircode/email/ServiceSynchronize.java | 291 +++++++++--------- app/src/main/res/values/strings.xml | 2 +- 8 files changed, 314 insertions(+), 306 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java index 0cb9c5e2..ce367281 100644 --- a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java +++ b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java @@ -26,23 +26,23 @@ import android.util.Log; import com.sun.mail.imap.IMAPFolder; import com.sun.mail.imap.IMAPMessage; import com.sun.mail.imap.IMAPStore; +import com.sun.mail.util.FolderClosedIOException; -import java.util.Date; +import java.util.Arrays; import java.util.Properties; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import javax.mail.FetchProfile; import javax.mail.Folder; +import javax.mail.FolderClosedException; import javax.mail.Message; +import javax.mail.MessageRemovedException; import javax.mail.Session; import javax.mail.UIDFolder; -import javax.mail.search.AndTerm; import javax.mail.search.BodyTerm; -import javax.mail.search.ComparisonTerm; import javax.mail.search.FromStringTerm; import javax.mail.search.OrTerm; -import javax.mail.search.ReceivedDateTerm; import javax.mail.search.SubjectTerm; import androidx.lifecycle.GenericLifecycleObserver; @@ -54,16 +54,16 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback= 0; j--) + try { + long uid = ifolder.getUID(isub[j]); + Log.i(Helper.TAG, "Boundary sync uid=" + uid); + if (db.message().getMessageByUid(fid, uid) == null) { + ServiceSynchronize.synchronizeMessage(context, folder, ifolder, (IMAPMessage) isub[j], true); + count++; + } + } catch (MessageRemovedException ex) { + Log.w(Helper.TAG, "Boundary " + ex + "\n" + Log.getStackTraceString(ex)); + } catch (FolderClosedException ex) { + throw ex; + } catch (FolderClosedIOException ex) { + throw ex; + } catch (Throwable ex) { + Log.e(Helper.TAG, "Boundary " + ex + "\n" + Log.getStackTraceString(ex)); + } finally { + ((IMAPMessage) isub[j]).invalidateHeaders(); + } + + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } } - EntityOperation.process(context); // download small attachments + mainHandler.post(new Runnable() { + @Override + public void run() { + intf.onLoaded(); + } + }); Log.i(Helper.TAG, "Boundary done"); } catch (final Throwable ex) { @@ -194,12 +232,7 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback> messages = null; - private SearchState searchState = SearchState.Reset; private BoundaryCallbackMessages searchCallback = null; private ExecutorService executor = Executors.newCachedThreadPool(Helper.backgroundThreadFactory); @@ -93,8 +92,6 @@ public class FragmentMessages extends FragmentEx { private static final int SEARCH_PAGE_SIZE = 10; private static final int UNDO_TIMEOUT = 5000; // milliseconds - private enum SearchState {Reset, Database, Boundary} - @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -667,44 +664,47 @@ public class FragmentMessages extends FragmentEx { messages = new LivePagedListBuilder<>(db.message().pagedUnifiedInbox(sort, debug), MESSAGES_PAGE_SIZE).build(); break; case FOLDER: - messages = new LivePagedListBuilder<>(db.message().pagedFolder(folder, sort, false, debug), MESSAGES_PAGE_SIZE).build(); + if (searchCallback == null) + searchCallback = new BoundaryCallbackMessages( + getContext(), FragmentMessages.this, + folder, null, MESSAGES_PAGE_SIZE, + new BoundaryCallbackMessages.IBoundaryCallbackMessages() { + @Override + public void onLoading() { + pbWait.setVisibility(View.VISIBLE); + } + + @Override + public void onLoaded() { + pbWait.setVisibility(View.GONE); + } + + @Override + public void onError(Context context, Throwable ex) { + pbWait.setVisibility(View.GONE); + Helper.unexpectedError(context, ex); + } + }); + + PagedList.Config config = new PagedList.Config.Builder() + .setPageSize(MESSAGES_PAGE_SIZE) + .setPrefetchDistance(MESSAGES_PAGE_SIZE) + .build(); + LivePagedListBuilder builder = new LivePagedListBuilder<>( + db.message().pagedFolder(folder, sort, false, debug), config); + builder.setBoundaryCallback(searchCallback); + messages = builder.build(); + break; case THREAD: messages = new LivePagedListBuilder<>(db.message().pagedThread(thread, sort, debug), MESSAGES_PAGE_SIZE).build(); break; } - - messages.observe(getViewLifecycleOwner(), new Observer>() { - @Override - public void onChanged(@Nullable PagedList messages) { - if (messages == null || - (viewType == AdapterMessage.ViewType.THREAD && messages.size() == 0)) { - finish(); - return; - } - - Log.i(Helper.TAG, "Submit messages=" + messages.size()); - adapter.submitList(messages); - - pbWait.setVisibility(View.GONE); - grpReady.setVisibility(View.VISIBLE); - - if (messages.size() == 0) { - tvNoEmail.setVisibility(View.VISIBLE); - rvMessage.setVisibility(View.GONE); - } else { - tvNoEmail.setVisibility(View.GONE); - rvMessage.setVisibility(View.VISIBLE); - } - } - }); } else { - Log.i(Helper.TAG, "Search state=" + searchState); - if (searchCallback == null) searchCallback = new BoundaryCallbackMessages( getContext(), FragmentMessages.this, - folder, search, + folder, search, SEARCH_PAGE_SIZE, new BoundaryCallbackMessages.IBoundaryCallbackMessages() { @Override public void onLoading() { @@ -718,79 +718,49 @@ public class FragmentMessages extends FragmentEx { @Override public void onError(Context context, Throwable ex) { + pbWait.setVisibility(View.GONE); Helper.unexpectedError(context, ex); } }); - Bundle args = new Bundle(); - args.putLong("folder", folder); - args.putString("search", search); + PagedList.Config config = new PagedList.Config.Builder() + .setPageSize(SEARCH_PAGE_SIZE) + .setPrefetchDistance(SEARCH_PAGE_SIZE) + .build(); + LivePagedListBuilder builder = new LivePagedListBuilder<>( + db.message().pagedFolder(folder, "time", true, false), config); + builder.setBoundaryCallback(searchCallback); + messages = builder.build(); + } - new SimpleTask() { - @Override - protected Void onLoad(Context context, Bundle args) { - if (searchState == SearchState.Reset) { - long folder = args.getLong("folder"); - DB.getInstance(context).message().resetFound(folder); - searchState = SearchState.Database; - Log.i(Helper.TAG, "Search reset done"); - } - return null; + messages.observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(@Nullable PagedList messages) { + if (messages == null || + (viewType == AdapterMessage.ViewType.THREAD && messages.size() == 0)) { + finish(); + return; } - @Override - protected void onLoaded(final Bundle args, Void data) { - LivePagedListBuilder builder = new LivePagedListBuilder<>(db.message().pagedFolder(folder, "time", true, false), SEARCH_PAGE_SIZE); - builder.setBoundaryCallback(searchCallback); - LiveData> messages = builder.build(); - messages.observe(getViewLifecycleOwner(), new Observer>() { - @Override - public void onChanged(PagedList messages) { - Log.i(Helper.TAG, "Submit found messages=" + messages.size()); - adapter.submitList(messages); - grpReady.setVisibility(View.VISIBLE); - } - }); - - new SimpleTask() { - @Override - protected Long onLoad(Context context, Bundle args) throws Throwable { - long last = 0; - if (searchState == SearchState.Database) { - last = new Date().getTime(); - long folder = args.getLong("folder"); - String search = args.getString("search").toLowerCase(); - DB db = DB.getInstance(context); - for (long id : db.message().getMessageIDs(folder)) { - EntityMessage message = db.message().getMessage(id); - if (message != null) { // Message could be removed in the meantime - String from = MessageHelper.getFormattedAddresses(message.from, true); - if (from.toLowerCase().contains(search) || - message.subject.toLowerCase().contains(search) || - message.read(context).toLowerCase().contains(search)) { - Log.i(Helper.TAG, "Search found id=" + id); - db.message().setMessageFound(message.id, true); - last = message.received; - } - } - } - searchState = SearchState.Boundary; - Log.i(Helper.TAG, "Search database done"); - } - return last; - } + Log.i(Helper.TAG, "Submit messages=" + messages.size()); + adapter.submitList(messages); - @Override - protected void onLoaded(Bundle args, Long last) { - pbWait.setVisibility(View.GONE); - searchCallback.setEnabled(true); - if (last > 0) - searchCallback.load(last); - } - }.load(FragmentMessages.this, args); + boolean searching = (searchCallback != null && searchCallback.isSearching()); + + if (!searching) + pbWait.setVisibility(View.GONE); + grpReady.setVisibility(View.VISIBLE); + + if (messages.size() == 0 && !searching) { + tvNoEmail.setVisibility(View.VISIBLE); + rvMessage.setVisibility(View.GONE); + } else { + tvNoEmail.setVisibility(View.GONE); + rvMessage.setVisibility(View.VISIBLE); } - }.load(this, args); - } + } + }); + } void onNewMessages() { diff --git a/app/src/main/java/eu/faircode/email/Helper.java b/app/src/main/java/eu/faircode/email/Helper.java index 11e17b25..ea9b1d6f 100644 --- a/app/src/main/java/eu/faircode/email/Helper.java +++ b/app/src/main/java/eu/faircode/email/Helper.java @@ -39,6 +39,7 @@ import android.widget.Spinner; import com.android.billingclient.api.BillingClient; import com.google.android.material.bottomnavigation.BottomNavigationView; +import com.sun.mail.imap.IMAPStore; import java.io.File; import java.io.FileInputStream; @@ -53,7 +54,9 @@ import java.text.DecimalFormat; import java.util.concurrent.ThreadFactory; import javax.mail.Address; +import javax.mail.AuthenticationFailedException; import javax.mail.FolderClosedException; +import javax.mail.MessagingException; import javax.mail.internet.InternetAddress; import androidx.appcompat.app.AlertDialog; @@ -214,7 +217,20 @@ public class Helper { return filename.substring(index + 1); } - static String refreshToken(Context context, String type, String name, String current) { + static void connect(Context context, IMAPStore istore, EntityAccount account) throws MessagingException { + try { + istore.connect(account.host, account.port, account.user, account.password); + } catch (AuthenticationFailedException ex) { + if (account.auth_type == Helper.AUTH_TYPE_GMAIL) { + account.password = Helper.refreshToken(context, "com.google", account.user, account.password); + DB.getInstance(context).account().setAccountPassword(account.id, account.password); + istore.connect(account.host, account.port, account.user, account.password); + } else + throw ex; + } + } + + private static String refreshToken(Context context, String type, String name, String current) { try { AccountManager am = AccountManager.get(context); Account[] accounts = am.getAccountsByType(type); @@ -313,7 +329,7 @@ public class Helper { } static boolean isPro(Context context) { - if (false && BuildConfig.DEBUG) + if (true && BuildConfig.DEBUG) return true; return PreferenceManager.getDefaultSharedPreferences(context).getBoolean("pro", false); } diff --git a/app/src/main/java/eu/faircode/email/JobDaily.java b/app/src/main/java/eu/faircode/email/JobDaily.java index 5b2d3514..0d5c774a 100644 --- a/app/src/main/java/eu/faircode/email/JobDaily.java +++ b/app/src/main/java/eu/faircode/email/JobDaily.java @@ -94,11 +94,6 @@ public class JobDaily extends JobService { int logs = db.log().deleteLogs(before); Log.i(Helper.TAG, "Deleted logs=" + logs); - // Cleanup found messages - Log.i(Helper.TAG, "Cleanup found messages"); - int found = db.message().deleteFoundMessages(); - Log.i(Helper.TAG, "Deleted found messages=" + found); - Log.i(Helper.TAG, "End daily job"); } }); diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 70ab87b7..328c434d 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -560,12 +560,6 @@ public class ServiceSynchronize extends LifecycleService { boolean debug = PreferenceManager.getDefaultSharedPreferences(this).getBoolean("debug", false); System.setProperty("mail.socket.debug", Boolean.toString(debug)); - // Refresh token - if (account.auth_type == Helper.AUTH_TYPE_GMAIL) { - account.password = Helper.refreshToken(this, "com.google", account.user, account.password); - db.account().setAccountPassword(account.id, account.password); - } - // Create session Properties props = MessageHelper.getSessionProperties(this, account.auth_type); final Session isession = Session.getInstance(props, null); @@ -647,8 +641,7 @@ public class ServiceSynchronize extends LifecycleService { for (EntityFolder folder : db.folder().getFolders(account.id)) db.folder().setFolderState(folder.id, null); db.account().setAccountState(account.id, "connecting"); - istore.connect(account.host, account.port, account.user, account.password); - + Helper.connect(this, istore, account); db.account().setAccountState(account.id, "connected"); db.account().setAccountError(account.id, null); @@ -704,7 +697,14 @@ public class ServiceSynchronize extends LifecycleService { for (Message imessage : e.getMessages()) try { - long id = synchronizeMessage(ServiceSynchronize.this, folder, ifolder, (IMAPMessage) imessage, false); + long id; + try { + db.beginTransaction(); + id = synchronizeMessage(ServiceSynchronize.this, folder, ifolder, (IMAPMessage) imessage, false); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } downloadMessage(ServiceSynchronize.this, folder, ifolder, (IMAPMessage) imessage, id); } catch (MessageRemovedException ex) { Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); @@ -777,7 +777,14 @@ public class ServiceSynchronize extends LifecycleService { fp.add(IMAPFolder.FetchProfileItem.FLAGS); ifolder.fetch(new Message[]{e.getMessage()}, fp); - long id = synchronizeMessage(ServiceSynchronize.this, folder, ifolder, (IMAPMessage) e.getMessage(), false); + long id; + try { + db.beginTransaction(); + id = synchronizeMessage(ServiceSynchronize.this, folder, ifolder, (IMAPMessage) e.getMessage(), false); + db.setTransactionSuccessful(); + } finally { + db.endTransaction(); + } downloadMessage(ServiceSynchronize.this, folder, ifolder, (IMAPMessage) e.getMessage(), id); } catch (MessageRemovedException ex) { Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); @@ -1235,12 +1242,6 @@ public class ServiceSynchronize extends LifecycleService { return; } - // Refresh token - if (ident.auth_type == Helper.AUTH_TYPE_GMAIL) { - ident.password = Helper.refreshToken(this, "com.google", ident.user, ident.password); - db.identity().setIdentityPassword(ident.id, ident.password); - } - // Create session Properties props = MessageHelper.getSessionProperties(this, ident.auth_type); final Session isession = Session.getInstance(props, null); @@ -1518,11 +1519,13 @@ public class ServiceSynchronize extends LifecycleService { long headers = SystemClock.elapsedRealtime(); ifolder.fetch(full.toArray(new Message[0]), fp); Log.i(Helper.TAG, folder.name + " fetched headers=" + full.size() + - " " + (SystemClock.elapsedRealtime() - fetch) + " ms"); + " " + (SystemClock.elapsedRealtime() - headers) + " ms"); for (int j = isub.length - 1; j >= 0; j--) try { + db.beginTransaction(); ids[from + j] = synchronizeMessage(this, folder, ifolder, (IMAPMessage) isub[j], false); + db.setTransactionSuccessful(); } catch (MessageRemovedException ex) { Log.w(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); } catch (FolderClosedException ex) { @@ -1532,6 +1535,7 @@ public class ServiceSynchronize extends LifecycleService { } catch (Throwable ex) { Log.e(Helper.TAG, folder.name + " " + ex + "\n" + Log.getStackTraceString(ex)); } finally { + db.endTransaction(); // Reduce memory usage ((IMAPMessage) isub[j]).invalidateHeaders(); } @@ -1590,155 +1594,148 @@ public class ServiceSynchronize extends LifecycleService { boolean flagged = helper.getFlagged(); DB db = DB.getInstance(context); - try { - db.beginTransaction(); - // Find message by uid (fast, no headers required) - EntityMessage message = db.message().getMessageByUid(folder.id, uid); - - // Find message by Message-ID (slow, headers required) - // - messages in inbox have same id as message sent to self - // - messages in archive have same id as original - if (message == null) { - // Will fetch headers within database transaction - String msgid = helper.getMessageID(); - String[] refs = helper.getReferences(); - String reference = (refs.length == 1 && refs[0].indexOf(BuildConfig.APPLICATION_ID) > 0 ? refs[0] : msgid); - Log.i(Helper.TAG, "Searching for " + msgid + " / " + reference); - for (EntityMessage dup : db.message().getMessageByMsgId(folder.account, msgid, reference)) { - EntityFolder dfolder = db.folder().getFolder(dup.folder); - boolean outbox = EntityFolder.OUTBOX.equals(dfolder.type); - Log.i(Helper.TAG, folder.name + " found as id=" + dup.id + - " folder=" + dfolder.type + ":" + dup.folder + "/" + folder.type + ":" + folder.id); - - if (dup.folder.equals(folder.id) || outbox) { - Log.i(Helper.TAG, folder.name + " found as id=" + dup.id + " uid=" + dup.uid + " msgid=" + msgid); - dup.folder = folder.id; - dup.uid = uid; - if (TextUtils.isEmpty(dup.thread)) // outbox: only now the uid is known - dup.thread = helper.getThreadId(uid); - db.message().updateMessage(dup); - message = dup; - } + // Find message by uid (fast, no headers required) + EntityMessage message = db.message().getMessageByUid(folder.id, uid); + + // Find message by Message-ID (slow, headers required) + // - messages in inbox have same id as message sent to self + // - messages in archive have same id as original + if (message == null) { + // Will fetch headers within database transaction + String msgid = helper.getMessageID(); + String[] refs = helper.getReferences(); + String reference = (refs.length == 1 && refs[0].indexOf(BuildConfig.APPLICATION_ID) > 0 ? refs[0] : msgid); + Log.i(Helper.TAG, "Searching for " + msgid + " / " + reference); + for (EntityMessage dup : db.message().getMessageByMsgId(folder.account, msgid, reference)) { + EntityFolder dfolder = db.folder().getFolder(dup.folder); + boolean outbox = EntityFolder.OUTBOX.equals(dfolder.type); + Log.i(Helper.TAG, folder.name + " found as id=" + dup.id + + " folder=" + dfolder.type + ":" + dup.folder + "/" + folder.type + ":" + folder.id); + + if (dup.folder.equals(folder.id) || outbox) { + Log.i(Helper.TAG, folder.name + " found as id=" + dup.id + " uid=" + dup.uid + " msgid=" + msgid); + dup.folder = folder.id; + dup.uid = uid; + if (TextUtils.isEmpty(dup.thread)) // outbox: only now the uid is known + dup.thread = helper.getThreadId(uid); + db.message().updateMessage(dup); + message = dup; } } + } - if (message == null) { - message = new EntityMessage(); - message.account = folder.account; - message.folder = folder.id; - message.uid = uid; - - if (!EntityFolder.ARCHIVE.equals(folder.type)) { - message.msgid = helper.getMessageID(); - if (TextUtils.isEmpty(message.msgid)) - Log.w(Helper.TAG, "No Message-ID id=" + message.id + " uid=" + message.uid); - } + if (message == null) { + message = new EntityMessage(); + message.account = folder.account; + message.folder = folder.id; + message.uid = uid; - message.references = TextUtils.join(" ", helper.getReferences()); - message.inreplyto = helper.getInReplyTo(); - message.deliveredto = helper.getDeliveredTo(); - message.thread = helper.getThreadId(uid); - message.from = helper.getFrom(); - message.to = helper.getTo(); - message.cc = helper.getCc(); - message.bcc = helper.getBcc(); - message.reply = helper.getReply(); - message.subject = imessage.getSubject(); - message.size = helper.getSize(); - message.content = false; - message.received = imessage.getReceivedDate().getTime(); - message.sent = (imessage.getSentDate() == null ? null : imessage.getSentDate().getTime()); - message.seen = seen; - message.ui_seen = seen; - message.flagged = false; - message.ui_flagged = false; - message.ui_hide = false; - message.ui_found = found; + if (!EntityFolder.ARCHIVE.equals(folder.type)) { + message.msgid = helper.getMessageID(); + if (TextUtils.isEmpty(message.msgid)) + Log.w(Helper.TAG, "No Message-ID id=" + message.id + " uid=" + message.uid); + } - if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) - == PackageManager.PERMISSION_GRANTED) { - try { - if (message.from != null) - for (int i = 0; i < message.from.length; i++) { - String email = ((InternetAddress) message.from[i]).getAddress(); - Cursor cursor = null; - try { - ContentResolver resolver = context.getContentResolver(); - cursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, - new String[]{ - ContactsContract.CommonDataKinds.Photo.CONTACT_ID, - ContactsContract.Contacts.DISPLAY_NAME - }, - ContactsContract.CommonDataKinds.Email.ADDRESS + " = ?", - new String[]{email}, null); - if (cursor.moveToNext()) { - int colContactId = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.CONTACT_ID); - int colDisplayName = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); - long contactId = cursor.getLong(colContactId); - String displayName = cursor.getString(colDisplayName); - - Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId); - message.avatar = uri.toString(); - - if (!TextUtils.isEmpty(displayName)) - ((InternetAddress) message.from[i]).setPersonal(displayName); - } - } finally { - if (cursor != null) - cursor.close(); + message.references = TextUtils.join(" ", helper.getReferences()); + message.inreplyto = helper.getInReplyTo(); + message.deliveredto = helper.getDeliveredTo(); + message.thread = helper.getThreadId(uid); + message.from = helper.getFrom(); + message.to = helper.getTo(); + message.cc = helper.getCc(); + message.bcc = helper.getBcc(); + message.reply = helper.getReply(); + message.subject = imessage.getSubject(); + message.size = helper.getSize(); + message.content = false; + message.received = imessage.getReceivedDate().getTime(); + message.sent = (imessage.getSentDate() == null ? null : imessage.getSentDate().getTime()); + message.seen = seen; + message.ui_seen = seen; + message.flagged = false; + message.ui_flagged = false; + message.ui_hide = false; + message.ui_found = found; + + if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) + == PackageManager.PERMISSION_GRANTED) { + try { + if (message.from != null) + for (int i = 0; i < message.from.length; i++) { + String email = ((InternetAddress) message.from[i]).getAddress(); + Cursor cursor = null; + try { + ContentResolver resolver = context.getContentResolver(); + cursor = resolver.query(ContactsContract.CommonDataKinds.Email.CONTENT_URI, + new String[]{ + ContactsContract.CommonDataKinds.Photo.CONTACT_ID, + ContactsContract.Contacts.DISPLAY_NAME + }, + ContactsContract.CommonDataKinds.Email.ADDRESS + " = ?", + new String[]{email}, null); + if (cursor.moveToNext()) { + int colContactId = cursor.getColumnIndex(ContactsContract.CommonDataKinds.Photo.CONTACT_ID); + int colDisplayName = cursor.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME); + long contactId = cursor.getLong(colContactId); + String displayName = cursor.getString(colDisplayName); + + Uri uri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, contactId); + message.avatar = uri.toString(); + + if (!TextUtils.isEmpty(displayName)) + ((InternetAddress) message.from[i]).setPersonal(displayName); } + } finally { + if (cursor != null) + cursor.close(); } - } catch (Throwable ex) { - Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); - } + } + } catch (Throwable ex) { + Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); } + } - message.id = db.message().insertMessage(message); + message.id = db.message().insertMessage(message); - Log.i(Helper.TAG, folder.name + " added id=" + message.id + " uid=" + message.uid); + Log.i(Helper.TAG, folder.name + " added id=" + message.id + " uid=" + message.uid); - int sequence = 1; - for (EntityAttachment attachment : helper.getAttachments()) { - Log.i(Helper.TAG, folder.name + " attachment" + - " seq=" + sequence + " name=" + attachment.name + " type=" + attachment.type); - attachment.message = message.id; - attachment.sequence = sequence++; - attachment.id = db.attachment().insertAttachment(attachment); + int sequence = 1; + for (EntityAttachment attachment : helper.getAttachments()) { + Log.i(Helper.TAG, folder.name + " attachment" + + " seq=" + sequence + " name=" + attachment.name + " type=" + attachment.type); + attachment.message = message.id; + attachment.sequence = sequence++; + attachment.id = db.attachment().insertAttachment(attachment); - if (message.size != null && attachment.size != null) - message.size -= attachment.size; - } + if (message.size != null && attachment.size != null) + message.size -= attachment.size; + } + db.message().updateMessage(message); + } else { + if (message.seen != seen || message.seen != message.ui_seen) { + message.seen = seen; + message.ui_seen = seen; db.message().updateMessage(message); - } else { - if (message.seen != seen || message.seen != message.ui_seen) { - message.seen = seen; - message.ui_seen = seen; - db.message().updateMessage(message); - Log.i(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid + " seen=" + seen); - } - - if (message.flagged != flagged || message.flagged != message.ui_flagged) { - message.flagged = flagged; - message.ui_flagged = flagged; - db.message().updateMessage(message); - Log.i(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid + " flagged=" + flagged); - } - - if (message.ui_hide) { - message.ui_hide = false; - db.message().updateMessage(message); - Log.i(Helper.TAG, folder.name + " unhidden id=" + message.id + " uid=" + message.uid); - } + Log.i(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid + " seen=" + seen); } - db.setTransactionSuccessful(); + if (message.flagged != flagged || message.flagged != message.ui_flagged) { + message.flagged = flagged; + message.ui_flagged = flagged; + db.message().updateMessage(message); + Log.i(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid + " flagged=" + flagged); + } - return message.id; - } finally { - db.endTransaction(); + if (message.ui_hide) { + message.ui_hide = false; + db.message().updateMessage(message); + Log.i(Helper.TAG, folder.name + " unhidden id=" + message.id + " uid=" + message.uid); + } } + + return message.id; } private static void downloadMessage(Context context, EntityFolder folder, IMAPFolder ifolder, IMAPMessage imessage, long id) throws MessagingException, IOException { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8eb2e6ce..6f25252d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -215,7 +215,7 @@ Sending message Search - Search sender/subject/text + Search on server Searching \'%1$s\' Sort on