From 790c09af9f422d442f9b2069dc0976197bf6a3ab Mon Sep 17 00:00:00 2001 From: M66B Date: Fri, 14 Sep 2018 16:15:06 +0000 Subject: [PATCH] Left/right experiment Refs #116 --- .../faircode/email/ConstraintLayoutTouch.java | 92 +++++++++++++++++++ .../java/eu/faircode/email/DaoMessage.java | 17 ++++ .../eu/faircode/email/FragmentMessage.java | 36 +++++++- app/src/main/res/layout/fragment_message.xml | 4 +- 4 files changed, 145 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/eu/faircode/email/ConstraintLayoutTouch.java diff --git a/app/src/main/java/eu/faircode/email/ConstraintLayoutTouch.java b/app/src/main/java/eu/faircode/email/ConstraintLayoutTouch.java new file mode 100644 index 00000000..62047d84 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/ConstraintLayoutTouch.java @@ -0,0 +1,92 @@ +package eu.faircode.email; + +import android.content.Context; +import android.util.AttributeSet; +import android.view.GestureDetector; +import android.view.MotionEvent; + +import androidx.constraintlayout.widget.ConstraintLayout; + +public class ConstraintLayoutTouch extends ConstraintLayout { + private IGestureListener listener = null; + + enum Direction {Left, Right, Up, Down} + + private static final long VELOCITY_THRESHOLD = 3000; + + public ConstraintLayoutTouch(Context context) { + super(context); + } + + public ConstraintLayoutTouch(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public ConstraintLayoutTouch(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + @Override + public boolean onInterceptTouchEvent(MotionEvent ev) { + if (listener != null) + gestureDetector.onTouchEvent(ev); + return super.onInterceptTouchEvent(ev); + } + + void setGestureListener(IGestureListener listener) { + this.listener = listener; + } + + private GestureDetector gestureDetector = new GestureDetector(getContext(), new GestureDetector.OnGestureListener() { + @Override + public boolean onDown(final MotionEvent e) { + return false; + } + + @Override + public void onShowPress(final MotionEvent e) { + } + + @Override + public boolean onSingleTapUp(final MotionEvent e) { + return false; + } + + @Override + public boolean onScroll(final MotionEvent e1, final MotionEvent e2, final float distanceX, + final float distanceY) { + return false; + } + + @Override + public void onLongPress(final MotionEvent e) { + } + + @Override + public boolean onFling(final MotionEvent e1, final MotionEvent e2, + final float velocityX, + final float velocityY) { + + if (Math.abs(velocityX) < VELOCITY_THRESHOLD && Math.abs(velocityY) < VELOCITY_THRESHOLD) + return false; + + if (Math.abs(velocityX) > Math.abs(velocityY)) { + if (velocityX >= 0) + listener.onSwipe(Direction.Right); + else + listener.onSwipe(Direction.Left); + } else { + if (velocityY >= 0) + listener.onSwipe(Direction.Down); + else + listener.onSwipe(Direction.Up); + } + + return true; + } + }); + + interface IGestureListener { + void onSwipe(Direction direction); + } +} diff --git a/app/src/main/java/eu/faircode/email/DaoMessage.java b/app/src/main/java/eu/faircode/email/DaoMessage.java index c73053b9..5904e743 100644 --- a/app/src/main/java/eu/faircode/email/DaoMessage.java +++ b/app/src/main/java/eu/faircode/email/DaoMessage.java @@ -160,6 +160,23 @@ public interface DaoMessage { " ORDER BY message.received") LiveData> liveUnseenUnified(); + @Query("SELECT message.*" + + ", account.name AS accountName, account.color AS accountColor" + + ", folder.name as folderName, folder.type as folderType" + + ", (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 related" + + " JOIN message ON message.folder = related.folder" + + " JOIN account ON account.id = message.account" + + " JOIN folder ON folder.id = message.folder" + + " WHERE related.id = :id" + + " ORDER BY" + + " CASE WHEN :next OR message.sent IS NULL THEN message.sent ELSE -message.sent END, " + + " CASE WHEN :next OR message.received IS NULL THEN message.received ELSE -message.received END" + + " LIMIT 1") + TupleMessageEx getMessage(long id, boolean next); + @Query("SELECT uid FROM message" + " WHERE folder = :folder" + " AND received >= :received" + diff --git a/app/src/main/java/eu/faircode/email/FragmentMessage.java b/app/src/main/java/eu/faircode/email/FragmentMessage.java index bbaf9a77..16c4dff5 100644 --- a/app/src/main/java/eu/faircode/email/FragmentMessage.java +++ b/app/src/main/java/eu/faircode/email/FragmentMessage.java @@ -100,7 +100,7 @@ import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.RecyclerView; public class FragmentMessage extends FragmentEx { - private ViewGroup view; + private ConstraintLayoutTouch view; private View vwAnswerAnchor; private ImageView ivFlagged; private ImageView ivAvatar; @@ -157,7 +157,7 @@ public class FragmentMessage extends FragmentEx { @Override @Nullable public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) { - view = (ViewGroup) inflater.inflate(R.layout.fragment_message, container, false); + view = (ConstraintLayoutTouch) inflater.inflate(R.layout.fragment_message, container, false); final SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getContext()); debug = prefs.getBoolean("debug", false); @@ -405,6 +405,38 @@ public class FragmentMessage extends FragmentEx { } }); + view.setGestureListener(new ConstraintLayoutTouch.IGestureListener() { + @Override + public void onSwipe(ConstraintLayoutTouch.Direction direction) { + if (message == null) + return; + + Bundle args = new Bundle(); + args.putLong("id", message.id); + args.putBoolean("next", + direction == ConstraintLayoutTouch.Direction.Down || + direction == ConstraintLayoutTouch.Direction.Right); + new SimpleTask() { + @Override + protected TupleMessageEx onLoad(Context context, Bundle args) throws Throwable { + long id = args.getLong("id"); + boolean next = args.getBoolean("next"); + return DB.getInstance(context).message().getMessage(id, next); + } + + @Override + protected void onLoaded(Bundle args, TupleMessageEx message) { + if (message != null) { + LocalBroadcastManager lbm = LocalBroadcastManager.getInstance(getContext()); + lbm.sendBroadcast( + new Intent(ActivityView.ACTION_VIEW_MESSAGE) + .putExtra("message", message)); + } + } + }.load(FragmentMessage.this, args); + } + }); + // Initialize grpHeader.setVisibility(View.GONE); grpAddresses.setVisibility(View.GONE); diff --git a/app/src/main/res/layout/fragment_message.xml b/app/src/main/res/layout/fragment_message.xml index 6d04908e..c8938ebf 100644 --- a/app/src/main/res/layout/fragment_message.xml +++ b/app/src/main/res/layout/fragment_message.xml @@ -1,5 +1,5 @@ - - +