Concept forward multiple

pull/196/head
M66B 4 years ago
parent 8f75ed1020
commit f37fe854c4

@ -274,6 +274,11 @@ public interface DaoMessage {
" AND folder.type <> '" + EntityFolder.OUTBOX + "'") " AND folder.type <> '" + EntityFolder.OUTBOX + "'")
LiveData<TupleFtsStats> liveFts(); LiveData<TupleFtsStats> liveFts();
@Query("SELECT COUNT(*) FROM message" +
" WHERE id IN (:ids)" +
" AND raw IS NULL or NOT raw")
LiveData<Integer> liveRaw(long[] ids);
@Query("SELECT *" + @Query("SELECT *" +
" FROM message" + " FROM message" +
" WHERE id = :id") " WHERE id = :id")

@ -441,6 +441,10 @@ public class EntityMessage implements Serializable {
} }
File getRawFile(Context context) { File getRawFile(Context context) {
return getRawFile(context, id);
}
static File getRawFile(Context context, Long id) {
File dir = new File(context.getFilesDir(), "raw"); File dir = new File(context.getFilesDir(), "raw");
if (!dir.exists()) if (!dir.exists())
dir.mkdir(); dir.mkdir();

@ -98,6 +98,7 @@ import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.widget.PopupMenu; import androidx.appcompat.widget.PopupMenu;
import androidx.constraintlayout.widget.Group; import androidx.constraintlayout.widget.Group;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.content.FileProvider;
import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils;
import androidx.core.view.MenuItemCompat; import androidx.core.view.MenuItemCompat;
import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentActivity;
@ -106,6 +107,7 @@ import androidx.fragment.app.FragmentResultListener;
import androidx.fragment.app.FragmentTransaction; import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.Lifecycle; import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner; import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.Observer; import androidx.lifecycle.Observer;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.localbroadcastmanager.content.LocalBroadcastManager; import androidx.localbroadcastmanager.content.LocalBroadcastManager;
@ -2645,6 +2647,11 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
if (message == null) if (message == null)
continue; continue;
result.count++;
if (message.raw != null && message.raw)
result.raw++;
EntityAccount account = accounts.get(message.account); EntityAccount account = accounts.get(message.account);
if (account == null) { if (account == null) {
account = db.account().getAccount(message.account); account = db.account().getAccount(message.account);
@ -2816,6 +2823,9 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
if (result.hasJunk && !result.isJunk && !result.isDrafts) // has junk and not junk/drafts if (result.hasJunk && !result.isJunk && !result.isDrafts) // has junk and not junk/drafts
popupMenu.getMenu().add(Menu.NONE, R.string.title_spam, order++, R.string.title_spam); popupMenu.getMenu().add(Menu.NONE, R.string.title_spam, order++, R.string.title_spam);
if (result.accounts.size() > 0 /* IMAP */ && BuildConfig.DEBUG)
popupMenu.getMenu().add(Menu.NONE, R.string.title_raw_send, order++, R.string.title_raw_send);
for (EntityAccount account : result.accounts) { for (EntityAccount account : result.accounts) {
String title = getString(R.string.title_move_to_account, account.name); String title = getString(R.string.title_move_to_account, account.name);
SpannableString ss = new SpannableString(title); SpannableString ss = new SpannableString(title);
@ -2882,6 +2892,9 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
} else if (itemId == R.string.title_spam) { } else if (itemId == R.string.title_spam) {
onActionJunkSelection(); onActionJunkSelection();
return true; return true;
} else if (itemId == R.string.title_raw_send) {
onActionRaw();
return true;
} else if (itemId == R.string.title_move_to_account) { } else if (itemId == R.string.title_move_to_account) {
long account = target.getIntent().getLongExtra("account", -1); long account = target.getIntent().getLongExtra("account", -1);
onActionMoveSelectionAccount(account, false, result.folders); onActionMoveSelectionAccount(account, false, result.folders);
@ -3298,6 +3311,105 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
}.execute(this, args, "messages:move"); }.execute(this, args, "messages:move");
} }
private void onActionRaw() {
Bundle args = new Bundle();
args.putLongArray("ids", getSelection());
selectionTracker.clearSelection();
new SimpleTask<Integer>() {
@Override
protected Integer onExecute(Context context, Bundle args) {
long[] ids = args.getLongArray("ids");
int count = 0;
DB db = DB.getInstance(context);
for (long id : ids) {
EntityMessage message = db.message().getMessage(id);
if (message == null)
continue;
if (message.raw == null || !message.raw) {
count++;
EntityOperation.queue(context, message, EntityOperation.RAW);
}
}
return count;
}
@Override
protected void onExecuted(Bundle args, Integer count) {
long[] ids = args.getLongArray("ids");
if (count == 0) {
send(ids);
return;
}
final Context context = getContext();
LayoutInflater inflator = LayoutInflater.from(context);
View dview = inflator.inflate(R.layout.dialog_forward, null);
TextView tvMessages = dview.findViewById(R.id.tvMessages);
tvMessages.setText(null);
final AlertDialog dialog = new AlertDialog.Builder(context)
.setView(dview)
.setNegativeButton(android.R.string.cancel, null)
.show();
DB db = DB.getInstance(context);
final LiveData<Integer> ld = db.message().liveRaw(ids);
ld.observe(getViewLifecycleOwner(), new Observer<Integer>() {
@Override
public void onChanged(Integer remaining) {
if (remaining == null)
return;
tvMessages.setText(getResources().getQuantityString(R.plurals.title_moving_messages, remaining, remaining));
if (remaining == 0) {
ld.removeObserver(this);
dialog.dismiss();
send(ids);
}
}
});
}
@Override
protected void onException(Bundle args, Throwable ex) {
Log.unexpectedError(getParentFragmentManager(), ex);
}
private void send(long[] ids) {
try {
final Context context = getContext();
ArrayList<Uri> uris = new ArrayList<>();
for (long id : ids) {
File file = EntityMessage.getRawFile(context, id);
Uri uri = FileProvider.getUriForFile(context, BuildConfig.APPLICATION_ID, file);
uris.add(uri);
}
Intent send = new Intent(Intent.ACTION_SEND_MULTIPLE);
send.setPackage(BuildConfig.APPLICATION_ID);
send.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
send.setType("message/rfc822");
send.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
context.startActivity(send);
} catch (Throwable ex) {
// java.lang.IllegalArgumentException: Failed to resolve canonical path for ...
Log.unexpectedError(getParentFragmentManager(), ex);
}
}
}.execute(this, args, "messages:forward");
}
private void onActionMoveSelectionAccount(long account, boolean copy, List<Long> disabled) { private void onActionMoveSelectionAccount(long account, boolean copy, List<Long> disabled) {
Bundle args = new Bundle(); Bundle args = new Bundle();
args.putString("title", getString(copy ? R.string.title_copy_to : R.string.title_move_to_folder)); args.putString("title", getString(copy ? R.string.title_copy_to : R.string.title_move_to_folder));
@ -7804,6 +7916,8 @@ public class FragmentMessages extends FragmentBase implements SharedPreferences.
} }
private class MoreResult { private class MoreResult {
int count;
int raw;
boolean seen; boolean seen;
boolean unseen; boolean unseen;
boolean visible; boolean visible;

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:padding="24dp">
<eu.faircode.email.FixedTextView
android:id="@+id/tvCaption"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_raw_send"
android:textAppearance="@style/TextAppearance.AppCompat.Large"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<eu.faircode.email.FixedTextView
android:id="@+id/tvMessages"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="12 messages"
android:textAppearance="@style/TextAppearance.AppCompat.Medium"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tvCaption" />
</androidx.constraintlayout.widget.ConstraintLayout>
Loading…
Cancel
Save