Browse Source

Fixes, improvements

main
M66B 5 years ago
parent
commit
633482ade7
17 changed files with 242 additions and 183 deletions
  1. +6
    -5
      app/schemas/eu.faircode.email.DB/1.json
  2. +1
    -1
      app/src/main/java/eu/faircode/email/ActivityMain.java
  3. +19
    -20
      app/src/main/java/eu/faircode/email/ActivityView.java
  4. +6
    -3
      app/src/main/java/eu/faircode/email/AdapterMessage.java
  5. +7
    -5
      app/src/main/java/eu/faircode/email/DaoMessage.java
  6. +1
    -1
      app/src/main/java/eu/faircode/email/EntityMessage.java
  7. +42
    -39
      app/src/main/java/eu/faircode/email/FragmentAccount.java
  8. +2
    -1
      app/src/main/java/eu/faircode/email/FragmentAccounts.java
  9. +6
    -2
      app/src/main/java/eu/faircode/email/FragmentCompose.java
  10. +6
    -3
      app/src/main/java/eu/faircode/email/FragmentFolder.java
  11. +6
    -1
      app/src/main/java/eu/faircode/email/FragmentFolders.java
  12. +2
    -1
      app/src/main/java/eu/faircode/email/FragmentIdentities.java
  13. +46
    -43
      app/src/main/java/eu/faircode/email/FragmentIdentity.java
  14. +35
    -21
      app/src/main/java/eu/faircode/email/FragmentMessage.java
  15. +15
    -8
      app/src/main/java/eu/faircode/email/FragmentMessages.java
  16. +2
    -2
      app/src/main/java/eu/faircode/email/FragmentSetup.java
  17. +40
    -27
      app/src/main/java/eu/faircode/email/ServiceSynchronize.java

+ 6
- 5
app/schemas/eu.faircode.email.DB/1.json View File

@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "262ca4c3e0dbf6673b00b8b19fc219de",
"identityHash": "984985d3928b4abdec0802b65e820b2b",
"entities": [
{
"tableName": "identity",
@ -479,12 +479,13 @@
"createSql": "CREATE UNIQUE INDEX `index_message_folder_uid` ON `${TABLE_NAME}` (`folder`, `uid`)"
},
{
"name": "index_message_msgid",
"name": "index_message_msgid_folder",
"unique": true,
"columnNames": [
"msgid"
"msgid",
"folder"
],
"createSql": "CREATE UNIQUE INDEX `index_message_msgid` ON `${TABLE_NAME}` (`msgid`)"
"createSql": "CREATE UNIQUE INDEX `index_message_msgid_folder` ON `${TABLE_NAME}` (`msgid`, `folder`)"
},
{
"name": "index_message_thread",
@ -751,7 +752,7 @@
],
"setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"262ca4c3e0dbf6673b00b8b19fc219de\")"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"984985d3928b4abdec0802b65e820b2b\")"
]
}
}

+ 1
- 1
app/src/main/java/eu/faircode/email/ActivityMain.java View File

@ -27,7 +27,7 @@ public class ActivityMain extends AppCompatActivity implements FragmentManager.O
DB.getInstance(this).account().liveAccounts(true).observe(this, new Observer<List<EntityAccount>>() {
@Override
public void onChanged(@Nullable List<EntityAccount> accounts) {
if (accounts.size() == 0)
if (accounts == null || accounts.size() == 0)
startActivity(new Intent(ActivityMain.this, ActivitySetup.class));
else {
startActivity(new Intent(ActivityMain.this, ActivityView.class));


+ 19
- 20
app/src/main/java/eu/faircode/email/ActivityView.java View File

@ -129,18 +129,20 @@ public class ActivityView extends ActivityBase implements FragmentManager.OnBack
public void onChanged(@Nullable List<EntityAccount> accounts) {
ArrayAdapterDrawer drawerArray = new ArrayAdapterDrawer(ActivityView.this, R.layout.item_drawer);
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
Collections.sort(accounts, new Comparator<EntityAccount>() {
@Override
public int compare(EntityAccount a1, EntityAccount a2) {
return collator.compare(a1.name, a2.name);
}
});
if (accounts != null) {
final Collator collator = Collator.getInstance(Locale.getDefault());
collator.setStrength(Collator.SECONDARY); // Case insensitive, process accents etc
Collections.sort(accounts, new Comparator<EntityAccount>() {
@Override
public int compare(EntityAccount a1, EntityAccount a2) {
return collator.compare(a1.name, a2.name);
}
});
for (EntityAccount account : accounts)
drawerArray.add(new DrawerItem(-1, R.drawable.baseline_folder_24, account.name, account.id));
for (EntityAccount account : accounts)
drawerArray.add(new DrawerItem(-1, R.drawable.baseline_folder_24, account.name, account.id));
}
drawerArray.add(new DrawerItem(ActivityView.this, R.drawable.baseline_settings_applications_24, R.string.menu_setup));
if (getIntentFAQ().resolveActivity(getPackageManager()) != null)
@ -474,16 +476,13 @@ public class ActivityView extends ActivityBase implements FragmentManager.OnBack
EntityMessage message = db.message().getMessage(id);
EntityFolder folder = db.folder().getFolder(message.folder);
if (!EntityFolder.OUTBOX.equals(folder.type) &&
!EntityFolder.ARCHIVE.equals(folder.type)) {
if (!message.seen && !message.ui_seen) {
message.ui_seen = !message.ui_seen;
db.message().updateMessage(message);
if (message.uid != null)
EntityOperation.queue(db, message, EntityOperation.SEEN, message.ui_seen);
if (!EntityFolder.OUTBOX.equals(folder.type))
for (EntityMessage tmessage : db.message().getMessageByThread(message.account, message.thread)) {
tmessage.ui_seen = true;
db.message().updateMessage(tmessage);
EntityOperation.queue(db, tmessage, EntityOperation.SEEN, tmessage.ui_seen);
}
}
db.setTransactionSuccessful();
} finally {


+ 6
- 3
app/src/main/java/eu/faircode/email/AdapterMessage.java View File

@ -129,10 +129,13 @@ public class AdapterMessage extends PagedListAdapter<TupleMessageEx, AdapterMess
public void onChanged(List<EntityOperation> operations) {
String text = message.error +
"\n" + message.id + " " + df.format(new Date(message.received)) +
"\n" + (message.ui_hide ? "HIDDEN " : " ") + message.uid + "/" + message.id +
"\n" + (message.ui_hide ? "HIDDEN " : "") +
"seen=" + message.seen + "/" + message.ui_seen + "/" + message.unseen +
" " + message.uid + "/" + message.id +
"\n" + message.msgid;
for (EntityOperation op : operations)
text += "\n" + op.name + " " + df.format(new Date(op.created));
if (operations != null)
for (EntityOperation op : operations)
text += "\n" + op.name + " " + df.format(new Date(op.created));
tvError.setText(text);
tvError.setVisibility(View.VISIBLE);


+ 7
- 5
app/src/main/java/eu/faircode/email/DaoMessage.java View File

@ -25,7 +25,6 @@ import androidx.lifecycle.LiveData;
import androidx.paging.DataSource;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.OnConflictStrategy;
import androidx.room.Query;
import androidx.room.Update;
@ -56,6 +55,7 @@ public interface DaoMessage {
", MAX(CASE WHEN folder.id = :folder THEN message.id ELSE 0 END) as dummy" +
" FROM message" +
" JOIN folder ON folder.id = message.folder" +
" LEFT JOIN folder f ON f.id = :folder" +
" WHERE (NOT message.ui_hide OR :debug)" +
" GROUP BY CASE WHEN message.thread IS NULL THEN message.id ELSE message.thread END, message.subject" +
" HAVING SUM(CASE WHEN folder.id = :folder THEN 1 ELSE 0 END) > 0" +
@ -83,9 +83,12 @@ public interface DaoMessage {
@Query("SELECT * FROM message WHERE msgid = :msgid")
EntityMessage getMessageByMsgId(String msgid);
@Query("SELECT * FROM message WHERE account = :account AND thread = :thread")
List<EntityMessage> getMessageByThread(long account, String thread);
@Query("SELECT message.*, folder.name as folderName, folder.type as folderType" +
", (SELECT COUNT(m.id) FROM message m WHERE m.account = message.account AND m.thread = message.thread AND NOT m.ui_hide) AS count" +
", (SELECT COUNT(m.id) FROM message m WHERE m.account = message.account AND m.thread = message.thread AND NOT m.ui_hide AND NOT m.ui_seen) AS unseen" +
", (SELECT COUNT(m1.id) FROM message m1 WHERE m1.account = message.account AND m1.thread = message.thread AND NOT m1.ui_hide) AS count" +
", (SELECT COUNT(m2.id) FROM message m2 WHERE m2.account = message.account AND m2.thread = message.thread AND NOT m2.ui_hide AND NOT m2.ui_seen) AS unseen" +
", (SELECT COUNT(a.id) FROM attachment a WHERE a.message = message.id) AS attachments" +
" FROM message" +
" JOIN folder ON folder.id = message.folder" +
@ -98,8 +101,7 @@ public interface DaoMessage {
@Query("SELECT uid FROM message WHERE folder = :folder AND received >= :received AND NOT uid IS NULL")
List<Long> getUids(long folder, long received);
// in case of duplicate message IDs
@Insert(onConflict = OnConflictStrategy.REPLACE)
@Insert
long insertMessage(EntityMessage message);
@Update


+ 1
- 1
app/src/main/java/eu/faircode/email/EntityMessage.java View File

@ -45,7 +45,7 @@ import static androidx.room.ForeignKey.CASCADE;
@Index(value = {"identity"}),
@Index(value = {"replying"}),
@Index(value = {"folder", "uid"}, unique = true),
@Index(value = {"msgid"}, unique = true),
@Index(value = {"msgid", "folder"}, unique = true),
@Index(value = {"thread"}),
@Index(value = {"received"}),
@Index(value = {"ui_seen"}),


+ 42
- 39
app/src/main/java/eu/faircode/email/FragmentAccount.java View File

@ -321,6 +321,9 @@ public class FragmentAccount extends FragmentEx {
@Override
protected void onException(Bundle args, Throwable ex) {
Helper.setViewsEnabled(view, true);
btnCheck.setEnabled(true);
pbCheck.setVisibility(View.GONE);
grpFolders.setVisibility(View.GONE);
btnSave.setVisibility(View.GONE);
Toast.makeText(getContext(), Helper.formatThrowable(ex), Toast.LENGTH_LONG).show();
@ -372,48 +375,48 @@ public class FragmentAccount extends FragmentEx {
new SimpleTask<Void>() {
@Override
protected Void onLoad(Context context, Bundle args) throws Throwable {
String name = args.getString("name");
String host = args.getString("host");
String port = args.getString("port");
String user = args.getString("user");
String password = args.getString("password");
boolean synchronize = args.getBoolean("synchronize");
EntityFolder drafts = (EntityFolder) args.getSerializable("drafts");
EntityFolder sent = (EntityFolder) args.getSerializable("sent");
EntityFolder all = (EntityFolder) args.getSerializable("all");
EntityFolder trash = (EntityFolder) args.getSerializable("trash");
EntityFolder junk = (EntityFolder) args.getSerializable("junk");
if (TextUtils.isEmpty(host))
throw new Throwable(getContext().getString(R.string.title_no_host));
if (TextUtils.isEmpty(port))
throw new Throwable(getContext().getString(R.string.title_no_port));
if (TextUtils.isEmpty(user))
throw new Throwable(getContext().getString(R.string.title_no_user));
if (TextUtils.isEmpty(password))
throw new Throwable(getContext().getString(R.string.title_no_password));
if (drafts == null)
throw new Throwable(getContext().getString(R.string.title_no_drafts));
// Check IMAP server
Session isession = Session.getInstance(MessageHelper.getSessionProperties(), null);
IMAPStore istore = null;
try {
ServiceSynchronize.stop(getContext(), "folder");
String name = args.getString("name");
String host = args.getString("host");
String port = args.getString("port");
String user = args.getString("user");
String password = args.getString("password");
boolean synchronize = args.getBoolean("synchronize");
EntityFolder drafts = (EntityFolder) args.getSerializable("drafts");
EntityFolder sent = (EntityFolder) args.getSerializable("sent");
EntityFolder all = (EntityFolder) args.getSerializable("all");
EntityFolder trash = (EntityFolder) args.getSerializable("trash");
EntityFolder junk = (EntityFolder) args.getSerializable("junk");
if (TextUtils.isEmpty(host))
throw new Throwable(getContext().getString(R.string.title_no_host));
if (TextUtils.isEmpty(port))
throw new Throwable(getContext().getString(R.string.title_no_port));
if (TextUtils.isEmpty(user))
throw new Throwable(getContext().getString(R.string.title_no_user));
if (TextUtils.isEmpty(password))
throw new Throwable(getContext().getString(R.string.title_no_password));
if (drafts == null)
throw new Throwable(getContext().getString(R.string.title_no_drafts));
// Check IMAP server
Session isession = Session.getInstance(MessageHelper.getSessionProperties(), null);
IMAPStore istore = null;
try {
istore = (IMAPStore) isession.getStore("imaps");
istore.connect(host, Integer.parseInt(port), user, password);
istore = (IMAPStore) isession.getStore("imaps");
istore.connect(host, Integer.parseInt(port), user, password);
if (!istore.hasCapability("IDLE"))
throw new MessagingException(getContext().getString(R.string.title_no_idle));
} finally {
if (istore != null)
istore.close();
}
if (!istore.hasCapability("IDLE"))
throw new MessagingException(getContext().getString(R.string.title_no_idle));
} finally {
if (istore != null)
istore.close();
}
if (TextUtils.isEmpty(name))
name = host + "/" + user;
if (TextUtils.isEmpty(name))
name = host + "/" + user;
try {
ServiceSynchronize.stop(getContext(), "account");
DB db = DB.getInstance(getContext());
try {


+ 2
- 1
app/src/main/java/eu/faircode/email/FragmentAccounts.java View File

@ -93,7 +93,8 @@ public class FragmentAccounts extends FragmentEx {
DB.getInstance(getContext()).account().liveAccounts().observe(getViewLifecycleOwner(), new Observer<List<EntityAccount>>() {
@Override
public void onChanged(@Nullable List<EntityAccount> accounts) {
adapter.set(accounts);
if (accounts != null)
adapter.set(accounts);
pbWait.setVisibility(View.GONE);
grpReady.setVisibility(View.VISIBLE);


+ 6
- 2
app/src/main/java/eu/faircode/email/FragmentCompose.java View File

@ -635,6 +635,9 @@ public class FragmentCompose extends FragmentEx {
db.identity().liveIdentities(true).observe(getViewLifecycleOwner(), new Observer<List<EntityIdentity>>() {
@Override
public void onChanged(@Nullable final List<EntityIdentity> identities) {
if (identities == null)
return;
Log.i(Helper.TAG, "Set identities=" + identities.size());
// Sort identities
@ -693,8 +696,9 @@ public class FragmentCompose extends FragmentEx {
new Observer<List<TupleAttachment>>() {
@Override
public void onChanged(@Nullable List<TupleAttachment> attachments) {
adapter.set(attachments);
grpAttachments.setVisibility(attachments.size() > 0 ? View.VISIBLE : View.GONE);
if (attachments != null)
adapter.set(attachments);
grpAttachments.setVisibility(attachments != null && attachments.size() > 0 ? View.VISIBLE : View.GONE);
}
});


+ 6
- 3
app/src/main/java/eu/faircode/email/FragmentFolder.java View File

@ -145,11 +145,14 @@ public class FragmentFolder extends FragmentEx {
DB.getInstance(getContext()).folder().liveFolder(id).observe(getViewLifecycleOwner(), new Observer<EntityFolder>() {
@Override
public void onChanged(@Nullable EntityFolder folder) {
if (folder != null) {
cbSynchronize.setChecked(folder.synchronize);
etAfter.setText(Integer.toString(folder.after));
if (folder == null) {
getFragmentManager().popBackStack();
return;
}
cbSynchronize.setChecked(folder.synchronize);
etAfter.setText(Integer.toString(folder.after));
pbWait.setVisibility(View.GONE);
Helper.setViewsEnabled(view, true);
btnSave.setEnabled(true);


+ 6
- 1
app/src/main/java/eu/faircode/email/FragmentFolders.java View File

@ -92,7 +92,7 @@ public class FragmentFolders extends FragmentEx {
db.account().liveAccount(account).observe(getViewLifecycleOwner(), new Observer<EntityAccount>() {
@Override
public void onChanged(@Nullable EntityAccount account) {
setSubtitle(account.name);
setSubtitle(account == null ? null : account.name);
}
});
@ -100,6 +100,11 @@ public class FragmentFolders extends FragmentEx {
db.folder().liveFolders(account).observe(getViewLifecycleOwner(), new Observer<List<TupleFolderEx>>() {
@Override
public void onChanged(@Nullable List<TupleFolderEx> folders) {
if (folders == null) {
getFragmentManager().popBackStack();
return;
}
adapter.set(folders);
pbWait.setVisibility(View.GONE);


+ 2
- 1
app/src/main/java/eu/faircode/email/FragmentIdentities.java View File

@ -93,7 +93,8 @@ public class FragmentIdentities extends FragmentEx {
DB.getInstance(getContext()).identity().liveIdentities().observe(getViewLifecycleOwner(), new Observer<List<TupleIdentityEx>>() {
@Override
public void onChanged(@Nullable List<TupleIdentityEx> identities) {
adapter.set(identities);
if (identities != null)
adapter.set(identities);
pbWait.setVisibility(View.GONE);
grpReady.setVisibility(View.VISIBLE);


+ 46
- 43
app/src/main/java/eu/faircode/email/FragmentIdentity.java View File

@ -198,50 +198,50 @@ public class FragmentIdentity extends FragmentEx {
new SimpleTask<Void>() {
@Override
protected Void onLoad(Context context, Bundle args) throws Throwable {
try {
ServiceSynchronize.stop(getContext(), "account");
long id = args.getLong("id");
String name = args.getString("name");
String email = args.getString("email");
String replyto = args.getString("replyto");
long account = args.getLong("account");
String host = args.getString("host");
boolean starttls = args.getBoolean("starttls");
String port = args.getString("port");
String user = args.getString("user");
String password = args.getString("password");
boolean synchronize = args.getBoolean("synchronize");
if (TextUtils.isEmpty(name))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_name));
if (TextUtils.isEmpty(email))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_email));
if (account < 0)
throw new IllegalArgumentException(getContext().getString(R.string.title_no_account));
if (TextUtils.isEmpty(host))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_host));
if (TextUtils.isEmpty(port))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_port));
if (TextUtils.isEmpty(user))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_user));
if (TextUtils.isEmpty(password))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_password));
if (TextUtils.isEmpty(replyto))
replyto = null;
// Check SMTP server
if (synchronize) {
Properties props = MessageHelper.getSessionProperties();
Session isession = Session.getInstance(props, null);
Transport itransport = isession.getTransport(starttls ? "smtp" : "smtps");
try {
itransport.connect(host, Integer.parseInt(port), user, password);
} finally {
itransport.close();
}
long id = args.getLong("id");
String name = args.getString("name");
String email = args.getString("email");
String replyto = args.getString("replyto");
long account = args.getLong("account");
String host = args.getString("host");
boolean starttls = args.getBoolean("starttls");
String port = args.getString("port");
String user = args.getString("user");
String password = args.getString("password");
boolean synchronize = args.getBoolean("synchronize");
if (TextUtils.isEmpty(name))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_name));
if (TextUtils.isEmpty(email))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_email));
if (account < 0)
throw new IllegalArgumentException(getContext().getString(R.string.title_no_account));
if (TextUtils.isEmpty(host))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_host));
if (TextUtils.isEmpty(port))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_port));
if (TextUtils.isEmpty(user))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_user));
if (TextUtils.isEmpty(password))
throw new IllegalArgumentException(getContext().getString(R.string.title_no_password));
if (TextUtils.isEmpty(replyto))
replyto = null;
// Check SMTP server
if (synchronize) {
Properties props = MessageHelper.getSessionProperties();
Session isession = Session.getInstance(props, null);
Transport itransport = isession.getTransport(starttls ? "smtp" : "smtps");
try {
itransport.connect(host, Integer.parseInt(port), user, password);
} finally {
itransport.close();
}
}
try {
ServiceSynchronize.stop(getContext(), "identity");
DB db = DB.getInstance(getContext());
try {
@ -388,6 +388,9 @@ public class FragmentIdentity extends FragmentEx {
db.account().liveAccounts().observe(getViewLifecycleOwner(), new Observer<List<EntityAccount>>() {
@Override
public void onChanged(List<EntityAccount> accounts) {
if (accounts == null)
return;
EntityAccount unselected = new EntityAccount();
unselected.id = -1L;
unselected.name = "";


+ 35
- 21
app/src/main/java/eu/faircode/email/FragmentMessage.java View File

@ -60,6 +60,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu;
import androidx.browser.customtabs.CustomTabsIntent;
import androidx.constraintlayout.widget.Group;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.Observer;
import androidx.recyclerview.widget.LinearLayoutManager;
@ -279,8 +280,9 @@ public class FragmentMessage extends FragmentEx {
new Observer<List<TupleAttachment>>() {
@Override
public void onChanged(@Nullable List<TupleAttachment> attachments) {
adapter.set(attachments);
grpAttachments.setVisibility(attachments.size() > 0 ? View.VISIBLE : View.GONE);
if (attachments != null)
adapter.set(attachments);
grpAttachments.setVisibility(attachments != null && attachments.size() > 0 ? View.VISIBLE : View.GONE);
}
});
@ -313,21 +315,22 @@ public class FragmentMessage extends FragmentEx {
boolean hasJunk = false;
boolean hasArchive = false;
boolean hasUser = false;
for (EntityFolder folder : folders) {
if (EntityFolder.TRASH.equals(folder.type))
hasTrash = true;
else if (EntityFolder.JUNK.equals(folder.type))
hasJunk = true;
else if (EntityFolder.ARCHIVE.equals(folder.type))
hasArchive = true;
else if (EntityFolder.USER.equals(folder.type))
hasUser = true;
}
if (folders != null)
for (EntityFolder folder : folders) {
if (EntityFolder.TRASH.equals(folder.type))
hasTrash = true;
else if (EntityFolder.JUNK.equals(folder.type))
hasJunk = true;
else if (EntityFolder.ARCHIVE.equals(folder.type))
hasArchive = true;
else if (EntityFolder.USER.equals(folder.type))
hasUser = true;
}
bottom_navigation.setTag(inTrash || !hasTrash);
top_navigation.getMenu().findItem(R.id.action_thread).setVisible(message.count > 1);
top_navigation.getMenu().findItem(R.id.action_seen).setVisible(!inOutbox && !inArchive);
top_navigation.getMenu().findItem(R.id.action_seen).setVisible(!inOutbox);
top_navigation.getMenu().findItem(R.id.action_edit).setVisible(inTrash);
top_navigation.getMenu().findItem(R.id.action_forward).setVisible(!inOutbox);
top_navigation.getMenu().findItem(R.id.action_reply_all).setVisible(!inOutbox && message.cc != null);
@ -335,7 +338,7 @@ public class FragmentMessage extends FragmentEx {
bottom_navigation.getMenu().findItem(R.id.action_spam).setVisible(!inOutbox && !inArchive && !inJunk && hasJunk);
bottom_navigation.getMenu().findItem(R.id.action_trash).setVisible(!inOutbox && !inArchive && hasTrash);
bottom_navigation.getMenu().findItem(R.id.action_move).setVisible(!inOutbox && !inArchive && (!inInbox || hasUser));
bottom_navigation.getMenu().findItem(R.id.action_move).setVisible(!inOutbox && (!inInbox || hasUser));
bottom_navigation.getMenu().findItem(R.id.action_archive).setVisible(!inOutbox && !inArchive && hasArchive);
bottom_navigation.getMenu().findItem(R.id.action_reply).setVisible(!inOutbox);
bottom_navigation.setVisibility(View.VISIBLE);
@ -372,6 +375,8 @@ public class FragmentMessage extends FragmentEx {
}
private void onActionThread(long id) {
getFragmentManager().popBackStack("thread", FragmentManager.POP_BACK_STACK_INCLUSIVE);
Bundle args = new Bundle();
args.putLong("thread", id); // message ID
@ -402,11 +407,12 @@ public class FragmentMessage extends FragmentEx {
db.beginTransaction();
EntityMessage message = db.message().getMessage(id);
message.ui_seen = !message.ui_seen;
db.message().updateMessage(message);
for (EntityMessage tmessage : db.message().getMessageByThread(message.account, message.thread)) {
tmessage.ui_seen = !message.ui_seen;
db.message().updateMessage(tmessage);
if (message.uid != null)
EntityOperation.queue(db, message, EntityOperation.SEEN, message.ui_seen);
EntityOperation.queue(db, tmessage, EntityOperation.SEEN, tmessage.ui_seen);
}
db.setTransactionSuccessful();
} finally {
@ -459,12 +465,17 @@ public class FragmentMessage extends FragmentEx {
draft.uid = null;
draft.id = db.message().insertMessage(draft);
EntityOperation.queue(db, draft, EntityOperation.ADD);
db.setTransactionSuccessful();
return null;
} finally {
db.endTransaction();
}
EntityOperation.process(context);
return null;
}
@Override
@ -749,8 +760,11 @@ public class FragmentMessage extends FragmentEx {
db.beginTransaction();
EntityMessage message = db.message().getMessage(id);
message.ui_hide = true;
db.message().updateMessage(message);
EntityFolder folder = db.folder().getFolder(message.folder);
if (!EntityFolder.ARCHIVE.equals(folder.type)) {
message.ui_hide = true;
db.message().updateMessage(message);
}
EntityOperation.queue(db, message, EntityOperation.MOVE, target);


+ 15
- 8
app/src/main/java/eu/faircode/email/FragmentMessages.java View File

@ -137,6 +137,11 @@ public class FragmentMessages extends FragmentEx {
messages.observe(getViewLifecycleOwner(), new Observer<PagedList<TupleMessageEx>>() {
@Override
public void onChanged(@Nullable PagedList<TupleMessageEx> messages) {
if (messages == null) {
getFragmentManager().popBackStack();
return;
}
Log.i(Helper.TAG, "Submit messages=" + messages.size());
adapter.submitList(messages);
@ -161,17 +166,19 @@ public class FragmentMessages extends FragmentEx {
DB db = DB.getInstance(context);
Long account;
if (thread < 0)
if (folder < 0)
return db.folder().getPrimaryDrafts().account;
else
Long account = null;
if (thread < 0) {
if (folder >= 0)
account = db.folder().getFolder(folder).account;
else
} else
account = db.message().getMessage(thread).account;
if (account == null) // outbox
account = db.folder().getPrimaryDrafts().account;
if (account == null) {
// outbox
EntityFolder primary = db.folder().getPrimaryDrafts();
if (primary != null)
account = primary.account;
}
return account;
}


+ 2
- 2
app/src/main/java/eu/faircode/email/FragmentSetup.java View File

@ -196,14 +196,14 @@ public class FragmentSetup extends FragmentEx {
db.account().liveAccounts(true).observe(getViewLifecycleOwner(), new Observer<List<EntityAccount>>() {
@Override
public void onChanged(@Nullable List<EntityAccount> accounts) {
tvAccountDone.setVisibility(accounts.size() > 0 ? View.VISIBLE : View.INVISIBLE);
tvAccountDone.setVisibility(accounts != null && accounts.size() > 0 ? View.VISIBLE : View.INVISIBLE);
}
});
db.identity().liveIdentities(true).observe(getViewLifecycleOwner(), new Observer<List<EntityIdentity>>() {
@Override
public void onChanged(@Nullable List<EntityIdentity> identities) {
tvIdentityDone.setVisibility(identities.size() > 0 ? View.VISIBLE : View.INVISIBLE);
tvIdentityDone.setVisibility(identities != null && identities.size() > 0 ? View.VISIBLE : View.INVISIBLE);
}
});
}


+ 40
- 27
app/src/main/java/eu/faircode/email/ServiceSynchronize.java View File

@ -134,21 +134,22 @@ public class ServiceSynchronize extends LifecycleService {
@Override
public void onChanged(@Nullable TupleAccountStats stats) {
if (stats != null) {
NotificationManager nm = getSystemService(NotificationManager.class);
nm.notify(NOTIFICATION_SYNCHRONIZE,
getNotificationService(stats.accounts, stats.operations, stats.unsent).build());
if (stats.unseen > 0) {
if (stats.unseen > prev_unseen) {
nm.cancel(NOTIFICATION_UNSEEN);
nm.notify(NOTIFICATION_UNSEEN, getNotificationUnseen(stats.unseen).build());
}
} else
if (stats == null)
return;
NotificationManager nm = getSystemService(NotificationManager.class);
nm.notify(NOTIFICATION_SYNCHRONIZE,
getNotificationService(stats.accounts, stats.operations, stats.unsent).build());
if (stats.unseen > 0) {
if (stats.unseen > prev_unseen) {
nm.cancel(NOTIFICATION_UNSEEN);
nm.notify(NOTIFICATION_UNSEEN, getNotificationUnseen(stats.unseen).build());
}
} else
nm.cancel(NOTIFICATION_UNSEEN);
prev_unseen = stats.unseen;
}
prev_unseen = stats.unseen;
}
});
}
@ -762,7 +763,7 @@ public class ServiceSynchronize extends LifecycleService {
JSONArray jargs = new JSONArray(op.args);
if (EntityOperation.SEEN.equals(op.name))
doSeen(folder, ifolder, message, jargs);
doSeen(folder, ifolder, message, jargs, db);
else if (EntityOperation.ADD.equals(op.name))
doAdd(folder, ifolder, message, db);
@ -821,18 +822,22 @@ public class ServiceSynchronize extends LifecycleService {
}
}
private void doSeen(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, JSONArray jargs) throws MessagingException, JSONException {
private void doSeen(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, JSONArray jargs, DB db) throws MessagingException, JSONException {
// Mark message (un)seen
if (message.uid == null) {
Log.w(Helper.TAG, folder.name + " local op seen id=" + message.id);
return;
}
boolean seen = jargs.getBoolean(0);
Message imessage = ifolder.getMessageByUID(message.uid);
if (imessage == null)
throw new MessageRemovedException();
imessage.setFlag(Flags.Flag.SEEN, jargs.getBoolean(0));
imessage.setFlag(Flags.Flag.SEEN, seen);
message.seen = seen;
db.message().updateMessage(message);
}
private void doAdd(EntityFolder folder, IMAPFolder ifolder, EntityMessage message, DB db) throws MessagingException {
@ -873,8 +878,10 @@ public class ServiceSynchronize extends LifecycleService {
for (EntityAttachment attachment : attachments)
attachment.content = db.attachment().getContent(attachment.id);
imessage.setFlag(Flags.Flag.DELETED, true);
ifolder.expunge();
if (!EntityFolder.ARCHIVE.equals(folder.type)) {
imessage.setFlag(Flags.Flag.DELETED, true);
ifolder.expunge();
}
MimeMessageEx icopy = MessageHelper.from(message, attachments, isession);
Folder itarget = istore.getFolder(target.name);
@ -1177,6 +1184,7 @@ public class ServiceSynchronize extends LifecycleService {
DB db = DB.getInstance(this);
try {
int result = 0;
db.beginTransaction();
// Find message by uid (fast, no headers required)
@ -1192,10 +1200,14 @@ public class ServiceSynchronize extends LifecycleService {
String msgid = imessage.getMessageID();
message = db.message().getMessageByMsgId(msgid);
if (message != null) {
Log.i(Helper.TAG, folder.name + " found as id=" + message.id + " uid=" + message.uid + " msgid=" + msgid);
message.folder = folder.id;
message.uid = uid;
db.message().updateMessage(message);
if (message.folder == folder.id || EntityFolder.OUTBOX.equals(folder.type)) {
Log.i(Helper.TAG, folder.name + " found as id=" + message.id + " uid=" + message.uid + " msgid=" + msgid);
message.folder = folder.id;
message.uid = uid;
db.message().updateMessage(message);
result = -1;
} else
message = null;
}
}
@ -1204,16 +1216,17 @@ public class ServiceSynchronize extends LifecycleService {
message.seen = seen;
message.ui_seen = seen;
db.message().updateMessage(message);
Log.v(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid);
return -1;
} else {
Log.v(Helper.TAG, folder.name + " updated id=" + message.id + " uid=" + message.uid + " seen=" + seen);
result = -1;
} else
Log.v(Helper.TAG, folder.name + " unchanged id=" + message.id + " uid=" + message.uid);
return 0;
}
}
db.setTransactionSuccessful();
if (message != null)
return result;
} finally {
db.endTransaction();
}


Loading…
Cancel
Save