Improved POP support

pull/147/head
M66B 6 years ago
parent fb3a4bfb63
commit 3edfb7b0bf

@ -481,7 +481,10 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
// Selected / disabled
itemView.setActivated(selectionTracker != null && selectionTracker.isSelected(message.id));
itemView.setAlpha(
message.uid == null && !EntityFolder.OUTBOX.equals(message.folderType) ? Helper.LOW_LIGHT : 1.0f);
message.uid == null &&
!message.accountPop &&
!EntityFolder.OUTBOX.equals(message.folderType)
? Helper.LOW_LIGHT : 1.0f);
// Duplicate
if (viewType == ViewType.THREAD) {
@ -842,9 +845,10 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
bnvActions.getMenu().findItem(R.id.action_delete).setVisible(
(inTrash && message.msgid != null) ||
message.accountPop ||
(!inTrash && hasTrash && message.uid != null) ||
(inOutbox && (!TextUtils.isEmpty(message.error) || !message.identitySynchronize)));
bnvActions.getMenu().findItem(R.id.action_delete).setTitle(inTrash ? R.string.title_delete : R.string.title_trash);
bnvActions.getMenu().findItem(R.id.action_delete).setTitle(inTrash || message.accountPop ? R.string.title_delete : R.string.title_trash);
bnvActions.getMenu().findItem(R.id.action_move).setVisible(
message.uid != null || (inOutbox && (message.ui_snoozed != null || message.error != null)));
@ -2161,7 +2165,7 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
popupMenu.getMenu().findItem(R.id.menu_reply_all).setEnabled(data.message.content);
popupMenu.getMenu().findItem(R.id.menu_answer).setEnabled(data.message.content);
popupMenu.getMenu().findItem(R.id.menu_unseen).setEnabled(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_unseen).setEnabled(data.message.uid != null || data.message.accountPop);
popupMenu.getMenu().findItem(R.id.menu_junk).setEnabled(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_junk).setVisible(

@ -47,7 +47,7 @@ public interface DaoMessage {
" AND NOT folder.type = '" + EntityFolder.DRAFTS + "' THEN 0 ELSE 1 END)";
@Query("SELECT message.*" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.pop as accountPop, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", COUNT(message.id) AS count" +
@ -87,7 +87,7 @@ public interface DaoMessage {
" AND NOT (folder.id <> :folder AND folder.type = '" + EntityFolder.DRAFTS + "') THEN 0 ELSE 1 END)";
@Query("SELECT message.*" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.pop as accountPop, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", COUNT(message.id) AS count" +
@ -119,7 +119,7 @@ public interface DaoMessage {
DataSource.Factory<Integer, TupleMessageEx> pagedFolder(long folder, boolean threading, String sort, boolean snoozed, boolean found, boolean debug);
@Query("SELECT message.*" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.pop as accountPop, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", 1 AS count" +
@ -191,7 +191,7 @@ public interface DaoMessage {
int countMessageByMsgId(long folder, String msgid);
@Query("SELECT message.*" +
", account.name AS accountName, identity.color AS accountColor, account.notify AS accountNotify" +
", account.name AS accountName, identity.color AS accountColor, account.pop as accountPop, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", 1 AS count" +
@ -208,7 +208,7 @@ public interface DaoMessage {
LiveData<TupleMessageEx> liveMessage(long id);
@Query("SELECT message.*" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.notify AS accountNotify" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, account.pop as accountPop, account.notify AS accountNotify" +
", folder.name AS folderName, folder.display AS folderDisplay, folder.type AS folderType" +
", identity.name AS identityName, identity.email AS identityEmail, identity.synchronize AS identitySynchronize" +
", 1 AS count" +

@ -635,11 +635,7 @@ public class FragmentAccount extends FragmentBase {
for (Folder ifolder : istore.getDefaultFolder().list("*")) {
// Check folder attributes
String fullName = ifolder.getFullName();
String[] attrs;
if (ifolder instanceof IMAPFolder)
attrs = ((IMAPFolder) ifolder).getAttributes();
else
attrs = new String[0];
String[] attrs = ((IMAPFolder) ifolder).getAttributes();
Log.i(fullName + " attrs=" + TextUtils.join(" ", attrs));
String type = EntityFolder.getType(attrs, fullName);
@ -862,6 +858,15 @@ public class FragmentAccount extends FragmentBase {
EntityFolder left = (EntityFolder) args.getSerializable("left");
EntityFolder right = (EntityFolder) args.getSerializable("right");
if (pop) {
drafts = new EntityFolder();
drafts.name = "Drafts";
drafts.synchronize = false;
drafts.initialize = false;
drafts.sync_days = 0;
drafts.keep_days = 0;
}
if (TextUtils.isEmpty(host))
throw new IllegalArgumentException(context.getString(R.string.title_no_host));
if (TextUtils.isEmpty(port))
@ -947,8 +952,8 @@ public class FragmentAccount extends FragmentBase {
inbox.unified = true;
inbox.notify = true;
inbox.initialize = !pop;
inbox.sync_days = EntityFolder.DEFAULT_SYNC;
inbox.keep_days = EntityFolder.DEFAULT_KEEP;
inbox.sync_days = (pop ? 0 : EntityFolder.DEFAULT_SYNC);
inbox.keep_days = (pop ? 0 : EntityFolder.DEFAULT_KEEP);
}
}

@ -2171,7 +2171,11 @@ public class FragmentMessages extends FragmentBase {
db.beginTransaction();
EntityMessage message = db.message().getMessage(id);
if (message.uid != null) {
if (message == null)
return null;
EntityAccount account = db.account().getAccount(message.account);
if (message.uid != null || account.pop) {
if (!message.content)
EntityOperation.queue(context, db, message, EntityOperation.BODY);
if (!message.ui_seen)

@ -951,7 +951,8 @@ public class ServiceSynchronize extends LifecycleService {
EntityLog.log(this, account.name + " connected");
// Update folder list
synchronizeFolders(account, istore, state);
if (istore instanceof IMAPStore)
synchronizeFolders(account, istore, state);
// Open synchronizing folders
final ExecutorService pollExecutor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
@ -1473,63 +1474,77 @@ public class ServiceSynchronize extends LifecycleService {
if (message != null)
db.message().setMessageError(message.id, null);
if (message != null && message.uid == null &&
!(EntityOperation.ADD.equals(op.name) ||
EntityOperation.DELETE.equals(op.name) ||
EntityOperation.SEND.equals(op.name) ||
EntityOperation.SYNC.equals(op.name)))
throw new IllegalArgumentException(op.name + " without uid " + op.args);
if (account != null && account.pop) {
if (EntityOperation.SEEN.equals(op.name))
doSeen(folder, (POP3Folder) ifolder, message, jargs, db);
// Operations should use database transaction when needed
else if (EntityOperation.ADD.equals(op.name))
; // Do nothing
if (EntityOperation.SEEN.equals(op.name))
doSeen(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.DELETE.equals(op.name))
doDelete(folder, (POP3Folder) ifolder, message, jargs, db);
else if (EntityOperation.FLAG.equals(op.name))
doFlag(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.SYNC.equals(op.name))
synchronizeMessages(account, folder, (POP3Folder) ifolder, jargs, state);
else if (EntityOperation.ANSWERED.equals(op.name))
doAnswered(folder, (IMAPFolder) ifolder, message, jargs, db);
else
throw new MessagingException("Unknown operation name=" + op.name);
} else {
if (message != null && message.uid == null &&
!(EntityOperation.ADD.equals(op.name) ||
EntityOperation.DELETE.equals(op.name) ||
EntityOperation.SEND.equals(op.name) ||
EntityOperation.SYNC.equals(op.name)))
throw new IllegalArgumentException(op.name + " without uid " + op.args);
// Operations should use database transaction when needed
else if (EntityOperation.KEYWORD.equals(op.name))
doKeyword(folder, (IMAPFolder) ifolder, message, jargs, db);
if (EntityOperation.SEEN.equals(op.name))
doSeen(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.ADD.equals(op.name))
doAdd(folder, isession, (IMAPStore) istore, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.FLAG.equals(op.name))
doFlag(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.MOVE.equals(op.name))
doMove(folder, isession, (IMAPStore) istore, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.ANSWERED.equals(op.name))
doAnswered(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.DELETE.equals(op.name))
doDelete(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.KEYWORD.equals(op.name))
doKeyword(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.SEND.equals(op.name))
doSend(message, db);
else if (EntityOperation.ADD.equals(op.name))
doAdd(folder, isession, (IMAPStore) istore, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.HEADERS.equals(op.name))
doHeaders(folder, (IMAPFolder) ifolder, message, db);
else if (EntityOperation.MOVE.equals(op.name))
doMove(folder, isession, (IMAPStore) istore, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.RAW.equals(op.name))
doRaw(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.DELETE.equals(op.name))
doDelete(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.BODY.equals(op.name))
doBody(folder, (IMAPFolder) ifolder, message, db);
else if (EntityOperation.SEND.equals(op.name))
doSend(message, db);
else if (EntityOperation.ATTACHMENT.equals(op.name))
doAttachment(folder, op, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.HEADERS.equals(op.name))
doHeaders(folder, (IMAPFolder) ifolder, message, db);
else if (EntityOperation.SYNC.equals(op.name))
if (EntityFolder.OUTBOX.equals(folder.type))
db.folder().setFolderError(folder.id, null);
else {
if (ifolder instanceof IMAPFolder)
else if (EntityOperation.RAW.equals(op.name))
doRaw(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.BODY.equals(op.name))
doBody(folder, (IMAPFolder) ifolder, message, db);
else if (EntityOperation.ATTACHMENT.equals(op.name))
doAttachment(folder, op, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.SYNC.equals(op.name))
if (EntityFolder.OUTBOX.equals(folder.type))
db.folder().setFolderError(folder.id, null);
else
synchronizeMessages(account, folder, (IMAPFolder) ifolder, jargs, state);
else if (ifolder instanceof POP3Folder)
synchronizeMessages(account, folder, (POP3Folder) ifolder, jargs, state);
}
else
throw new MessagingException("Unknown operation name=" + op.name);
else
throw new MessagingException("Unknown operation name=" + op.name);
}
// Operation succeeded
db.operation().deleteOperation(op.id);
@ -1598,6 +1613,15 @@ public class ServiceSynchronize extends LifecycleService {
}
}
private void doSeen(EntityFolder folder, POP3Folder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException, JSONException {
boolean seen = jargs.getBoolean(0);
if (message.seen.equals(seen))
return;
Log.i("Setting POP message=" + message.id + " seen=" + seen);
db.message().setMessageSeen(message.id, seen);
}
private void doSeen(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException, JSONException {
// Mark message (un)seen
if (!ifolder.getPermanentFlags().contains(Flags.Flag.SEEN)) {
@ -1880,6 +1904,24 @@ public class ServiceSynchronize extends LifecycleService {
}
}
private void doDelete(EntityFolder folder, POP3Folder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException {
Log.i("Deleting POP message=" + message.id + " msgid=" + message.msgid);
// Delete message
if (TextUtils.isEmpty(message.msgid))
throw new IllegalArgumentException("Message ID missing");
Message[] imessages = ifolder.search(new MessageIDTerm(message.msgid));
for (Message imessage : imessages) {
Log.i(folder.name + " deleting uid=" + message.uid + " msgid=" + message.msgid);
imessage.setFlag(Flags.Flag.DELETED, true);
}
ifolder.close();
ifolder.open(Folder.READ_WRITE);
db.message().deleteMessage(message.id);
}
private void doDelete(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException {
// Delete message
if (TextUtils.isEmpty(message.msgid))
@ -2234,11 +2276,7 @@ public class ServiceSynchronize extends LifecycleService {
for (Folder ifolder : ifolders) {
String fullName = ifolder.getFullName();
String[] attrs;
if (ifolder instanceof IMAPFolder)
attrs = ((IMAPFolder) ifolder).getAttributes();
else
attrs = new String[0];
String[] attrs = ((IMAPFolder) ifolder).getAttributes();
String type = EntityFolder.getType(attrs, fullName);
EntityLog.log(this, account.name + ":" + fullName +

@ -24,6 +24,7 @@ import androidx.room.Ignore;
public class TupleMessageEx extends EntityMessage {
public String accountName;
public Integer accountColor;
public boolean accountPop;
public boolean accountNotify;
public String folderName;
public String folderDisplay;
@ -47,6 +48,7 @@ public class TupleMessageEx extends EntityMessage {
return (super.uiEquals(obj) &&
(this.accountName == null ? other.accountName == null : this.accountName.equals(other.accountName)) &&
(this.accountColor == null ? other.accountColor == null : this.accountColor.equals(other.accountColor)) &&
this.accountPop == other.accountPop &&
//this.accountNotify == other.accountNotify &&
this.folderName.equals(other.folderName) &&
(this.folderDisplay == null ? other.folderDisplay == null : this.folderDisplay.equals(other.folderDisplay)) &&
@ -72,6 +74,7 @@ public class TupleMessageEx extends EntityMessage {
return (super.equals(obj) &&
(this.accountName == null ? other.accountName == null : this.accountName.equals(other.accountName)) &&
(this.accountColor == null ? other.accountColor == null : this.accountColor.equals(other.accountColor)) &&
this.accountPop == other.accountPop &&
this.accountNotify == other.accountNotify &&
this.folderName.equals(other.folderName) &&
(this.folderDisplay == null ? other.folderDisplay == null : this.folderDisplay.equals(other.folderDisplay)) &&

Loading…
Cancel
Save