From e0393c9739059dacc89905a24fc34f7443a2ac39 Mon Sep 17 00:00:00 2001 From: M66B Date: Sat, 20 Oct 2018 16:05:43 +0000 Subject: [PATCH] Added browse view model --- .../email/BoundaryCallbackMessages.java | 167 +--------------- .../eu/faircode/email/FragmentMessages.java | 9 +- .../eu/faircode/email/ViewModelBrowse.java | 187 ++++++++++++++++++ 3 files changed, 201 insertions(+), 162 deletions(-) create mode 100644 app/src/main/java/eu/faircode/email/ViewModelBrowse.java diff --git a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java index 8cd34f35..5fa3e2cd 100644 --- a/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java +++ b/app/src/main/java/eu/faircode/email/BoundaryCallbackMessages.java @@ -23,53 +23,20 @@ import android.content.Context; import android.os.Handler; 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.ArrayList; -import java.util.Arrays; -import java.util.List; -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.BodyTerm; -import javax.mail.search.FromStringTerm; -import javax.mail.search.OrTerm; -import javax.mail.search.RecipientStringTerm; -import javax.mail.search.SubjectTerm; - import androidx.lifecycle.GenericLifecycleObserver; import androidx.lifecycle.Lifecycle; import androidx.lifecycle.LifecycleOwner; import androidx.paging.PagedList; public class BoundaryCallbackMessages extends PagedList.BoundaryCallback { - private Context context; - private long fid; - private String search; - private int pageSize; + private ViewModelBrowse model; private Handler handler; private IBoundaryCallbackMessages intf; private ExecutorService executor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory); - private IMAPStore istore = null; - private IMAPFolder ifolder = null; - private Message[] imessages = null; - private List existing = new ArrayList<>(); - private int index; - private boolean searching = false; - private int loaded = 0; - interface IBoundaryCallbackMessages { void onLoading(); @@ -78,53 +45,31 @@ public class BoundaryCallbackMessages extends PagedList.BoundaryCallback existing = new ArrayList<>(); + private int index; + private boolean searching = false; + private int loaded = 0; + + void set(Context context, long folder, String search, int pageSize) { + this.context = context; + this.fid = folder; + this.search = search; + this.pageSize = pageSize; + } + + Context getContext() { + return context; + } + + boolean isSearching() { + return searching; + } + + int getLoaded() { + return loaded; + } + + void load() throws MessagingException, FolderClosedIOException { + try { + searching = true; + + DB db = DB.getInstance(context); + EntityFolder folder = db.folder().getFolder(fid); + if (folder.account == null) // outbox + return; + EntityAccount account = db.account().getAccount(folder.account); + + if (imessages == null) { + Properties props = MessageHelper.getSessionProperties(account.auth_type); + props.setProperty("mail.imap.throwsearchexception", "true"); + Session isession = Session.getInstance(props, null); + + Log.i(Helper.TAG, "Boundary connecting account=" + account.name); + istore = (IMAPStore) isession.getStore("imaps"); + Helper.connect(context, istore, account); + + Log.i(Helper.TAG, "Boundary opening folder=" + folder.name); + ifolder = (IMAPFolder) istore.getFolder(folder.name); + ifolder.open(Folder.READ_WRITE); + + Log.i(Helper.TAG, "Boundary searching=" + search); + if (search == null) + imessages = ifolder.getMessages(); + else + imessages = ifolder.search( + new OrTerm( + new OrTerm( + new FromStringTerm(search), + new RecipientStringTerm(Message.RecipientType.TO, search) + ), + new OrTerm( + new SubjectTerm(search), + new BodyTerm(search) + ) + ) + ); + Log.i(Helper.TAG, "Boundary found messages=" + imessages.length); + + index = imessages.length - 1; + } + + int count = 0; + while (index >= 0 && count < pageSize) { + Log.i(Helper.TAG, "Boundary index=" + index); + int from = Math.max(0, index - (pageSize - count) + 1); + Message[] isub = Arrays.copyOfRange(imessages, from, index + 1); + index -= (pageSize - count); + + FetchProfile fp = new FetchProfile(); + fp.add(FetchProfile.Item.ENVELOPE); + fp.add(FetchProfile.Item.FLAGS); + fp.add(FetchProfile.Item.CONTENT_INFO); // body structure + fp.add(UIDFolder.FetchProfileItem.UID); + fp.add(IMAPFolder.FetchProfileItem.HEADERS); + fp.add(FetchProfile.Item.SIZE); + fp.add(IMAPFolder.FetchProfileItem.INTERNALDATE); + ifolder.fetch(isub, fp); + + try { + db.beginTransaction(); + + for (int j = isub.length - 1; j >= 0; j--) + try { + long uid = ifolder.getUID(isub[j]); + Log.i(Helper.TAG, "Boundary sync uid=" + uid); + EntityMessage message = db.message().getMessageByUid(fid, uid); + if (message == null) { + ServiceSynchronize.synchronizeMessage(context, folder, ifolder, (IMAPMessage) isub[j], search != null); + count++; + loaded++; + } else if (search != null) { + existing.add(message.id); + db.message().setMessageFound(message.id, true); + } + } 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(); + } + } + + Log.i(Helper.TAG, "Boundary done"); + } finally { + searching = false; + } + } + + void clear() { + Log.i(Helper.TAG, "Boundary close"); + + DB db = DB.getInstance(context); + for (long id : existing) + db.message().setMessageFound(id, false); + db.message().deleteFoundMessages(); + + try { + if (istore != null) + istore.close(); + } catch (Throwable ex) { + Log.e(Helper.TAG, "Boundary " + ex + "\n" + Log.getStackTraceString(ex)); + } finally { + context = null; + istore = null; + ifolder = null; + imessages = null; + existing.clear(); + } + } +}