From 17c894b3d1c2f4748bb273d4e5cce8dee13e9542 Mon Sep 17 00:00:00 2001 From: M66B Date: Sun, 26 Aug 2018 13:24:16 +0000 Subject: [PATCH] Virtual messages --- .../java/eu/faircode/email/ActivityView.java | 12 +- .../eu/faircode/email/AdapterMessage.java | 4 +- .../eu/faircode/email/AdapterOperation.java | 20 +- .../java/eu/faircode/email/EntityMessage.java | 13 +- .../eu/faircode/email/FragmentMessage.java | 549 +++++++++--------- .../eu/faircode/email/FragmentMessages.java | 31 +- 6 files changed, 308 insertions(+), 321 deletions(-) diff --git a/app/src/main/java/eu/faircode/email/ActivityView.java b/app/src/main/java/eu/faircode/email/ActivityView.java index 6c6aaa4f2d..8e672e207f 100644 --- a/app/src/main/java/eu/faircode/email/ActivityView.java +++ b/app/src/main/java/eu/faircode/email/ActivityView.java @@ -647,18 +647,16 @@ public class ActivityView extends ActivityBase implements FragmentManager.OnBack new SimpleTask() { @Override protected Void onLoad(Context context, Bundle args) { - long id = args.getLong("id"); + TupleMessageEx message = (TupleMessageEx) args.getSerializable("message"); DB db = DB.getInstance(context); try { db.beginTransaction(); - EntityMessage message = db.message().getMessage(id); - if (message != null) // Searched messages are not stored in the database - for (EntityMessage tmessage : db.message().getMessageByThread(message.account, message.thread)) { - db.message().setMessageUiSeen(tmessage.id, true); - EntityOperation.queue(db, tmessage, EntityOperation.SEEN, true); - } + for (EntityMessage tmessage : db.message().getMessageByThread(message.account, message.thread)) { + db.message().setMessageUiSeen(tmessage.id, true); + EntityOperation.queue(db, tmessage, EntityOperation.SEEN, true); + } db.setTransactionSuccessful(); } finally { diff --git a/app/src/main/java/eu/faircode/email/AdapterMessage.java b/app/src/main/java/eu/faircode/email/AdapterMessage.java index f1143403aa..0facb2ffea 100644 --- a/app/src/main/java/eu/faircode/email/AdapterMessage.java +++ b/app/src/main/java/eu/faircode/email/AdapterMessage.java @@ -190,7 +190,7 @@ public class AdapterMessage extends PagedListAdapter() { - private boolean once = false; + if (savedInstanceState == null) { + setSubtitle(Helper.localizeFolderName(getContext(), message.folderName)); - @Override - public void onChanged(@Nullable final TupleMessageEx message) { - if (message == null || (!(debug && BuildConfig.DEBUG) && message.ui_hide)) { - // Message gone (moved, deleted) - finish(); - return; - } - - FragmentMessage.this.message = message; - - if (savedInstanceState == null) { - if (once) - return; - once = true; + tvFrom.setText(message.from == null ? null : MessageHelper.getFormattedAddresses(message.from, true)); + tvTime.setText(message.sent == null ? null : df.format(new Date(message.sent))); + tvTo.setText(message.to == null ? null : MessageHelper.getFormattedAddresses(message.to, true)); + tvSubject.setText(message.subject); - setSubtitle(Helper.localizeFolderName(getContext(), message.folderName)); + tvCount.setText(Integer.toString(message.count)); - tvFrom.setText(message.from == null ? null : MessageHelper.getFormattedAddresses(message.from, true)); - tvTime.setText(message.sent == null ? null : df.format(new Date(message.sent))); - tvTo.setText(message.to == null ? null : MessageHelper.getFormattedAddresses(message.to, true)); - tvSubject.setText(message.subject); + tvReplyTo.setText(message.reply == null ? null : MessageHelper.getFormattedAddresses(message.reply, true)); + tvCc.setText(message.cc == null ? null : MessageHelper.getFormattedAddresses(message.cc, true)); + tvBcc.setText(message.bcc == null ? null : MessageHelper.getFormattedAddresses(message.bcc, true)); - tvCount.setText(Integer.toString(message.count)); - - tvReplyTo.setText(message.reply == null ? null : MessageHelper.getFormattedAddresses(message.reply, true)); - tvCc.setText(message.cc == null ? null : MessageHelper.getFormattedAddresses(message.cc, true)); - tvBcc.setText(message.bcc == null ? null : MessageHelper.getFormattedAddresses(message.bcc, true)); + tvError.setText(message.error); + } else { + free = savedInstanceState.getBoolean("free"); + if (free) { + tvCount.setTag(savedInstanceState.getInt("tag_count")); + tvCc.setTag(savedInstanceState.getInt("tag_cc")); + rvAttachment.setTag(savedInstanceState.getInt("tag_attachment")); + tvError.setTag(savedInstanceState.getInt("tag_error")); + } + decrypted = savedInstanceState.getString("decrypted"); + } - tvError.setText(message.error); + if (tvBody.getTag() == null) { + // Spanned text needs to be loaded after recreation too + final Bundle args = new Bundle(); + args.putLong("id", message.id); + args.putBoolean("has_images", false); + args.putBoolean("show_images", false); - } else { - free = savedInstanceState.getBoolean("free"); - if (free) { - tvCount.setTag(savedInstanceState.getInt("tag_count")); - tvCc.setTag(savedInstanceState.getInt("tag_cc")); - rvAttachment.setTag(savedInstanceState.getInt("tag_attachment")); - tvError.setTag(savedInstanceState.getInt("tag_error")); - } - decrypted = savedInstanceState.getString("decrypted"); - } + pbBody.setVisibility(View.VISIBLE); + final SimpleTask bodyTask = new SimpleTask() { + @Override + protected Spanned onLoad(final Context context, final Bundle args) throws Throwable { + final long id = args.getLong("id"); + final boolean show_images = args.getBoolean("show_images"); + String body = (decrypted == null ? message.read(context) : decrypted); + args.putInt("size", body.length()); - getActivity().invalidateOptionsMenu(); + return Html.fromHtml(HtmlHelper.sanitize(getContext(), body, false), new Html.ImageGetter() { + @Override + public Drawable getDrawable(String source) { + float scale = context.getResources().getDisplayMetrics().density; + int px = (int) (24 * scale + 0.5f); + + if (show_images) { + // Get cache folder + File dir = new File(context.getCacheDir(), "images"); + dir.mkdir(); + + // Cleanup cache + long now = new Date().getTime(); + File[] images = dir.listFiles(); + if (images != null) + for (File image : images) + if (image.isFile() && image.lastModified() + CACHE_IMAGE_DURATION < now) { + Log.i(Helper.TAG, "Deleting from image cache " + image.getName()); + image.delete(); + } - if (tvBody.getTag() == null) { - // Spanned text needs to be loaded after recreation too - final Bundle args = new Bundle(); - args.putLong("id", message.id); - args.putBoolean("has_images", false); - args.putBoolean("show_images", false); + // Create unique file name + File file = new File(dir, id + "_" + source.hashCode()); - pbBody.setVisibility(View.VISIBLE); - final SimpleTask bodyTask = new SimpleTask() { - @Override - protected Spanned onLoad(final Context context, final Bundle args) throws Throwable { - final long id = args.getLong("id"); - final boolean show_images = args.getBoolean("show_images"); - String body = (decrypted == null ? EntityMessage.read(context, id) : decrypted); - args.putInt("size", body.length()); + InputStream is = null; + FileOutputStream os = null; + try { + // Get input stream + if (file.exists()) + is = new FileInputStream(file); + else + is = new URL(source).openStream(); + + // Decode image from stream + Bitmap bm = BitmapFactory.decodeStream(is); + if (bm == null) + throw new IllegalArgumentException(); + + // Cache bitmap + if (!file.exists()) { + os = new FileOutputStream(file); + bm.compress(Bitmap.CompressFormat.PNG, 100, os); + } - return Html.fromHtml(HtmlHelper.sanitize(getContext(), body, false), new Html.ImageGetter() { - @Override - public Drawable getDrawable(String source) { - float scale = context.getResources().getDisplayMetrics().density; - int px = (int) (24 * scale + 0.5f); - - if (show_images) { - // Get cache folder - File dir = new File(context.getCacheDir(), "images"); - dir.mkdir(); - - // Cleanup cache - long now = new Date().getTime(); - File[] images = dir.listFiles(); - if (images != null) - for (File image : images) - if (image.isFile() && image.lastModified() + CACHE_IMAGE_DURATION < now) { - Log.i(Helper.TAG, "Deleting from image cache " + image.getName()); - image.delete(); - } - - // Create unique file name - File file = new File(dir, id + "_" + source.hashCode()); - - InputStream is = null; - FileOutputStream os = null; + // Create drawable from bitmap + Drawable d = new BitmapDrawable(context.getResources(), bm); + d.setBounds(0, 0, bm.getWidth(), bm.getHeight()); + return d; + } catch (Throwable ex) { + // Show warning icon + Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + Drawable d = context.getResources().getDrawable(R.drawable.baseline_warning_24, context.getTheme()); + d.setBounds(0, 0, px, px); + return d; + } finally { + // Close streams + if (is != null) { try { - // Get input stream - if (file.exists()) - is = new FileInputStream(file); - else - is = new URL(source).openStream(); - - // Decode image from stream - Bitmap bm = BitmapFactory.decodeStream(is); - if (bm == null) - throw new IllegalArgumentException(); - - // Cache bitmap - if (!file.exists()) { - os = new FileOutputStream(file); - bm.compress(Bitmap.CompressFormat.PNG, 100, os); - } - - // Create drawable from bitmap - Drawable d = new BitmapDrawable(context.getResources(), bm); - d.setBounds(0, 0, bm.getWidth(), bm.getHeight()); - return d; - } catch (Throwable ex) { - // Show warning icon - Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); - Drawable d = context.getResources().getDrawable(R.drawable.baseline_warning_24, context.getTheme()); - d.setBounds(0, 0, px, px); - return d; - } finally { - // Close streams - if (is != null) { - try { - is.close(); - } catch (IOException e) { - Log.w(Helper.TAG, e + "\n" + Log.getStackTraceString(e)); - } - } - if (os != null) { - try { - os.close(); - } catch (IOException e) { - Log.w(Helper.TAG, e + "\n" + Log.getStackTraceString(e)); - } - } + is.close(); + } catch (IOException e) { + Log.w(Helper.TAG, e + "\n" + Log.getStackTraceString(e)); + } + } + if (os != null) { + try { + os.close(); + } catch (IOException e) { + Log.w(Helper.TAG, e + "\n" + Log.getStackTraceString(e)); } - } else { - // Show placeholder icon - args.putBoolean("has_images", true); - Drawable d = context.getResources().getDrawable(R.drawable.baseline_image_24, context.getTheme()); - d.setBounds(0, 0, px, px); - return d; } } - }, new Html.TagHandler() { - @Override - public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { - // Do nothing - } - }); + } else { + // Show placeholder icon + args.putBoolean("has_images", true); + Drawable d = context.getResources().getDrawable(R.drawable.baseline_image_24, context.getTheme()); + d.setBounds(0, 0, px, px); + return d; + } } - + }, new Html.TagHandler() { @Override - protected void onLoaded(Bundle args, Spanned body) { - boolean has_images = args.getBoolean("has_images"); - boolean show_images = args.getBoolean("show_images"); - tvSize.setText(Helper.humanReadableByteCount(args.getInt("size"), false)); - tvBody.setText(body); - tvBody.setTag(true); - btnImages.setVisibility(has_images && !show_images ? View.VISIBLE : View.GONE); - grpMessage.setVisibility(View.VISIBLE); - fab.setVisibility(free ? View.GONE : View.VISIBLE); - pbBody.setVisibility(View.GONE); + public void handleTag(boolean opening, String tag, Editable output, XMLReader xmlReader) { + // Do nothing } - }; + }); + } - bodyTask.load(FragmentMessage.this, args); + @Override + protected void onLoaded(Bundle args, Spanned body) { + boolean has_images = args.getBoolean("has_images"); + boolean show_images = args.getBoolean("show_images"); + tvSize.setText(Helper.humanReadableByteCount(args.getInt("size"), false)); + tvBody.setText(body); + tvBody.setTag(true); + btnImages.setVisibility(has_images && !show_images ? View.VISIBLE : View.GONE); + grpMessage.setVisibility(View.VISIBLE); + fab.setVisibility(free ? View.GONE : View.VISIBLE); + pbBody.setVisibility(View.GONE); + } + }; - btnImages.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - v.setEnabled(false); - args.putBoolean("show_images", true); - bodyTask.load(FragmentMessage.this, args); - } - }); + bodyTask.load(FragmentMessage.this, args); + + btnImages.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + v.setEnabled(false); + args.putBoolean("show_images", true); + bodyTask.load(FragmentMessage.this, args); } + }); + } - int typeface = (message.ui_seen ? Typeface.NORMAL : Typeface.BOLD); - tvFrom.setTypeface(null, typeface); - tvTime.setTypeface(null, typeface); - tvSubject.setTypeface(null, typeface); - tvCount.setTypeface(null, typeface); + int typeface = (message.ui_seen ? Typeface.NORMAL : Typeface.BOLD); + tvFrom.setTypeface(null, typeface); + tvTime.setTypeface(null, typeface); + tvSubject.setTypeface(null, typeface); + tvCount.setTypeface(null, typeface); - int colorUnseen = Helper.resolveColor(getContext(), message.ui_seen - ? android.R.attr.textColorSecondary : R.attr.colorUnread); - tvFrom.setTextColor(colorUnseen); - tvTime.setTextColor(colorUnseen); + int colorUnseen = Helper.resolveColor(getContext(), message.ui_seen + ? android.R.attr.textColorSecondary : R.attr.colorUnread); + tvFrom.setTextColor(colorUnseen); + tvTime.setTextColor(colorUnseen); - pbWait.setVisibility(View.GONE); + pbWait.setVisibility(View.GONE); - grpHeader.setVisibility(free ? View.GONE : View.VISIBLE); - vSeparatorBody.setVisibility(free ? View.GONE : View.VISIBLE); + grpHeader.setVisibility(free ? View.GONE : View.VISIBLE); + vSeparatorBody.setVisibility(free ? View.GONE : View.VISIBLE); - if (free) { - tvCount.setVisibility((int) tvCount.getTag()); - grpAddresses.setVisibility((int) tvCc.getTag()); - grpError.setVisibility((int) tvError.getTag()); - } else { - tvCount.setVisibility(!free && message.count > 1 ? View.VISIBLE : View.GONE); - grpError.setVisibility(free || message.error == null ? View.GONE : View.VISIBLE); + if (free) { + tvCount.setVisibility((int) tvCount.getTag()); + grpAddresses.setVisibility((int) tvCc.getTag()); + grpError.setVisibility((int) tvError.getTag()); + } else { + tvCount.setVisibility(!free && message.count > 1 ? View.VISIBLE : View.GONE); + grpError.setVisibility(free || message.error == null ? View.GONE : View.VISIBLE); + } + + DB db = DB.getInstance(getContext()); + + if (!message.virtual) { + // Observe message + db.message().liveMessage(message.id).observe(getViewLifecycleOwner(), new Observer() { + + @Override + public void onChanged(@Nullable final TupleMessageEx message) { + if (message == null || (!(debug && BuildConfig.DEBUG) && message.ui_hide)) { + // Message gone (moved, deleted) + finish(); + return; + } } + }); - // Observe attachments - db.attachment().liveAttachments(id).removeObservers(getViewLifecycleOwner()); - db.attachment().liveAttachments(id).observe(getViewLifecycleOwner(), - new Observer>() { - @Override - public void onChanged(@Nullable List attachments) { - if (attachments == null) - attachments = new ArrayList<>(); + // Observe attachments + db.attachment().liveAttachments(message.id).observe(getViewLifecycleOwner(), + new Observer>() { + @Override + public void onChanged(@Nullable List attachments) { + if (attachments == null) + attachments = new ArrayList<>(); - adapter.set(attachments); - grpAttachments.setVisibility(!free && attachments.size() > 0 ? View.VISIBLE : View.GONE); - } - }); + adapter.set(attachments); + grpAttachments.setVisibility(!free && attachments.size() > 0 ? View.VISIBLE : View.GONE); + } + }); - // Observe folders - db.folder().liveFolders(message.account).removeObservers(getViewLifecycleOwner()); - db.folder().liveFolders(message.account).observe(getViewLifecycleOwner(), new Observer>() { - @Override - public void onChanged(@Nullable List folders) { - if (folders == null) - folders = new ArrayList<>(); - - boolean inInbox = EntityFolder.INBOX.equals(message.folderType); - boolean inOutbox = EntityFolder.OUTBOX.equals(message.folderType); - boolean inArchive = EntityFolder.ARCHIVE.equals(message.folderType); - boolean inTrash = EntityFolder.TRASH.equals(message.folderType); - boolean inJunk = EntityFolder.JUNK.equals(message.folderType); - - boolean hasTrash = false; - boolean hasJunk = false; - boolean hasArchive = false; - boolean hasUser = false; - 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; - } + // Observe folders + db.folder().liveFolders(message.account).observe(getViewLifecycleOwner(), new Observer>() { + @Override + public void onChanged(@Nullable List folders) { + if (folders == null) + folders = new ArrayList<>(); + + boolean inInbox = EntityFolder.INBOX.equals(message.folderType); + boolean inOutbox = EntityFolder.OUTBOX.equals(message.folderType); + boolean inArchive = EntityFolder.ARCHIVE.equals(message.folderType); + boolean inTrash = EntityFolder.TRASH.equals(message.folderType); + boolean inJunk = EntityFolder.JUNK.equals(message.folderType); + + boolean hasTrash = false; + boolean hasJunk = false; + boolean hasArchive = false; + boolean hasUser = false; + 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 || inOutbox); + bottom_navigation.setTag(inTrash || !hasTrash || inOutbox); - bottom_navigation.getMenu().findItem(R.id.action_spam).setVisible(message.uid != null && !inArchive && !inJunk && hasJunk); - bottom_navigation.getMenu().findItem(R.id.action_trash).setVisible((message.uid != null && hasTrash) || (inOutbox && !TextUtils.isEmpty(message.error))); - bottom_navigation.getMenu().findItem(R.id.action_move).setVisible(message.uid != null && (!inInbox || hasUser)); - bottom_navigation.getMenu().findItem(R.id.action_archive).setVisible(message.uid != null && !inArchive && hasArchive); - bottom_navigation.getMenu().findItem(R.id.action_reply).setVisible(!inOutbox); - bottom_navigation.setVisibility(View.VISIBLE); - } - }); - } - }); + bottom_navigation.getMenu().findItem(R.id.action_spam).setVisible(message.uid != null && !inArchive && !inJunk && hasJunk); + bottom_navigation.getMenu().findItem(R.id.action_trash).setVisible((message.uid != null && hasTrash) || (inOutbox && !TextUtils.isEmpty(message.error))); + bottom_navigation.getMenu().findItem(R.id.action_move).setVisible(message.uid != null && (!inInbox || hasUser)); + bottom_navigation.getMenu().findItem(R.id.action_archive).setVisible(message.uid != null && !inArchive && hasArchive); + bottom_navigation.getMenu().findItem(R.id.action_reply).setVisible(!inOutbox); + bottom_navigation.setVisibility(View.VISIBLE); + } + }); + } } @Override @@ -636,22 +625,20 @@ public class FragmentMessage extends FragmentEx { public void onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); - boolean inOutbox = (message != null && EntityFolder.OUTBOX.equals(message.folderType)); + boolean inOutbox = EntityFolder.OUTBOX.equals(message.folderType); menu.findItem(R.id.menu_addresses).setVisible(!free); - menu.findItem(R.id.menu_thread).setVisible(!free && message != null && message.count > 1); - menu.findItem(R.id.menu_seen).setVisible(!free && message != null && !inOutbox); - menu.findItem(R.id.menu_forward).setVisible(!free && message != null && !inOutbox); - menu.findItem(R.id.menu_reply_all).setVisible(!free && message != null && message.cc != null && !inOutbox); + menu.findItem(R.id.menu_thread).setVisible(!free && !message.virtual && message.count > 1); + menu.findItem(R.id.menu_seen).setVisible(!free && !message.virtual && !inOutbox); + menu.findItem(R.id.menu_forward).setVisible(!free && !message.virtual && !inOutbox); + menu.findItem(R.id.menu_reply_all).setVisible(!free && !message.virtual && message.cc != null && !inOutbox); menu.findItem(R.id.menu_decrypt).setVisible(decrypted == null); - if (message != null) { - MenuItem menuSeen = menu.findItem(R.id.menu_seen); - menuSeen.setIcon(message.ui_seen - ? R.drawable.baseline_visibility_off_24 - : R.drawable.baseline_visibility_24); - menuSeen.setTitle(message.ui_seen ? R.string.title_unseen : R.string.title_seen); - } + MenuItem menuSeen = menu.findItem(R.id.menu_seen); + menuSeen.setIcon(message.ui_seen + ? R.drawable.baseline_visibility_off_24 + : R.drawable.baseline_visibility_24); + menuSeen.setTitle(message.ui_seen ? R.string.title_unseen : R.string.title_seen); } @Override @@ -661,19 +648,19 @@ public class FragmentMessage extends FragmentEx { onMenuAddresses(); return true; case R.id.menu_thread: - onMenuThread(message.id); + onMenuThread(); return true; case R.id.menu_seen: - onMenuSeen(message.id); + onMenuSeen(); return true; case R.id.menu_forward: - onMenuForward(message.id); + onMenuForward(); return true; case R.id.menu_reply_all: - onMenuReplyAll(message.id); + onMenuReplyAll(); return true; case R.id.menu_decrypt: - onMenuDecrypt(message); + onMenuDecrypt(); return true; default: return super.onOptionsItemSelected(item); @@ -684,11 +671,11 @@ public class FragmentMessage extends FragmentEx { grpAddresses.setVisibility(grpAddresses.getVisibility() == View.GONE ? View.VISIBLE : View.GONE); } - private void onMenuThread(long id) { + private void onMenuThread() { getFragmentManager().popBackStack("thread", FragmentManager.POP_BACK_STACK_INCLUSIVE); Bundle args = new Bundle(); - args.putLong("thread", id); // message ID + args.putLong("thread", message.id); FragmentMessages fragment = new FragmentMessages(); fragment.setArguments(args); @@ -698,11 +685,11 @@ public class FragmentMessage extends FragmentEx { fragmentTransaction.commit(); } - private void onMenuSeen(long id) { + private void onMenuSeen() { Helper.setViewsEnabled(view, false); Bundle args = new Bundle(); - args.putLong("id", id); + args.putLong("id", message.id); new SimpleTask() { @Override @@ -741,19 +728,19 @@ public class FragmentMessage extends FragmentEx { }.load(this, args); } - private void onMenuForward(long id) { + private void onMenuForward() { startActivity(new Intent(getContext(), ActivityCompose.class) .putExtra("action", "forward") - .putExtra("reference", id)); + .putExtra("reference", message.id)); } - private void onMenuReplyAll(long id) { + private void onMenuReplyAll() { startActivity(new Intent(getContext(), ActivityCompose.class) .putExtra("action", "reply_all") - .putExtra("reference", id)); + .putExtra("reference", message.id)); } - private void onMenuDecrypt(EntityMessage message) { + private void onMenuDecrypt() { Log.i(Helper.TAG, "On decrypt"); try { if (!PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean("pro", false)) @@ -826,14 +813,14 @@ public class FragmentMessage extends FragmentEx { public void onActivityResult(int requestCode, int resultCode, Intent data) { Log.i(Helper.TAG, "Message onActivityResult request=" + requestCode + " result=" + resultCode + " data=" + data); if (resultCode == RESULT_OK) { - if (requestCode == ActivityView.REQUEST_OPENPGP && message != null) { + if (requestCode == ActivityView.REQUEST_OPENPGP) { Log.i(Helper.TAG, "User interacted"); - onMenuDecrypt(message); + onMenuDecrypt(); } } } - private void onActionSpam(final long id) { + private void onActionSpam() { AlertDialog.Builder builder = new AlertDialog.Builder(getContext()); builder .setMessage(R.string.title_ask_spam) @@ -843,7 +830,7 @@ public class FragmentMessage extends FragmentEx { Helper.setViewsEnabled(view, false); Bundle args = new Bundle(); - args.putLong("id", id); + args.putLong("id", message.id); new SimpleTask() { @Override @@ -886,7 +873,7 @@ public class FragmentMessage extends FragmentEx { .setNegativeButton(android.R.string.cancel, null).show(); } - private void onActionDelete(final long id) { + private void onActionDelete() { boolean delete = (Boolean) bottom_navigation.getTag(); if (delete) { // No trash or is trash @@ -899,7 +886,7 @@ public class FragmentMessage extends FragmentEx { Helper.setViewsEnabled(view, false); Bundle args = new Bundle(); - args.putLong("id", id); + args.putLong("id", message.id); new SimpleTask() { @Override @@ -946,7 +933,7 @@ public class FragmentMessage extends FragmentEx { Helper.setViewsEnabled(view, false); Bundle args = new Bundle(); - args.putLong("id", id); + args.putLong("id", message.id); new SimpleTask() { @Override @@ -986,9 +973,9 @@ public class FragmentMessage extends FragmentEx { } } - private void onActionMove(long id) { + private void onActionMove() { Bundle args = new Bundle(); - args.putLong("id", id); + args.putLong("id", message.id); new SimpleTask>() { @Override @@ -1102,11 +1089,11 @@ public class FragmentMessage extends FragmentEx { }.load(FragmentMessage.this, args); } - private void onActionArchive(long id) { + private void onActionArchive() { Helper.setViewsEnabled(view, false); Bundle args = new Bundle(); - args.putLong("id", id); + args.putLong("id", message.id); new SimpleTask() { @Override @@ -1147,9 +1134,9 @@ public class FragmentMessage extends FragmentEx { }.load(FragmentMessage.this, args); } - private void onActionReply(long id) { + private void onActionReply() { startActivity(new Intent(getContext(), ActivityCompose.class) .putExtra("action", "reply") - .putExtra("reference", id)); + .putExtra("reference", message.id)); } } diff --git a/app/src/main/java/eu/faircode/email/FragmentMessages.java b/app/src/main/java/eu/faircode/email/FragmentMessages.java index 5cb6994121..4719c07d69 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessages.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessages.java @@ -218,17 +218,25 @@ public class FragmentMessages extends FragmentEx { @Override public void loadInitial(LoadInitialParams params, LoadInitialCallback callback) { Log.i(Helper.TAG, "loadInitial(" + params.requestedStartPosition + ", " + params.requestedLoadSize + ")"); - callback.onResult(search(search, params.requestedStartPosition, params.requestedLoadSize), params.requestedStartPosition); + SearchResult result = search(search, params.requestedStartPosition, params.requestedLoadSize); + callback.onResult(result.messages, params.requestedStartPosition, result.total); } @Override public void loadRange(LoadRangeParams params, LoadRangeCallback callback) { Log.i(Helper.TAG, "loadRange(" + params.startPosition + ", " + params.loadSize + ")"); - callback.onResult(search(search, params.startPosition, params.loadSize)); + SearchResult result = search(search, params.startPosition, params.loadSize); + callback.onResult(result.messages); } - private List search(String term, int from, int count) { - List list = new ArrayList<>(); + class SearchResult { + int total; + List messages; + } + + private SearchResult search(String term, int from, int count) { + SearchResult result = new SearchResult(); + result.messages = new ArrayList<>(); IMAPStore istore = null; try { DB db = DB.getInstance(getContext()); @@ -251,11 +259,12 @@ public class FragmentMessages extends FragmentEx { new OrTerm( new SubjectTerm(term), new BodyTerm(term))); + result.total = imessages.length; Log.i(Helper.TAG, "Found messages=" + imessages.length); List selected = new ArrayList<>(); int base = imessages.length - 1 - from; - for (int i = base; i >= 0 && i >= base - count - 1; i--) + for (int i = base; i >= 0 && i >= base - count + 1; i--) selected.add(imessages[i]); Log.i(Helper.TAG, "Selected messages=" + selected.size()); @@ -303,7 +312,10 @@ public class FragmentMessages extends FragmentEx { message.unseen = (seen ? 0 : 1); message.attachments = 0; - list.add(message); + message.body = helper.getHtml(); + message.virtual = true; + + result.messages.add(message); } } catch (Throwable ex) { Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); @@ -316,17 +328,16 @@ public class FragmentMessages extends FragmentEx { } } - return list; + return result; } - }; } }; PagedList.Config.Builder plcb = new PagedList.Config.Builder() - .setEnablePlaceholders(false) + .setEnablePlaceholders(true) .setInitialLoadSizeHint(10) - .setPageSize(PAGE_SIZE); + .setPageSize(10); messages = new LivePagedListBuilder<>(dsf, plcb.build()).build(); }