Select swipe left/right folder

pull/147/head
M66B 6 years ago
parent b1386d5941
commit 1562a33836

@ -1025,8 +1025,9 @@ There is an advanced option to disable automatically resizing of image attachmen
**(64) Can you add custom actions for swipe left/right?**
The most natural thing to do when swiping a list entry left or right is to remove the entry from the list.
The most natural action in the context of FairEmail is to either archive or trash the message.
Other actions, like adding stars to messages, reporting messages as spam and move messages are available via multiple selection.
The most natural action in the context of an email app is moving the message out of the folder to another folder.
You can select the folder to move to in the account settings.
Other actions, like marking messages read and adding stars to messages are available via multiple selection.
<br />

File diff suppressed because it is too large Load Diff

@ -292,6 +292,14 @@ public class AdapterMessage extends RecyclerView.Adapter<AdapterMessage.ViewHold
grpExpanded = itemView.findViewById(R.id.grpExpanded);
}
Rect getItemRect() {
return new Rect(
super.itemView.getLeft(),
super.itemView.getBottom() - vwColor.getHeight(),
super.itemView.getRight(),
super.itemView.getBottom());
}
private void wire() {
final View touch = (viewType == ViewType.THREAD && threading ? ivExpander : vwColor);
touch.setOnClickListener(this);

@ -49,7 +49,7 @@ import io.requery.android.database.sqlite.RequerySQLiteOpenHelperFactory;
// https://developer.android.com/topic/libraries/architecture/room.html
@Database(
version = 38,
version = 39,
entities = {
EntityIdentity.class,
EntityAccount.class,
@ -460,6 +460,14 @@ public abstract class DB extends RoomDatabase {
db.execSQL("ALTER TABLE `rule` ADD COLUMN `stop` INTEGER NOT NULL DEFAULT 0");
}
})
.addMigrations(new Migration(38, 39) {
@Override
public void migrate(SupportSQLiteDatabase db) {
Log.i("DB migration from version " + startVersion + " to " + endVersion);
db.execSQL("ALTER TABLE `account` ADD COLUMN `swipe_left` INTEGER");
db.execSQL("ALTER TABLE `account` ADD COLUMN `swipe_right` INTEGER");
}
})
.build();
}

@ -83,6 +83,12 @@ public interface DaoAccount {
" WHERE operation.name = '" + EntityOperation.SEND + "') AS unsent")
LiveData<TupleAccountStats> liveStats();
@Query("SELECT account.id, swipe_left, l.type AS left_type, swipe_right, r.type AS right_type" +
" FROM account" +
" LEFT JOIN folder l ON l.id = account.swipe_left" +
" LEFT JOIN folder r ON r.id = account.swipe_right")
LiveData<List<TupleAccountSwipes>> liveAccountSwipes();
@Insert
long insertAccount(EntityAccount account);

@ -71,7 +71,9 @@ public class EntityAccount {
@NonNull
public Boolean notify;
@NonNull
public Boolean browse;
public Boolean browse = true;
public Long swipe_left;
public Long swipe_right;
@NonNull
public Integer poll_interval; // keep-alive interval
public String prefix; // namespace
@ -116,6 +118,8 @@ public class EntityAccount {
json.put("synchronize", synchronize);
json.put("primary", primary);
json.put("browse", browse);
json.put("swipe_left", swipe_left);
json.put("swipe_right", swipe_right);
if (color != null)
json.put("color", color);
json.put("notify", notify);
@ -142,14 +146,22 @@ public class EntityAccount {
account.auth_type = json.getInt("auth_type");
account.synchronize = json.getBoolean("synchronize");
account.primary = json.getBoolean("primary");
if (json.has("browse"))
account.browse = json.getBoolean("browse");
else
account.browse = true;
if (json.has("swipe_left"))
account.swipe_left = json.getLong("swipe_left");
if (json.has("swipe_right"))
account.swipe_right = json.getLong("swipe_right");
if (json.has("color"))
account.color = json.getInt("color");
if (json.has("notify"))
account.notify = json.getBoolean("notify");
account.poll_interval = json.getInt("poll_interval");
return account;
}

@ -123,6 +123,8 @@ public class FragmentAccount extends FragmentBase {
private Spinner spAll;
private Spinner spTrash;
private Spinner spJunk;
private Spinner spLeft;
private Spinner spRight;
private Button btnSave;
private ContentLoadingProgressBar pbSave;
@ -194,6 +196,8 @@ public class FragmentAccount extends FragmentBase {
spAll = view.findViewById(R.id.spAll);
spTrash = view.findViewById(R.id.spTrash);
spJunk = view.findViewById(R.id.spJunk);
spLeft = view.findViewById(R.id.spLeft);
spRight = view.findViewById(R.id.spRight);
btnSave = view.findViewById(R.id.btnSave);
pbSave = view.findViewById(R.id.pbSave);
@ -401,6 +405,8 @@ public class FragmentAccount extends FragmentBase {
spAll.setAdapter(adapter);
spTrash.setAdapter(adapter);
spJunk.setAdapter(adapter);
spLeft.setAdapter(adapter);
spRight.setAdapter(adapter);
// Initialize
Helper.setViewsEnabled(view, false);
@ -530,7 +536,10 @@ public class FragmentAccount extends FragmentBase {
if (TextUtils.isEmpty(realm))
realm = null;
DB db = DB.getInstance(context);
CheckResult result = new CheckResult();
result.account = db.account().getAccount(id);
result.folders = new ArrayList<>();
// Check IMAP server / get folders
@ -583,7 +592,6 @@ public class FragmentAccount extends FragmentBase {
if (selectable) {
// Create entry
DB db = DB.getInstance(context);
EntityFolder folder = db.folder().getFolderByName(id, ifolder.getFullName());
if (folder == null) {
int sync = EntityFolder.SYSTEM_FOLDER_SYNC.indexOf(type);
@ -653,7 +661,7 @@ public class FragmentAccount extends FragmentBase {
protected void onExecuted(Bundle args, CheckResult result) {
tvIdle.setVisibility(result.idle ? View.GONE : View.VISIBLE);
setFolders(result.folders);
setFolders(result.folders, result.account);
new Handler().post(new Runnable() {
@Override
@ -692,17 +700,23 @@ public class FragmentAccount extends FragmentBase {
EntityFolder all = (EntityFolder) spAll.getSelectedItem();
EntityFolder trash = (EntityFolder) spTrash.getSelectedItem();
EntityFolder junk = (EntityFolder) spJunk.getSelectedItem();
EntityFolder left = (EntityFolder) spLeft.getSelectedItem();
EntityFolder right = (EntityFolder) spRight.getSelectedItem();
if (drafts != null && drafts.type == null)
if (drafts != null && drafts.id < 0)
drafts = null;
if (sent != null && sent.type == null)
if (sent != null && sent.id < 0)
sent = null;
if (all != null && all.type == null)
if (all != null && all.id < 0)
all = null;
if (trash != null && trash.type == null)
if (trash != null && trash.id < 0)
trash = null;
if (junk != null && junk.type == null)
if (junk != null && junk.id < 0)
junk = null;
if (left != null && left.id < 0)
left = null;
if (right != null && right.id < 0)
right = null;
Bundle args = new Bundle();
args.putLong("id", id);
@ -731,6 +745,8 @@ public class FragmentAccount extends FragmentBase {
args.putSerializable("all", all);
args.putSerializable("trash", trash);
args.putSerializable("junk", junk);
args.putLong("left", left == null ? -1 : left.id);
args.putLong("right", right == null ? -1 : right.id);
new SimpleTask<Void>() {
@Override
@ -780,6 +796,8 @@ public class FragmentAccount extends FragmentBase {
EntityFolder all = (EntityFolder) args.getSerializable("all");
EntityFolder trash = (EntityFolder) args.getSerializable("trash");
EntityFolder junk = (EntityFolder) args.getSerializable("junk");
Long left = args.getLong("left");
Long right = args.getLong("right");
if (TextUtils.isEmpty(host))
throw new IllegalArgumentException(context.getString(R.string.title_no_host));
@ -802,6 +820,11 @@ public class FragmentAccount extends FragmentBase {
if (TextUtils.isEmpty(prefix))
prefix = null;
if (left < 0)
left = null;
if (right < 0)
right = null;
Character separator = null;
long now = new Date().getTime();
@ -870,6 +893,8 @@ public class FragmentAccount extends FragmentBase {
account.primary = (account.synchronize && primary);
account.notify = notify;
account.browse = browse;
account.swipe_left = left;
account.swipe_right = right;
account.poll_interval = Integer.parseInt(interval);
account.prefix = prefix;
@ -1020,7 +1045,7 @@ public class FragmentAccount extends FragmentBase {
}
@Override
protected void onExecuted(Bundle args, EntityAccount account) {
protected void onExecuted(Bundle args, final EntityAccount account) {
// Get providers
List<EmailProvider> providers = EmailProvider.loadProfiles(getContext());
providers.add(0, new EmailProvider(getString(R.string.title_select)));
@ -1130,7 +1155,7 @@ public class FragmentAccount extends FragmentBase {
protected void onExecuted(Bundle args, List<EntityFolder> folders) {
if (folders == null)
folders = new ArrayList<>();
setFolders(folders);
setFolders(folders, account);
}
@Override
@ -1315,25 +1340,37 @@ public class FragmentAccount extends FragmentBase {
vwColor.setBackground(border);
}
private void setFolders(List<EntityFolder> folders) {
private void setFolders(List<EntityFolder> folders, EntityAccount account) {
EntityFolder none = new EntityFolder();
none.id = -1L;
none.name = "-";
folders.add(0, none);
adapter.clear();
adapter.addAll(folders);
Long left = (account == null ? null : account.swipe_left);
Long right = (account == null ? null : account.swipe_right);
for (int pos = 0; pos < folders.size(); pos++) {
if (EntityFolder.DRAFTS.equals(folders.get(pos).type))
EntityFolder folder = folders.get(pos);
if (EntityFolder.DRAFTS.equals(folder.type))
spDrafts.setSelection(pos);
else if (EntityFolder.SENT.equals(folders.get(pos).type))
else if (EntityFolder.SENT.equals(folder.type))
spSent.setSelection(pos);
else if (EntityFolder.ARCHIVE.equals(folders.get(pos).type))
else if (EntityFolder.ARCHIVE.equals(folder.type))
spAll.setSelection(pos);
else if (EntityFolder.TRASH.equals(folders.get(pos).type))
else if (EntityFolder.TRASH.equals(folder.type))
spTrash.setSelection(pos);
else if (EntityFolder.JUNK.equals(folders.get(pos).type))
else if (EntityFolder.JUNK.equals(folder.type))
spJunk.setSelection(pos);
if (left == null ? (account == null && EntityFolder.TRASH.equals(folder.type)) : left.equals(folder.id))
spLeft.setSelection(pos);
if (right == null ? (account == null && EntityFolder.ARCHIVE.equals(folder.type)) : right.equals(folder.id))
spRight.setSelection(pos);
}
grpFolders.setVisibility(folders.size() > 1 ? View.VISIBLE : View.GONE);
@ -1341,6 +1378,7 @@ public class FragmentAccount extends FragmentBase {
}
private class CheckResult {
EntityAccount account;
List<EntityFolder> folders;
boolean idle;
}

@ -26,6 +26,7 @@ import android.content.Intent;
import android.content.SharedPreferences;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Rect;
import android.graphics.drawable.Drawable;
import android.net.ConnectivityManager;
import android.net.Network;
@ -117,8 +118,8 @@ public class FragmentMessages extends FragmentBase {
private boolean connected = false;
private boolean searching = false;
private AdapterMessage adapter;
private List<Long> archives = new ArrayList<>();
private List<Long> trashes = new ArrayList<>();
private Map<Long, TupleAccountSwipes> accountSwipes = new HashMap<>();
private AdapterMessage.ViewType viewType;
private SelectionTracker<Long> selectionTracker = null;
@ -551,29 +552,19 @@ public class FragmentMessages extends FragmentBase {
private ItemTouchHelper.Callback touchHelper = new ItemTouchHelper.Callback() {
@Override
public int getMovementFlags(RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext());
if (!prefs.getBoolean("swipe", true))
return 0;
if (selectionTracker != null && selectionTracker.hasSelection())
return 0;
int pos = viewHolder.getAdapterPosition();
if (pos == RecyclerView.NO_POSITION)
TupleMessageEx message = getMessage(viewHolder);
if (message == null)
return 0;
TupleMessageEx message = ((AdapterMessage) rvMessage.getAdapter()).getCurrentList().get(pos);
if (message == null || message.uid == null ||
(values.containsKey("expanded") && values.get("expanded").contains(message.id)) ||
EntityFolder.DRAFTS.equals(message.folderType) ||
EntityFolder.OUTBOX.equals(message.folderType))
TupleAccountSwipes swipes = accountSwipes.get(message.account);
if (swipes == null)
return 0;
int flags = 0;
if (archives.contains(message.account))
flags |= ItemTouchHelper.RIGHT;
if (trashes.contains(message.account))
if (swipes.swipe_left != null && !swipes.swipe_left.equals(message.folder))
flags |= ItemTouchHelper.LEFT;
if (swipes.swipe_right != null && !swipes.swipe_right.equals(message.folder))
flags |= ItemTouchHelper.RIGHT;
return makeMovementFlags(0, flags);
}
@ -585,40 +576,36 @@ public class FragmentMessages extends FragmentBase {
@Override
public void onChildDraw(Canvas canvas, RecyclerView recyclerView, RecyclerView.ViewHolder viewHolder, float dX, float dY, int actionState, boolean isCurrentlyActive) {
int pos = viewHolder.getAdapterPosition();
if (pos == RecyclerView.NO_POSITION)
return;
TupleMessageEx message = ((AdapterMessage) rvMessage.getAdapter()).getCurrentList().get(pos);
TupleMessageEx message = getMessage(viewHolder);
if (message == null)
return;
boolean inbox = (EntityFolder.ARCHIVE.equals(message.folderType) || EntityFolder.TRASH.equals(message.folderType));
TupleAccountSwipes swipes = accountSwipes.get(message.account);
if (swipes == null)
return;
View itemView = viewHolder.itemView;
Rect rect = ((AdapterMessage.ViewHolder) viewHolder).getItemRect();
int margin = Helper.dp2pixels(getContext(), 12);
if (dX > margin) {
// Right swipe
Drawable d = getResources().getDrawable(
inbox ? R.drawable.baseline_move_to_inbox_24 : R.drawable.baseline_archive_24,
getContext().getTheme());
int padding = (itemView.getHeight() - d.getIntrinsicHeight());
Drawable d = getResources().getDrawable(getIcon(swipes.right_type), getContext().getTheme());
int padding = (rect.height() - d.getIntrinsicHeight());
d.setBounds(
itemView.getLeft() + margin,
itemView.getTop() + padding / 2,
itemView.getLeft() + margin + d.getIntrinsicWidth(),
itemView.getTop() + padding / 2 + d.getIntrinsicHeight());
rect.left + margin,
rect.top + padding / 2,
rect.left + margin + d.getIntrinsicWidth(),
rect.top + padding / 2 + d.getIntrinsicHeight());
d.draw(canvas);
} else if (dX < -margin) {
// Left swipe
Drawable d = getResources().getDrawable(inbox ? R.drawable.baseline_move_to_inbox_24 : R.drawable.baseline_delete_24, getContext().getTheme());
int padding = (itemView.getHeight() - d.getIntrinsicHeight());
Drawable d = getResources().getDrawable(getIcon(swipes.left_type), getContext().getTheme());
int padding = (rect.height() - d.getIntrinsicHeight());
d.setBounds(
itemView.getLeft() + itemView.getWidth() - d.getIntrinsicWidth() - margin,
itemView.getTop() + padding / 2,
itemView.getLeft() + itemView.getWidth() - margin,
itemView.getTop() + padding / 2 + d.getIntrinsicHeight());
rect.left + rect.width() - d.getIntrinsicWidth() - margin,
rect.top + padding / 2,
rect.left + rect.width() - margin,
rect.top + padding / 2 + d.getIntrinsicHeight());
d.draw(canvas);
}
@ -627,51 +614,38 @@ public class FragmentMessages extends FragmentBase {
@Override
public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction) {
int pos = viewHolder.getAdapterPosition();
if (pos == RecyclerView.NO_POSITION)
TupleMessageEx message = getMessage(viewHolder);
if (message == null)
return;
TupleMessageEx message = ((AdapterMessage) rvMessage.getAdapter()).getCurrentList().get(pos);
if (message == null)
TupleAccountSwipes swipes = accountSwipes.get(message.account);
if (swipes == null)
return;
Log.i("Swiped dir=" + direction + " message=" + message.id);
Bundle args = new Bundle();
args.putLong("id", message.id);
args.putBoolean("thread", viewType != AdapterMessage.ViewType.THREAD);
args.putInt("direction", direction);
args.putLong("target", direction == ItemTouchHelper.LEFT ? swipes.swipe_left : swipes.swipe_right);
new SimpleTask<MessageTarget>() {
@Override
protected MessageTarget onExecute(Context context, Bundle args) {
long id = args.getLong("id");
boolean thread = args.getBoolean("thread");
int direction = args.getInt("direction");
long target = args.getLong("target");
MessageTarget result = new MessageTarget();
EntityFolder target = null;
// Get target folder and hide message
DB db = DB.getInstance(context);
try {
db.beginTransaction();
EntityMessage message = db.message().getMessage(id);
EntityFolder folder = db.folder().getFolder(message.folder);
if (EntityFolder.ARCHIVE.equals(folder.type) || EntityFolder.TRASH.equals(folder.type))
target = db.folder().getFolderByType(message.account, EntityFolder.INBOX);
else {
if (direction == ItemTouchHelper.RIGHT)
target = db.folder().getFolderByType(message.account, EntityFolder.ARCHIVE);
if (direction == ItemTouchHelper.LEFT || target == null)
target = db.folder().getFolderByType(message.account, EntityFolder.TRASH);
if (target == null)
target = db.folder().getFolderByType(message.account, EntityFolder.INBOX);
}
result.target = target;
result.target = db.folder().getFolder(target);
EntityMessage message = db.message().getMessage(id);
List<EntityMessage> messages = db.message().getMessageByThread(
message.account, message.thread, threading && thread ? null : id, message.folder);
for (EntityMessage threaded : messages) {
@ -700,6 +674,39 @@ public class FragmentMessages extends FragmentBase {
}
}.execute(FragmentMessages.this, args, "messages:swipe");
}
private TupleMessageEx getMessage(RecyclerView.ViewHolder viewHolder) {
if (selectionTracker != null && selectionTracker.hasSelection())
return null;
int pos = viewHolder.getAdapterPosition();
if (pos == RecyclerView.NO_POSITION)
return null;
TupleMessageEx message = ((AdapterMessage) rvMessage.getAdapter()).getCurrentList().get(pos);
if (message == null || message.uid == null)
return null;
if (values.containsKey("expanded") && values.get("expanded").contains(message.id))
return null;
if (EntityFolder.DRAFTS.equals(message.folderType) || EntityFolder.OUTBOX.equals(message.folderType))
return null;
return message;
}
int getIcon(String type) {
if (EntityFolder.INBOX.equals(type))
return R.drawable.baseline_move_to_inbox_24;
if (EntityFolder.ARCHIVE.equals(type))
return R.drawable.baseline_archive_24;
if (EntityFolder.TRASH.equals(type))
return R.drawable.baseline_delete_24;
if (EntityFolder.JUNK.equals(type))
return R.drawable.baseline_flag_24;
return R.drawable.baseline_folder_24;
}
};
private void onActionMove(String folderType) {
@ -1334,6 +1341,20 @@ public class FragmentMessages extends FragmentBase {
}
});
db.account().liveAccountSwipes().observe(getViewLifecycleOwner(), new Observer<List<TupleAccountSwipes>>() {
@Override
public void onChanged(List<TupleAccountSwipes> swipes) {
if (swipes == null)
swipes = new ArrayList<>();
Log.i("Swipes=" + swipes.size());
accountSwipes.clear();
for (TupleAccountSwipes swipe : swipes)
accountSwipes.put(swipe.id, swipe);
}
});
// Folder
switch (viewType) {
case UNIFIED:
@ -1401,25 +1422,7 @@ public class FragmentMessages extends FragmentBase {
break;
}
// Folders and messages
db.folder().liveSystemFolders(account).observe(getViewLifecycleOwner(), new Observer<List<EntityFolder>>() {
@Override
public void onChanged(List<EntityFolder> folders) {
if (folders == null)
folders = new ArrayList<>();
archives.clear();
trashes.clear();
for (EntityFolder folder : folders)
if (EntityFolder.ARCHIVE.equals(folder.type))
archives.add(folder.account);
else if (EntityFolder.TRASH.equals(folder.type))
trashes.add(folder.account);
loadMessages();
}
});
loadMessages();
if (selectionTracker != null && selectionTracker.hasSelection())
fabMore.show();
@ -1931,13 +1934,19 @@ public class FragmentMessages extends FragmentBase {
archivable = true;
}
EntityFolder trash = db.folder().getFolderByType(account, EntityFolder.TRASH);
EntityFolder archive = db.folder().getFolderByType(account, EntityFolder.ARCHIVE);
trashable = (trashable && trash != null);
archivable = (archivable && archive != null);
return new Boolean[]{trashable, archivable};
}
@Override
protected void onExecuted(Bundle args, Boolean[] data) {
bottom_navigation.getMenu().findItem(R.id.action_delete).setVisible(trashes.size() > 0 && data[0]);
bottom_navigation.getMenu().findItem(R.id.action_archive).setVisible(archives.size() > 0 && data[1]);
bottom_navigation.getMenu().findItem(R.id.action_delete).setVisible(data[0]);
bottom_navigation.getMenu().findItem(R.id.action_archive).setVisible(data[1]);
bottom_navigation.setVisibility(View.VISIBLE);
}

@ -67,7 +67,6 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
private SwitchCompat swAddresses;
private SwitchCompat swPull;
private SwitchCompat swSwipe;
private SwitchCompat swActionbar;
private SwitchCompat swAutoClose;
private SwitchCompat swAutoNext;
@ -90,7 +89,7 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
"enabled", "updates",
"metered", "download",
"unified", "threading", "avatars", "identicons", "preview", "addresses",
"pull", "swipe", "actionbar", "autoclose", "autonext",
"pull", "actionbar", "autoclose", "autonext",
"autoread", "collapse", "automove", "confirm", "sender", "autoresize", "autosend",
"light", "sound", "debug",
"first", "why", "last_update_check",
@ -122,7 +121,6 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
swAddresses = view.findViewById(R.id.swAddresses);
swPull = view.findViewById(R.id.swPull);
swSwipe = view.findViewById(R.id.swSwipe);
swActionbar = view.findViewById(R.id.swActionbar);
swAutoClose = view.findViewById(R.id.swAutoClose);
swAutoNext = view.findViewById(R.id.swAutoNext);
@ -232,13 +230,6 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
}
});
swSwipe.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
prefs.edit().putBoolean("swipe", checked).apply();
}
});
swActionbar.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton compoundButton, boolean checked) {
@ -420,7 +411,6 @@ public class FragmentOptions extends FragmentBase implements SharedPreferences.O
swAddresses.setChecked(prefs.getBoolean("addresses", true));
swPull.setChecked(prefs.getBoolean("pull", true));
swSwipe.setChecked(prefs.getBoolean("swipe", true));
swActionbar.setChecked(prefs.getBoolean("actionbar", true));
swAutoClose.setChecked(prefs.getBoolean("autoclose", true));
swAutoNext.setChecked(prefs.getBoolean("autonext", false));

@ -0,0 +1,28 @@
package eu.faircode.email;
/*
This file is part of FairEmail.
FairEmail is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
FairEmail is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with FairEmail. If not, see <http://www.gnu.org/licenses/>.
Copyright 2018-2019 by Marcel Bokhorst (M66B)
*/
public class TupleAccountSwipes {
public long id;
public Long swipe_left;
public String left_type;
public Long swipe_right;
public String right_type;
}

@ -55,14 +55,14 @@ public class ViewModelMessages extends ViewModel {
}
void observe(AdapterMessage.ViewType viewType, LifecycleOwner owner, Observer<PagedList<TupleMessageEx>> observer) {
if (owner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
if (owner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.INITIALIZED)) {
final boolean thread = (viewType == AdapterMessage.ViewType.THREAD);
messages.get(thread).observe(owner, observer);
}
}
void removeObservers(AdapterMessage.ViewType viewType, LifecycleOwner owner) {
if (owner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.RESUMED)) {
if (owner.getLifecycle().getCurrentState().isAtLeast(Lifecycle.State.INITIALIZED)) {
boolean thread = (viewType == AdapterMessage.ViewType.THREAD);
LiveData<PagedList<TupleMessageEx>> list = messages.get(thread);
if (list != null)

@ -0,0 +1,10 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="24.0"
android:viewportHeight="24.0"
android:tint="?attr/colorControlNormal">
<path
android:fillColor="@android:color/white"
android:pathData="M14.4,6L14,4H5v17h2v-7h5.6l0.4,2h7V6z"/>
</vector>

@ -499,13 +499,33 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/spJunk" />
<TextView
android:id="@+id/tvLeft"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_account_left"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintBottom_toBottomOf="@+id/spLeft"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/spLeft" />
<TextView
android:id="@+id/tvRight"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/title_account_right"
android:textAppearance="@style/TextAppearance.AppCompat.Small"
app:layout_constraintBottom_toBottomOf="@+id/spRight"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="@+id/spRight" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier_folders"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
app:barrierDirection="end"
app:constraint_referenced_ids="tvDrafts,tvSent,tvAll,tvTrash,tvJunk" />
app:constraint_referenced_ids="tvDrafts,tvSent,tvAll,tvTrash,tvJunk,tvLeft,tvRight" />
<Spinner
android:id="@+id/spDrafts"
@ -557,6 +577,25 @@
app:layout_constraintStart_toEndOf="@id/barrier_folders"
app:layout_constraintTop_toBottomOf="@id/spTrash" />
<Spinner
android:id="@+id/spLeft"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier_folders"
app:layout_constraintTop_toBottomOf="@id/spJunk" />
<Spinner
android:id="@+id/spRight"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginStart="6dp"
android:layout_marginTop="12dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/barrier_folders"
app:layout_constraintTop_toBottomOf="@id/spLeft" />
<!-- save -->
@ -567,7 +606,7 @@
android:layout_marginTop="12dp"
android:text="@string/title_save"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/spJunk" />
app:layout_constraintTop_toBottomOf="@id/spRight" />
<eu.faircode.email.ContentLoadingProgressBar
android:id="@+id/pbSave"
@ -626,6 +665,6 @@
android:id="@+id/grpFolders"
android:layout_width="0dp"
android:layout_height="0dp"
app:constraint_referenced_ids="tvDrafts,spDrafts,tvSent,spSent,tvAll,spAll,tvTrash,spTrash,tvJunk,spJunk" />
app:constraint_referenced_ids="tvDrafts,spDrafts,tvSent,spSent,tvAll,spAll,tvTrash,spTrash,tvJunk,spJunk,tvLeft,spLeft,tvRight,spRight" />
</androidx.constraintlayout.widget.ConstraintLayout>
</ScrollView>

@ -325,18 +325,6 @@
app:layout_constraintTop_toBottomOf="@id/vSeparatorBehavior"
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swSwipe"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="12dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="12dp"
android:text="@string/title_advanced_swipe"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swPull"
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat
android:id="@+id/swActionbar"
android:layout_width="match_parent"
@ -346,7 +334,7 @@
android:layout_marginEnd="12dp"
android:text="@string/title_advanced_actionbar"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/swSwipe"
app:layout_constraintTop_toBottomOf="@id/swPull"
app:switchPadding="12dp" />
<androidx.appcompat.widget.SwitchCompat

@ -139,7 +139,6 @@
<string name="title_advanced_sound">Select notification sound</string>
<string name="title_advanced_pull_refresh">Pull down to refresh</string>
<string name="title_advanced_swipe">Swipe actions</string>
<string name="title_advanced_actionbar">Conversation action bar</string>
<string name="title_advanced_autoclose">Automatically close conversations</string>
<string name="title_advanced_autonext">Automatically go to next conversation on close conversation</string>
@ -181,6 +180,8 @@
<string name="title_account_signature">Signature text</string>
<string name="title_account_color">Color</string>
<string name="title_account_notify">Separate notifications</string>
<string name="title_account_left">Swipe left</string>
<string name="title_account_right">Swipe right</string>
<string name="title_domain">Domain name</string>
<string name="title_autoconfig">Get settings</string>
<string name="title_imap" translatable="false">IMAP</string>

Loading…
Cancel
Save