Removed POP3 support

There are too many disadvantages likely resulting in too many support questions
pull/147/head
M66B 7 years ago
parent 144bd41170
commit 67b203ad3a

@ -238,17 +238,15 @@ public class AdapterFolder extends RecyclerView.Adapter<AdapterFolder.ViewHolder
popupMenu.getMenu().add(Menu.NONE, action_synchronize_now, 1, R.string.title_synchronize_now);
if (folder.account != null && !folder.accountPop)
if (folder.account != null)
popupMenu.getMenu().add(Menu.NONE, action_delete_local, 2, R.string.title_delete_local);
if (EntityFolder.TRASH.equals(folder.type) && !folder.accountPop)
if (EntityFolder.TRASH.equals(folder.type))
popupMenu.getMenu().add(Menu.NONE, action_empty_trash, 3, R.string.title_empty_trash);
if (folder.account != null) {
if (!folder.accountPop || EntityFolder.INBOX.equals(folder.type))
popupMenu.getMenu().add(Menu.NONE, action_edit_properties, 4, R.string.title_edit_properties);
if (!folder.accountPop)
popupMenu.getMenu().add(Menu.NONE, action_edit_rules, 5, R.string.title_edit_rules);
popupMenu.getMenu().add(Menu.NONE, action_edit_properties, 4, R.string.title_edit_properties);
popupMenu.getMenu().add(Menu.NONE, action_edit_rules, 5, R.string.title_edit_rules);
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {

@ -482,7 +482,6 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
itemView.setActivated(selectionTracker != null && selectionTracker.isSelected(message.id));
itemView.setAlpha(
message.uid == null &&
!message.accountPop &&
!EntityFolder.OUTBOX.equals(message.folderType)
? Helper.LOW_LIGHT : 1.0f);
@ -845,10 +844,9 @@ 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 || message.accountPop ? R.string.title_delete : R.string.title_trash);
bnvActions.getMenu().findItem(R.id.action_delete).setTitle(inTrash ? 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)));
@ -2165,7 +2163,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 || data.message.accountPop);
popupMenu.getMenu().findItem(R.id.menu_unseen).setEnabled(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_junk).setEnabled(data.message.uid != null);
popupMenu.getMenu().findItem(R.id.menu_junk).setVisible(

@ -55,7 +55,7 @@ public interface DaoFolder {
" AND (:search OR (account.synchronize AND account.browse))")
EntityFolder getBrowsableFolder(long folder, boolean search);
@Query("SELECT folder.*, account.name AS accountName, account.color AS accountColor, account.pop as accountPop, account.state AS accountState" +
@Query("SELECT folder.*, account.name AS accountName, account.color AS accountColor, account.state AS accountState" +
", COUNT(message.id) AS messages" +
", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" +
", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" +
@ -69,7 +69,7 @@ public interface DaoFolder {
" GROUP BY folder.id")
LiveData<List<TupleFolderEx>> liveFolders(Long account);
@Query("SELECT folder.*, account.name AS accountName, account.color AS accountColor, account.pop as accountPop, account.state AS accountState" +
@Query("SELECT folder.*, account.name AS accountName, account.color AS accountColor, account.state AS accountState" +
", COUNT(message.id) AS messages" +
", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" +
", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" +
@ -91,7 +91,7 @@ public interface DaoFolder {
" WHERE `primary` AND type = '" + EntityFolder.ARCHIVE + "'")
LiveData<EntityFolder> livePrimaryArchive();
@Query("SELECT folder.*, account.name AS accountName, account.color AS accountColor, account.pop as accountPop, account.state AS accountState" +
@Query("SELECT folder.*, account.name AS accountName, account.color AS accountColor, account.state AS accountState" +
", COUNT(message.id) AS messages" +
", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" +
", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" +
@ -112,16 +112,6 @@ public interface DaoFolder {
@Query("SELECT * FROM folder WHERE id = :id")
EntityFolder getFolder(Long id);
@Query("SELECT folder.*, account.name AS accountName, account.color AS accountColor, account.pop as accountPop, account.state AS accountState" +
", COUNT(message.id) AS messages" +
", SUM(CASE WHEN message.content = 1 THEN 1 ELSE 0 END) AS content" +
", SUM(CASE WHEN message.ui_seen = 0 THEN 1 ELSE 0 END) AS unseen" +
" FROM folder" +
" LEFT JOIN account ON account.id = folder.account" +
" LEFT JOIN message ON message.folder = folder.id AND NOT message.ui_hide" +
" WHERE folder.id = :id")
TupleFolderEx getFolderEx(Long id);
@Query("SELECT * FROM folder WHERE account = :account AND name = :name")
EntityFolder getFolderByName(Long account, String name);

@ -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.pop as accountPop, account.notify AS accountNotify" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, 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.pop as accountPop, account.notify AS accountNotify" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, 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.pop as accountPop, account.notify AS accountNotify" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, 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" +
@ -170,15 +170,14 @@ public interface DaoMessage {
" ORDER BY message.received DESC")
List<Long> getMessageIdsByFolder(Long folder);
@Query("SELECT message.*" +
@Query("SELECT *" +
" FROM message" +
" LEFT JOIN account ON account.id = :account" +
" WHERE account = :account" +
" AND message.thread = :thread" +
" AND thread = :thread" +
" AND (:id IS NULL OR message.id = :id)" +
" AND (:folder IS NULL OR message.folder = :folder)" +
" AND (NOT message.uid IS NULL OR account.pop)" +
" AND NOT message.ui_hide")
" AND NOT uid IS NULL" +
" AND NOT ui_hide")
List<EntityMessage> getMessageByThread(long account, String thread, Long id, Long folder);
@Query("SELECT * FROM message" +
@ -192,7 +191,7 @@ public interface DaoMessage {
int countMessageByMsgId(long folder, String msgid);
@Query("SELECT message.*" +
", account.name AS accountName, identity.color AS accountColor, account.pop as accountPop, account.notify AS accountNotify" +
", account.name AS accountName, identity.color AS accountColor, 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" +
@ -209,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.pop as accountPop, account.notify AS accountNotify" +
", account.name AS accountName, IFNULL(identity.color, account.color) AS accountColor, 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" +

@ -49,7 +49,7 @@ public class EntityAccount implements Serializable {
@NonNull
public Integer auth_type;
@NonNull
public Boolean pop = false;
public Boolean pop = false; // obsolete
@NonNull
public String host; // POP3/IMAP
@NonNull
@ -89,7 +89,7 @@ public class EntityAccount implements Serializable {
public Long last_connected;
String getProtocol() {
return (pop ? "pop3" : "imap") + (starttls ? "" : "s");
return "imap" + (starttls ? "" : "s");
}
static String getNotificationChannelName(long account) {
@ -116,7 +116,6 @@ public class EntityAccount implements Serializable {
JSONObject json = new JSONObject();
json.put("id", id);
json.put("auth_type", auth_type);
json.put("pop", pop);
json.put("host", host);
json.put("starttls", starttls);
json.put("insecure", insecure);
@ -149,8 +148,6 @@ public class EntityAccount implements Serializable {
EntityAccount account = new EntityAccount();
// id
account.auth_type = json.getInt("auth_type");
if (json.has("pop"))
account.pop = json.getBoolean("pop");
account.host = json.getString("host");
account.starttls = (json.has("starttls") && json.getBoolean("starttls"));
account.insecure = (json.has("insecure") && json.getBoolean("insecure"));

@ -78,7 +78,6 @@ import javax.mail.Store;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.widget.SwitchCompat;
import androidx.constraintlayout.widget.Group;
import androidx.fragment.app.FragmentTransaction;
@ -93,8 +92,6 @@ public class FragmentAccount extends FragmentBase {
private Button btnAutoConfig;
private Button btnAuthorize;
private SwitchCompat swPop;
private TextView tvPopHint;
private EditText etHost;
private CheckBox cbStartTls;
private CheckBox cbInsecure;
@ -171,8 +168,6 @@ public class FragmentAccount extends FragmentBase {
btnAutoConfig = view.findViewById(R.id.btnAutoConfig);
btnAuthorize = view.findViewById(R.id.btnAuthorize);
swPop = view.findViewById(R.id.swPop);
tvPopHint = view.findViewById(R.id.tvPopHint);
etHost = view.findViewById(R.id.etHost);
etPort = view.findViewById(R.id.etPort);
cbStartTls = view.findViewById(R.id.cbStartTls);
@ -247,7 +242,6 @@ public class FragmentAccount extends FragmentBase {
auth_type = Helper.AUTH_TYPE_PASSWORD;
swPop.setChecked(false);
etHost.setText(provider.imap_host);
etPort.setText(provider.imap_host == null ? null : Integer.toString(provider.imap_port));
cbStartTls.setChecked(provider.imap_starttls);
@ -293,39 +287,10 @@ public class FragmentAccount extends FragmentBase {
}
});
swPop.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
boolean starttls = cbStartTls.isChecked();
if (isChecked) {
tvPopHint.setVisibility(View.VISIBLE);
etHost.setHint("pop.domain.tld");
etPort.setHint(starttls ? "110" : "995");
etRealm.setText(null);
cbBrowse.setChecked(false);
etPrefix.setText(null);
btnCheck.setVisibility(View.GONE);
btnSave.setVisibility(View.VISIBLE);
} else {
tvPopHint.setVisibility(View.GONE);
etHost.setHint("imap.domain.tld");
etPort.setHint(starttls ? "143" : "993");
btnCheck.setVisibility(View.VISIBLE);
btnSave.setVisibility(View.GONE);
}
etRealm.setEnabled(!isChecked);
cbBrowse.setEnabled(!isChecked);
etPrefix.setEnabled(!isChecked);
}
});
cbStartTls.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
if (swPop.isChecked())
etPort.setHint(checked ? "110" : "995");
else
etPort.setHint(checked ? "143" : "993");
etPort.setHint(checked ? "143" : "993");
}
});
@ -465,8 +430,6 @@ public class FragmentAccount extends FragmentBase {
btnAutoConfig.setEnabled(false);
tvPopHint.setVisibility(View.GONE);
btnAuthorize.setVisibility(View.GONE);
cbStartTls.setVisibility(View.GONE);
cbInsecure.setVisibility(View.GONE);
@ -518,7 +481,6 @@ public class FragmentAccount extends FragmentBase {
@Override
protected void onExecuted(Bundle args, EmailProvider provider) {
swPop.setChecked(false);
etHost.setText(provider.imap_host);
etPort.setText(Integer.toString(provider.imap_port));
cbStartTls.setChecked(provider.imap_starttls);
@ -538,7 +500,6 @@ public class FragmentAccount extends FragmentBase {
Bundle args = new Bundle();
args.putLong("id", id);
args.putInt("auth_type", auth_type);
args.putBoolean("pop", swPop.isChecked());
args.putString("host", etHost.getText().toString());
args.putBoolean("starttls", cbStartTls.isChecked());
args.putBoolean("insecure", cbInsecure.isChecked());
@ -573,7 +534,6 @@ public class FragmentAccount extends FragmentBase {
protected CheckResult onExecute(Context context, Bundle args) throws Throwable {
long id = args.getLong("id");
int auth_type = args.getInt("auth_type");
boolean pop = args.getBoolean("pop");
String host = args.getString("host");
boolean starttls = args.getBoolean("starttls");
boolean insecure = args.getBoolean("insecure");
@ -585,10 +545,7 @@ public class FragmentAccount extends FragmentBase {
if (TextUtils.isEmpty(host))
throw new IllegalArgumentException(context.getString(R.string.title_no_host));
if (TextUtils.isEmpty(port))
if (pop)
port = (starttls ? "110" : "995");
else
port = (starttls ? "143" : "993");
port = (starttls ? "143" : "993");
if (TextUtils.isEmpty(user))
throw new IllegalArgumentException(context.getString(R.string.title_no_user));
if (TextUtils.isEmpty(password) && !insecure)
@ -609,7 +566,7 @@ public class FragmentAccount extends FragmentBase {
isession.setDebug(true);
Store istore = null;
try {
istore = isession.getStore((pop ? "pop3" : "imap") + (starttls ? "" : "s"));
istore = isession.getStore("imap" + (starttls ? "" : "s"));
try {
istore.connect(host, Integer.parseInt(port), user, password);
} catch (AuthenticationFailedException ex) {
@ -620,11 +577,9 @@ public class FragmentAccount extends FragmentBase {
throw ex;
}
if (istore instanceof IMAPStore) {
result.idle = ((IMAPStore) istore).hasCapability("IDLE");
result.move = ((IMAPStore) istore).hasCapability("MOVE");
result.uidplus = ((IMAPStore) istore).hasCapability("UIDPLUS");
}
result.idle = ((IMAPStore) istore).hasCapability("IDLE");
result.move = ((IMAPStore) istore).hasCapability("MOVE");
result.uidplus = ((IMAPStore) istore).hasCapability("UIDPLUS");
boolean inbox = false;
boolean archive = false;
@ -718,17 +673,11 @@ public class FragmentAccount extends FragmentBase {
@Override
protected void onExecuted(Bundle args, CheckResult result) {
boolean pop = args.getBoolean("pop");
tvIdle.setVisibility(result.idle || pop ? View.GONE : View.VISIBLE);
tvMove.setVisibility(result.move || pop ? View.GONE : View.VISIBLE);
tvUidPlus.setVisibility(result.uidplus || pop ? View.GONE : View.VISIBLE);
tvIdle.setVisibility(result.idle ? View.GONE : View.VISIBLE);
tvMove.setVisibility(result.move ? View.GONE : View.VISIBLE);
tvUidPlus.setVisibility(result.uidplus ? View.GONE : View.VISIBLE);
if (pop) {
grpFolders.setVisibility(View.GONE);
btnSave.setVisibility(View.VISIBLE);
} else
setFolders(result.folders, result.account);
setFolders(result.folders, result.account);
new Handler().post(new Runnable() {
@Override
@ -787,7 +736,6 @@ public class FragmentAccount extends FragmentBase {
args.putLong("id", id);
args.putInt("auth_type", auth_type);
args.putBoolean("pop", swPop.isChecked());
args.putString("host", etHost.getText().toString());
args.putBoolean("starttls", cbStartTls.isChecked());
args.putBoolean("insecure", cbInsecure.isChecked());
@ -837,7 +785,6 @@ public class FragmentAccount extends FragmentBase {
long id = args.getLong("id");
int auth_type = args.getInt("auth_type");
boolean pop = args.getBoolean("pop");
String host = args.getString("host");
boolean starttls = args.getBoolean("starttls");
boolean insecure = args.getBoolean("insecure");
@ -864,29 +811,10 @@ public class FragmentAccount extends FragmentBase {
EntityFolder left = (EntityFolder) args.getSerializable("left");
EntityFolder right = (EntityFolder) args.getSerializable("right");
if (pop) {
drafts = new EntityFolder();
drafts.name = context.getString(R.string.title_folder_drafts);
drafts.synchronize = false;
drafts.initialize = false;
drafts.sync_days = 0;
drafts.keep_days = 0;
sent = new EntityFolder();
sent.name = context.getString(R.string.title_folder_sent);
sent.synchronize = false;
sent.initialize = false;
sent.sync_days = 0;
sent.keep_days = 0;
}
if (TextUtils.isEmpty(host))
throw new IllegalArgumentException(context.getString(R.string.title_no_host));
if (TextUtils.isEmpty(port))
if (pop)
port = (starttls ? "110" : "995");
else
port = (starttls ? "143" : "993");
port = (starttls ? "143" : "993");
if (TextUtils.isEmpty(user))
throw new IllegalArgumentException(context.getString(R.string.title_no_user));
if (synchronize && TextUtils.isEmpty(password) && !insecure)
@ -912,7 +840,6 @@ public class FragmentAccount extends FragmentBase {
boolean check = (synchronize && (account == null ||
auth_type != account.auth_type ||
pop != account.pop ||
!host.equals(account.host) || Integer.parseInt(port) != account.port ||
!user.equals(account.user) || !password.equals(account.password) ||
(realm == null ? accountRealm != null : !realm.equals(accountRealm))));
@ -934,7 +861,7 @@ public class FragmentAccount extends FragmentBase {
Store istore = null;
try {
istore = isession.getStore((pop ? "pop3" : "imap") + (starttls ? "" : "s"));
istore = isession.getStore("imap" + (starttls ? "" : "s"));
try {
istore.connect(host, Integer.parseInt(port), user, password);
} catch (AuthenticationFailedException ex) {
@ -949,11 +876,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);
@ -964,9 +887,9 @@ public class FragmentAccount extends FragmentBase {
inbox.synchronize = true;
inbox.unified = true;
inbox.notify = true;
inbox.initialize = !pop;
inbox.sync_days = (pop ? 0 : EntityFolder.DEFAULT_SYNC);
inbox.keep_days = (pop ? 0 : EntityFolder.DEFAULT_KEEP);
inbox.initialize = true;
inbox.sync_days = EntityFolder.DEFAULT_SYNC;
inbox.keep_days = EntityFolder.DEFAULT_KEEP;
}
}
@ -987,7 +910,6 @@ public class FragmentAccount extends FragmentBase {
account = new EntityAccount();
account.auth_type = auth_type;
account.pop = pop;
account.host = host;
account.starttls = starttls;
account.insecure = insecure;
@ -1205,7 +1127,6 @@ public class FragmentAccount extends FragmentBase {
spProvider.setTag(1);
spProvider.setSelection(1);
}
swPop.setChecked(account.pop);
etHost.setText(account.host);
etPort.setText(Long.toString(account.port));
}
@ -1268,15 +1189,6 @@ public class FragmentAccount extends FragmentBase {
// Consider previous check/save/delete as cancelled
pbWait.setVisibility(View.GONE);
if (account != null && account.pop) {
etRealm.setEnabled(false);
cbBrowse.setEnabled(false);
etPrefix.setEnabled(false);
grpFolders.setVisibility(View.GONE);
btnSave.setVisibility(View.VISIBLE);
return;
}
args.putLong("account", account == null ? -1 : account.id);
new SimpleTask<List<EntityFolder>>() {

@ -41,7 +41,6 @@ import java.util.Calendar;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.Group;
public class FragmentFolder extends FragmentBase {
private ViewGroup view;
@ -59,7 +58,6 @@ public class FragmentFolder extends FragmentBase {
private Button btnSave;
private ContentLoadingProgressBar pbSave;
private ContentLoadingProgressBar pbWait;
private Group grpPop;
private long id = -1;
private long account = -1;
@ -99,7 +97,6 @@ public class FragmentFolder extends FragmentBase {
btnSave = view.findViewById(R.id.btnSave);
pbSave = view.findViewById(R.id.pbSave);
pbWait = view.findViewById(R.id.pbWait);
grpPop = view.findViewById(R.id.grpPop);
cbUnified.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
@ -139,7 +136,6 @@ public class FragmentFolder extends FragmentBase {
btnSave.setEnabled(false);
pbSave.setVisibility(View.GONE);
pbWait.setVisibility(View.VISIBLE);
grpPop.setVisibility(View.GONE);
return view;
}
@ -365,15 +361,15 @@ public class FragmentFolder extends FragmentBase {
Bundle args = new Bundle();
args.putLong("id", id);
new SimpleTask<TupleFolderEx>() {
new SimpleTask<EntityFolder>() {
@Override
protected TupleFolderEx onExecute(Context context, Bundle args) {
protected EntityFolder onExecute(Context context, Bundle args) {
long id = args.getLong("id");
return DB.getInstance(context).folder().getFolderEx(id);
return DB.getInstance(context).folder().getFolder(id);
}
@Override
protected void onExecuted(Bundle args, TupleFolderEx folder) {
protected void onExecuted(Bundle args, EntityFolder folder) {
if (savedInstanceState == null) {
etName.setText(folder == null ? null : folder.name);
etDisplay.setText(folder == null ? null : folder.display);
@ -393,7 +389,6 @@ public class FragmentFolder extends FragmentBase {
// Consider previous save as cancelled
pbWait.setVisibility(View.GONE);
grpPop.setVisibility(folder == null || !folder.accountPop ? View.VISIBLE : View.GONE);
Helper.setViewsEnabled(view, true);
etName.setEnabled(folder == null);

@ -154,7 +154,7 @@ public class FragmentFolders extends FragmentBase {
@Override
public void onChanged(@Nullable EntityAccount account) {
setSubtitle(account == null ? null : account.name);
if (account == null || account.pop)
if (account == null)
fab.hide();
else
fab.show();

@ -445,7 +445,6 @@ public class FragmentMessages extends FragmentBase {
new ItemTouchHelper(touchHelper).attachToRecyclerView(rvMessage);
selectionPredicate = new SelectionPredicateMessage(rvMessage);
selectionPredicate.setFolder(viewType == AdapterMessage.ViewType.FOLDER);
selectionTracker = new SelectionTracker.Builder<>(
"messages-selection",
@ -930,18 +929,6 @@ public class FragmentMessages extends FragmentBase {
if (message == null)
continue;
EntityAccount account = db.account().getAccount(message.account);
if (account.pop) {
if (message.ui_seen)
result.seen = true;
else
result.unseen = true;
result.isTrash = true;
continue;
}
if (!fids.contains(message.folder))
fids.add(message.folder);
@ -984,9 +971,6 @@ public class FragmentMessages extends FragmentBase {
if (result.hasTrash == null) result.hasTrash = false;
if (result.hasJunk == null) result.hasJunk = false;
if (fids.size() == 0) // POP
return result;
result.accounts = db.account().getAccounts(true);
final Collator collator = Collator.getInstance(Locale.getDefault());
@ -1001,20 +985,19 @@ public class FragmentMessages extends FragmentBase {
}
});
for (EntityAccount account : result.accounts)
if (!account.pop) {
List<EntityFolder> targets = new ArrayList<>();
List<EntityFolder> folders = db.folder().getFolders(account.id);
for (EntityFolder target : folders)
if (!target.hide &&
!EntityFolder.ARCHIVE.equals(target.type) &&
!EntityFolder.TRASH.equals(target.type) &&
!EntityFolder.JUNK.equals(target.type) &&
(fids.size() != 1 || !fids.contains(target.id)))
targets.add(target);
EntityFolder.sort(context, targets);
result.targets.put(account, targets);
}
for (EntityAccount account : result.accounts) {
List<EntityFolder> targets = new ArrayList<>();
List<EntityFolder> folders = db.folder().getFolders(account.id);
for (EntityFolder target : folders)
if (!target.hide &&
!EntityFolder.ARCHIVE.equals(target.type) &&
!EntityFolder.TRASH.equals(target.type) &&
!EntityFolder.JUNK.equals(target.type) &&
(fids.size() != 1 || !fids.contains(target.id)))
targets.add(target);
EntityFolder.sort(context, targets);
result.targets.put(account, targets);
}
return result;
}
@ -1030,9 +1013,9 @@ public class FragmentMessages extends FragmentBase {
popupMenu.getMenu().add(Menu.NONE, action_snooze, 3, R.string.title_snooze);
if (result.unflagged != null && result.unflagged)
if (result.unflagged)
popupMenu.getMenu().add(Menu.NONE, action_flag, 4, R.string.title_flag);
if (result.flagged != null && result.flagged)
if (result.flagged)
popupMenu.getMenu().add(Menu.NONE, action_unflag, 5, R.string.title_unflag);
if (result.hasArchive && !result.isArchive) // has archive and not is archive/drafts
@ -1048,17 +1031,15 @@ public class FragmentMessages extends FragmentBase {
popupMenu.getMenu().add(Menu.NONE, action_junk, 9, R.string.title_spam);
int order = 11;
if (result.accounts != null)
for (EntityAccount account : result.accounts)
if (!account.pop) {
SubMenu smenu = popupMenu.getMenu()
.addSubMenu(Menu.NONE, 0, order++, getString(R.string.title_move_to, account.name));
int sorder = 1;
for (EntityFolder target : result.targets.get(account)) {
MenuItem item = smenu.add(Menu.NONE, action_move, sorder++, target.getDisplayName(getContext()));
item.setIntent(new Intent().putExtra("target", target.id));
}
}
for (EntityAccount account : result.accounts) {
SubMenu smenu = popupMenu.getMenu()
.addSubMenu(Menu.NONE, 0, order++, getString(R.string.title_move_to, account.name));
int sorder = 1;
for (EntityFolder target : result.targets.get(account)) {
MenuItem item = smenu.add(Menu.NONE, action_move, sorder++, target.getDisplayName(getContext()));
item.setIntent(new Intent().putExtra("target", target.id));
}
}
popupMenu.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
@Override
@ -2219,9 +2200,8 @@ public class FragmentMessages extends FragmentBase {
EntityMessage message = db.message().getMessage(id);
if (message == null)
return null;
EntityAccount account = db.account().getAccount(message.account);
if (message.uid != null || account.pop) {
if (message.uid != null) {
if (!message.content)
EntityOperation.queue(context, db, message, EntityOperation.BODY);
if (!message.ui_seen)
@ -2532,8 +2512,8 @@ public class FragmentMessages extends FragmentBase {
private class MoreResult {
boolean seen;
boolean unseen;
Boolean flagged;
Boolean unflagged;
boolean flagged;
boolean unflagged;
Boolean hasArchive;
Boolean hasTrash;
Boolean hasJunk;

@ -23,8 +23,6 @@ import android.content.Context;
import android.text.TextUtils;
import android.webkit.MimeTypeMap;
import com.sun.mail.imap.IMAPMessage;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
@ -36,13 +34,10 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Enumeration;
import java.util.List;
import java.util.Locale;
import java.util.Properties;
import javax.activation.DataHandler;
@ -170,25 +165,6 @@ public class MessageHelper {
props.put("mail.smtp.writetimeout", Integer.toString(NETWORK_TIMEOUT)); // one thread overhead
props.put("mail.smtp.timeout", Integer.toString(NETWORK_TIMEOUT));
// https://javaee.github.io/javamail/docs/api/com/sun/mail/pop3/package-summary.html
props.put("mail.pop3s.ssl.checkserveridentity", checkserveridentity);
props.put("mail.pop3s.ssl.trust", "*");
props.put("mail.pop3s.starttls.enable", "false");
props.put("mail.pop3s.starttls.required", "false");
props.put("mail.pop3s.connectiontimeout", Integer.toString(NETWORK_TIMEOUT));
props.put("mail.pop3s.timeout", Integer.toString(NETWORK_TIMEOUT));
props.put("mail.pop3s.writetimeout", Integer.toString(NETWORK_TIMEOUT)); // one thread overhead
props.put("mail.pop3.ssl.checkserveridentity", checkserveridentity);
props.put("mail.pop3.ssl.trust", "*");
props.put("mail.pop3.starttls.enable", "true");
props.put("mail.pop3.starttls.required", "true");
props.put("mail.pop3.connectiontimeout", Integer.toString(NETWORK_TIMEOUT));
props.put("mail.pop3.timeout", Integer.toString(NETWORK_TIMEOUT));
props.put("mail.pop3.writetimeout", Integer.toString(NETWORK_TIMEOUT)); // one thread overhead
// MIME
props.put("mail.mime.allowutf8", "true"); // SMTPTransport, MimeMessage
props.put("mail.mime.address.strict", "false");
@ -536,23 +512,7 @@ public class MessageHelper {
}
long getReceived() throws MessagingException {
if (imessage instanceof IMAPMessage)
return imessage.getReceivedDate().getTime();
else {
String[] headers = imessage.getHeader("Received");
DateFormat df = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
if (headers != null)
for (String received : headers) {
int i = received.lastIndexOf(';');
if (i > 0)
try {
return df.parse(received.substring(i + 1).trim()).getTime();
} catch (java.text.ParseException ex) {
// Ignored
}
}
return new Date().getTime();
}
return imessage.getReceivedDate().getTime();
}
Long getSent() throws MessagingException {

@ -25,7 +25,6 @@ import androidx.recyclerview.widget.RecyclerView;
public class SelectionPredicateMessage extends SelectionTracker.SelectionPredicate<Long> {
private boolean enabled;
private boolean folder;
private RecyclerView recyclerView;
SelectionPredicateMessage(RecyclerView recyclerView) {
@ -37,10 +36,6 @@ public class SelectionPredicateMessage extends SelectionTracker.SelectionPredica
this.enabled = enabled;
}
void setFolder(boolean folder) {
this.folder = folder;
}
@Override
public boolean canSetStateForKey(@NonNull Long key, boolean nextState) {
if (!enabled)
@ -51,7 +46,7 @@ public class SelectionPredicateMessage extends SelectionTracker.SelectionPredica
if (message == null)
return false;
if (message.uid != null || (folder && message.accountPop))
if (message.uid != null)
return true;
return false;
@ -67,7 +62,7 @@ public class SelectionPredicateMessage extends SelectionTracker.SelectionPredica
if (message == null)
return false;
if (message.uid != null || (folder && message.accountPop))
if (message.uid != null)
return true;
return false;

@ -55,8 +55,6 @@ import com.sun.mail.imap.IMAPStore;
import com.sun.mail.imap.protocol.FetchResponse;
import com.sun.mail.imap.protocol.IMAPProtocol;
import com.sun.mail.imap.protocol.UID;
import com.sun.mail.pop3.POP3Folder;
import com.sun.mail.pop3.POP3Message;
import com.sun.mail.util.FolderClosedIOException;
import com.sun.mail.util.MailConnectException;
@ -937,10 +935,8 @@ public class ServiceSynchronize extends LifecycleService {
throw ex;
}
final boolean capIdle =
(istore instanceof IMAPStore ? ((IMAPStore) istore).hasCapability("IDLE") : false);
final boolean capUidPlus =
(istore instanceof IMAPStore ? ((IMAPStore) istore).hasCapability("UIDPLUS") : false);
final boolean capIdle = ((IMAPStore) istore).hasCapability("IDLE");
final boolean capUidPlus = ((IMAPStore) istore).hasCapability("UIDPLUS");
Log.i(account.name + " idle=" + capIdle + " uidplus=" + capUidPlus);
db.account().setAccountState(account.id, "connected");
@ -951,8 +947,7 @@ public class ServiceSynchronize extends LifecycleService {
EntityLog.log(this, account.name + " connected");
// Update folder list
if (istore instanceof IMAPStore)
synchronizeFolders(account, istore, state);
synchronizeFolders(account, istore, state);
// Open synchronizing folders
final ExecutorService pollExecutor = Executors.newSingleThreadExecutor(Helper.backgroundThreadFactory);
@ -1226,14 +1221,12 @@ public class ServiceSynchronize extends LifecycleService {
if (db.operation().getOperationCount(folder.id, null) == 0)
return;
if (!account.pop || EntityFolder.INBOX.equals(folder.type)) {
db.folder().setFolderState(folder.id, "connecting");
db.folder().setFolderState(folder.id, "connecting");
ifolder = istore.getFolder(folder.name);
ifolder.open(Folder.READ_WRITE);
ifolder = istore.getFolder(folder.name);
ifolder.open(Folder.READ_WRITE);
db.folder().setFolderState(folder.id, "connected");
}
db.folder().setFolderState(folder.id, "connected");
db.folder().setFolderError(folder.id, null);
}
@ -1477,77 +1470,59 @@ public class ServiceSynchronize extends LifecycleService {
if (message != null)
db.message().setMessageError(message.id, null);
if (account != null && account.pop) {
if (EntityOperation.SEEN.equals(op.name))
doSeen(folder, (POP3Folder) ifolder, message, jargs, db);
else if (EntityOperation.ADD.equals(op.name))
; // Do nothing
else if (EntityOperation.DELETE.equals(op.name))
doDelete(folder, (POP3Folder) ifolder, message, jargs, db);
else if (EntityOperation.SYNC.equals(op.name))
synchronizeMessages(account, folder, (POP3Folder) ifolder, jargs, state);
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);
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
// Operations should use database transaction when needed
if (EntityOperation.SEEN.equals(op.name))
doSeen(folder, (IMAPFolder) ifolder, message, jargs, db);
if (EntityOperation.SEEN.equals(op.name))
doSeen(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.FLAG.equals(op.name))
doFlag(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.FLAG.equals(op.name))
doFlag(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.ANSWERED.equals(op.name))
doAnswered(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.ANSWERED.equals(op.name))
doAnswered(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.KEYWORD.equals(op.name))
doKeyword(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.KEYWORD.equals(op.name))
doKeyword(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.ADD.equals(op.name))
doAdd(folder, isession, (IMAPStore) istore, (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.MOVE.equals(op.name))
doMove(folder, isession, (IMAPStore) istore, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.DELETE.equals(op.name))
doDelete(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.DELETE.equals(op.name))
doDelete(folder, (IMAPFolder) ifolder, message, jargs, db);
else if (EntityOperation.SEND.equals(op.name))
doSend(message, db);
else if (EntityOperation.SEND.equals(op.name))
doSend(message, db);
else if (EntityOperation.HEADERS.equals(op.name))
doHeaders(folder, (IMAPFolder) ifolder, message, db);
else if (EntityOperation.HEADERS.equals(op.name))
doHeaders(folder, (IMAPFolder) ifolder, message, db);
else if (EntityOperation.RAW.equals(op.name))
doRaw(folder, (IMAPFolder) ifolder, message, jargs, db);
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.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 (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
throw new MessagingException("Unknown operation name=" + op.name);
}
synchronizeMessages(account, folder, (IMAPFolder) ifolder, jargs, state);
else
throw new MessagingException("Unknown operation name=" + op.name);
// Operation succeeded
db.operation().deleteOperation(op.id);
@ -1616,15 +1591,6 @@ 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(folder.name + " 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)) {
@ -1909,36 +1875,6 @@ public class ServiceSynchronize extends LifecycleService {
}
}
private void doDelete(EntityFolder folder, POP3Folder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException {
Log.i(folder.name + " deleting POP message=" + message.id + " msgid=" + message.msgid);
if (EntityFolder.INBOX.equals(folder.type)) {
// Delete message
if (TextUtils.isEmpty(message.msgid))
throw new IllegalArgumentException("Message ID missing");
boolean found = false;
Message[] imessages = ifolder.getMessages();
for (Message imessage : imessages) {
MessageHelper helper = new MessageHelper((MimeMessage) imessage);
String msgid = helper.getMessageID();
if (message.msgid.equals(msgid)) {
found = true;
imessage.setFlag(Flags.Flag.DELETED, true);
break;
}
}
if (!found)
throw new MessageRemovedException();
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))
@ -2364,110 +2300,6 @@ public class ServiceSynchronize extends LifecycleService {
}
}
private void synchronizeMessages(EntityAccount account, final EntityFolder folder, POP3Folder ifolder, JSONArray jargs, ServiceState state) throws JSONException, MessagingException, IOException {
DB db = DB.getInstance(this);
if (!EntityFolder.INBOX.equals(folder.type)) {
db.folder().setFolderSyncState(folder.id, null);
return;
}
try {
db.folder().setFolderSyncState(folder.id, "syncing");
Message[] imessages = ifolder.getMessages();
Log.i(folder.name + " POP messages=" + imessages.length);
db.folder().setFolderSyncState(folder.id, "downloading");
for (Message imessage : imessages)
try {
if (!state.running())
break;
MessageHelper helper = new MessageHelper((MimeMessage) imessage);
String msgid = helper.getMessageID();
if (msgid == null) {
Log.w(folder.name + " POP no message ID");
continue;
}
List<EntityMessage> messages = db.message().getMessageByMsgId(folder.account, msgid);
if (messages.size() > 0) {
for (EntityMessage message : messages)
db.message().setMessageUiHide(message.id, false);
Log.i(folder.name + " POP having=" + msgid);
continue;
}
EntityMessage message = new EntityMessage();
message.account = folder.account;
message.folder = folder.id;
message.identity = null;
message.uid = null;
message.msgid = helper.getMessageID();
message.references = TextUtils.join(" ", helper.getReferences());
message.inreplyto = helper.getInReplyTo();
message.deliveredto = helper.getDeliveredTo();
message.thread = helper.getThreadId(0);
message.sender = MessageHelper.getSortKey(helper.getFrom());
message.from = helper.getFrom();
message.to = helper.getTo();
message.cc = helper.getCc();
message.bcc = helper.getBcc();
message.reply = helper.getReply();
message.subject = helper.getSubject();
message.size = helper.getSize();
message.content = false;
message.received = helper.getReceived();
message.sent = helper.getSent();
message.seen = false;
message.answered = false;
message.flagged = false;
message.flags = null;
message.keywords = null;
message.ui_seen = false;
message.ui_answered = false;
message.ui_flagged = false;
message.ui_hide = false;
message.ui_found = false;
message.ui_ignored = false;
message.ui_browsed = false;
Uri lookupUri = ContactInfo.getLookupUri(this, message.from);
message.avatar = (lookupUri == null ? null : lookupUri.toString());
message.id = db.message().insertMessage(message);
Log.i(folder.name + " POP id=" + message.id + " uid=" + message.uid);
MessageHelper.MessageParts parts = helper.getMessageParts();
String body = parts.getHtml(this);
Helper.writeText(EntityMessage.getFile(this, message.id), body);
db.message().setMessageContent(message.id, true, HtmlHelper.getPreview(body));
db.message().setMessageWarning(message.id, parts.getWarnings(message.warning));
int sequence = 1;
for (EntityAttachment attachment : parts.getAttachments()) {
Log.i(folder.name + " POP attachment seq=" + sequence +
" name=" + attachment.name + " type=" + attachment.type +
" cid=" + attachment.cid + " pgp=" + attachment.encryption);
attachment.message = message.id;
attachment.sequence = sequence++;
attachment.id = db.attachment().insertAttachment(attachment);
parts.downloadAttachment(this, db, attachment.id, attachment.sequence);
}
} catch (Throwable ex) {
db.folder().setFolderError(folder.id, Helper.formatThrowable(ex));
} finally {
((POP3Message) imessage).invalidate(true);
}
} finally {
db.folder().setFolderSyncState(folder.id, null);
}
}
private void synchronizeMessages(EntityAccount account, final EntityFolder folder, IMAPFolder ifolder, JSONArray jargs, ServiceState state) throws JSONException, MessagingException, IOException {
final DB db = DB.getInstance(this);
try {

@ -22,7 +22,6 @@ package eu.faircode.email;
public class TupleFolderEx extends EntityFolder {
public String accountName;
public Integer accountColor;
public boolean accountPop;
public String accountState;
public int messages;
public int content;
@ -35,7 +34,6 @@ public class TupleFolderEx extends EntityFolder {
return (super.equals(obj) &&
(this.accountName == null ? other.accountName == null : accountName.equals(other.accountName)) &&
(this.accountColor == null ? other.accountColor == null : this.accountColor.equals(other.accountColor)) &&
this.accountPop == other.accountPop &&
(this.accountState == null ? other.accountState == null : accountState.equals(other.accountState)) &&
this.messages == other.messages &&
this.content == other.content &&

@ -24,7 +24,6 @@ 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;
@ -48,7 +47,6 @@ 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)) &&
@ -74,7 +72,6 @@ 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)) &&

@ -82,42 +82,22 @@
android:id="@+id/tvImap"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/title_imap"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
app:layout_constraintBottom_toBottomOf="@+id/swPop"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/swPop" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swPop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="12dp"
app:layout_constraintStart_toEndOf="@id/tvImap"
app:layout_constraintTop_toBottomOf="@id/btnAutoConfig" />
<TextView
android:id="@+id/tvPop"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:text="@string/title_pop3"
android:textAppearance="@style/Base.TextAppearance.AppCompat.Small"
app:layout_constraintBottom_toBottomOf="@id/swPop"
app:layout_constraintStart_toEndOf="@id/swPop"
app:layout_constraintTop_toTopOf="@id/swPop" />
<TextView
android:id="@+id/tvPopHint"
android:id="@+id/tvPopSupport"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:text="@string/title_pop3_hint"
android:text="@string/title_pop3_support"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
android:textStyle="italic"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swPop" />
app:layout_constraintTop_toBottomOf="@id/tvImap" />
<!-- host -->
@ -129,7 +109,7 @@
android:text="@string/title_host"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvPopHint" />
app:layout_constraintTop_toBottomOf="@id/tvPopSupport" />
<EditText
android:id="@+id/etHost"
@ -717,7 +697,7 @@
android:layout_height="0dp"
app:constraint_referenced_ids="
tvDomain,tvDomainHint,etDomain,btnAutoConfig,
tvImap,swPop,tvPop,tvHost,etHost,cbStartTls,cbInsecure,tvPort,etPort" />
tvImap,tvPopSupport,tvHost,etHost,cbStartTls,cbInsecure,tvPort,etPort" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpAuthorize"

@ -199,15 +199,5 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Group
android:id="@+id/grpPop"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="
cbHide,
cbPoll,cbDownload,
tvSyncDays,tvSyncDaysRemark,etSyncDays,
tvKeepDays,etKeepDays,cbKeepAll" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

@ -252,6 +252,7 @@
<string name="title_edit_html">Edit as HTML</string>
<string name="title_last_connected">Last connected: %1$s</string>
<string name="title_pop3_hint">POP3 has significant limitations, so use IMAP whenever possible</string>
<string name="title_pop3_support">POP3 is not supported, see also the FAQ</string>
<string name="title_unseen_count" translatable="false">%1$s (%2$d)</string>

Loading…
Cancel
Save