call: hide preview feature

Change-Id: I8f22a67840d5f7ec4649a248894e86562af89f17
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
index 02008e0..d9272c2 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
@@ -46,6 +46,7 @@
 import android.text.Editable;
 import android.text.TextWatcher;
 import android.util.Rational;
+import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.Menu;
 import android.view.MenuInflater;
@@ -60,6 +61,7 @@
 import android.view.WindowManager;
 import android.view.animation.DecelerateInterpolator;
 import android.view.inputmethod.InputMethodManager;
+import android.widget.FrameLayout;
 import android.widget.RelativeLayout;
 import android.widget.Toast;
 
@@ -93,7 +95,6 @@
 import cx.ring.client.ConversationSelectionActivity;
 import cx.ring.client.HomeActivity;
 import cx.ring.databinding.FragCallBinding;
-import cx.ring.dependencyinjection.JamiInjectionComponent;
 import cx.ring.model.CallContact;
 import cx.ring.model.SipCall;
 import cx.ring.mvp.BaseSupportFragment;
@@ -152,6 +153,9 @@
     private PointF previewDrag = null;
     private final ValueAnimator previewSnapAnimation = new ValueAnimator();
     private final int[] previewMargins = new int[4];
+    private float previewHiddenState = 0;
+    private enum PreviewPosition {LEFT, RIGHT}
+    private PreviewPosition previewPosition = PreviewPosition.RIGHT;
 
     @Inject
     DeviceRuntimeService mDeviceRuntimeService;
@@ -215,8 +219,7 @@
             if (action != null) {
                 if (action.equals(ACTION_PLACE_CALL)) {
                     prepareCall(false);
-                }
-                else if (action.equals(ACTION_GET_CALL) || action.equals(CallActivity.ACTION_CALL_ACCEPT)) {
+                } else if (action.equals(ACTION_GET_CALL) || action.equals(CallActivity.ACTION_CALL_ACCEPT)) {
                     presenter.initIncomingCall(getArguments().getString(KEY_CONF_ID), action.equals(ACTION_GET_CALL));
                 }
             }
@@ -320,6 +323,14 @@
         }
     };
 
+    /**
+     * @param hiddenState 0.f if fully shown, 1.f if fully hidden.
+     */
+    private void setPreviewDragHiddenState(float hiddenState) {
+        binding.previewSurface.setAlpha(1.f - (3 * hiddenState / 4));
+        binding.previewHandle.setAlpha(hiddenState);
+    }
+
     @SuppressLint("ClickableViewAccessibility")
     @Override
     public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
@@ -405,59 +416,88 @@
         previewSnapAnimation.setInterpolator(new DecelerateInterpolator());
         previewSnapAnimation.addUpdateListener(animation -> {
             RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) binding.previewContainer.getLayoutParams();
-            float f = margin * animation.getAnimatedFraction();
             float r = 1.f - animation.getAnimatedFraction();
+            float hideMargin = 0.f;
+            float targetHiddenState = 0.f;
+            if (previewHiddenState != 0.f) {
+                targetHiddenState = 1.f;
+                float v = binding.previewContainer.getWidth() * 0.85f * animation.getAnimatedFraction();
+                hideMargin = previewPosition == PreviewPosition.RIGHT ? v : -v;
+            }
+            setPreviewDragHiddenState(previewHiddenState * r  + targetHiddenState * animation.getAnimatedFraction());
+
+            float f = margin * animation.getAnimatedFraction();
             params.setMargins(
-                    (int)(previewMargins[0] * r + f),
+                    (int)(previewMargins[0] * r + f + hideMargin),
                     (int)(previewMargins[1] * r + f),
-                    (int)(previewMargins[2] * r + f),
+                    (int)(previewMargins[2] * r + f - hideMargin),
                     (int)(previewMargins[3] * r + f));
             binding.previewContainer.setLayoutParams(params);
         });
 
         binding.previewContainer.setOnTouchListener((v, event) -> {
             int action = event.getActionMasked();
+            RelativeLayout parent = (RelativeLayout) v.getParent();
+            RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
+
             if (action == MotionEvent.ACTION_DOWN) {
                 previewSnapAnimation.cancel();
                 previewDrag = new PointF(event.getX(), event.getY());
                 v.setElevation(v.getContext().getResources().getDimension(R.dimen.call_preview_elevation_dragged));
-                RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
                 params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                 params.removeRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
                 params.addRule(RelativeLayout.ALIGN_PARENT_TOP);
                 params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
-                params.setMargins((int)v.getX(), (int)v.getY(), 0, 0);
+                params.setMargins((int) v.getX(), (int) v.getY(), parent.getWidth() - ((int) v.getX() + v.getWidth()), parent.getHeight() - ((int) v.getY() + v.getHeight()));
                 v.setLayoutParams(params);
                 return true;
             } else if (action == MotionEvent.ACTION_MOVE) {
                 if (previewDrag != null) {
-                    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
-                    RelativeLayout parent = (RelativeLayout) v.getParent();
+                    int currentXPosition = params.leftMargin + (int) (event.getX() - previewDrag.x);
+                    int currentYPosition = params.topMargin + (int) (event.getY() - previewDrag.y);
                     params.setMargins(
-                            Math.min(params.leftMargin + (int) (event.getX() - previewDrag.x), parent.getWidth() - v.getWidth() - (int)margin),
-                            Math.min(params.topMargin + (int) (event.getY() - previewDrag.y), parent.getHeight() - v.getHeight() - (int)margin),
-                            0, 0);
+                            currentXPosition,
+                            currentYPosition,
+                            -((currentXPosition + v.getWidth()) - (int) event.getX()),
+                            -((currentYPosition + v.getHeight()) - (int) event.getY()));
                     v.setLayoutParams(params);
+
+                    float outPosition = binding.previewContainer.getWidth() * 0.85f;
+                    float drapOut = 0.f;
+                    if (currentXPosition < 0) {
+                        drapOut = Math.min(1.f, -currentXPosition / outPosition);
+                    } else if (currentXPosition + v.getWidth() > parent.getWidth()) {
+                        drapOut = Math.min(1.f, (currentXPosition + v.getWidth() - parent.getWidth()) / outPosition);
+                    }
+                    setPreviewDragHiddenState(drapOut);
                     return true;
                 }
                 return false;
             } else if (action == MotionEvent.ACTION_UP) {
                 if (previewDrag != null) {
+                    int currentXPosition = params.leftMargin + (int) (event.getX() - previewDrag.x);
+
                     previewSnapAnimation.cancel();
                     previewDrag = null;
                     v.setElevation(v.getContext().getResources().getDimension(R.dimen.call_preview_elevation));
-                    RelativeLayout parent = (RelativeLayout) v.getParent();
-                    RelativeLayout.LayoutParams params = (RelativeLayout.LayoutParams) v.getLayoutParams();
                     int ml = 0, mr = 0, mt = 0, mb = 0;
+
+                    FrameLayout.LayoutParams hp = (FrameLayout.LayoutParams) binding.previewHandle.getLayoutParams();
                     if (params.leftMargin + (v.getWidth() / 2) > parent.getWidth() / 2) {
                         params.removeRule(RelativeLayout.ALIGN_PARENT_LEFT);
                         params.addRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                         mr = (int) (parent.getWidth() - v.getWidth() - v.getX());
+                        previewPosition = PreviewPosition.RIGHT;
+                        hp.gravity = Gravity.CENTER_VERTICAL | Gravity.LEFT;
                     } else {
                         params.removeRule(RelativeLayout.ALIGN_PARENT_RIGHT);
                         params.addRule(RelativeLayout.ALIGN_PARENT_LEFT);
                         ml = (int) v.getX();
+                        previewPosition = PreviewPosition.LEFT;
+                        hp.gravity = Gravity.CENTER_VERTICAL | Gravity.RIGHT;
                     }
+                    binding.previewHandle.setLayoutParams(hp);
+
                     if (params.topMargin + (v.getHeight() / 2) > parent.getHeight() / 2) {
                         params.removeRule(RelativeLayout.ALIGN_PARENT_TOP);
                         params.addRule(RelativeLayout.ALIGN_PARENT_BOTTOM);
@@ -473,6 +513,15 @@
                     previewMargins[3] = mb;
                     params.setMargins(ml, mt, mr, mb);
                     v.setLayoutParams(params);
+
+                    float outPosition = binding.previewContainer.getWidth() * 0.85f;
+                    previewHiddenState = currentXPosition < 0
+                            ? Math.min(1.f, -currentXPosition / outPosition)
+                            : ((currentXPosition + v.getWidth() > parent.getWidth())
+                                ? Math.min(1.f, (currentXPosition + v.getWidth() - parent.getWidth()) / outPosition)
+                                : 0.f);
+                    setPreviewDragHiddenState(previewHiddenState);
+
                     previewSnapAnimation.start();
                     return true;
                 }
@@ -676,7 +725,7 @@
 
     @Override
     public void updateTime(final long duration) {
-        if (binding.callStatusTxt != null) {
+        if (binding != null) {
             if (duration == 0)
                 binding.callStatusTxt.setText(null);
             else
@@ -767,7 +816,7 @@
 
     @Override
     public void initMenu(boolean isSpeakerOn, boolean displayFlip, boolean canDial, boolean onGoingCall) {
-        if (binding.callCameraFlipBtn != null) {
+        if (binding != null) {
             binding.callCameraFlipBtn.setVisibility(displayFlip ? View.VISIBLE : View.GONE);
         }
         if (dialPadBtn != null) {
diff --git a/ring-android/app/src/main/java/cx/ring/views/AutoFitTextureView.java b/ring-android/app/src/main/java/cx/ring/views/AutoFitTextureView.java
index de46975..be505d2 100644
--- a/ring-android/app/src/main/java/cx/ring/views/AutoFitTextureView.java
+++ b/ring-android/app/src/main/java/cx/ring/views/AutoFitTextureView.java
@@ -1,11 +1,16 @@
 package cx.ring.views;
 
 import android.content.Context;
+import android.graphics.Rect;
 import android.util.AttributeSet;
-import android.util.Log;
 import android.util.TypedValue;
 import android.view.TextureView;
 
+import androidx.core.view.ViewCompat;
+
+import java.util.Collections;
+import java.util.List;
+
 /**
  * A {@link TextureView} that can be adjusted to a specified aspect ratio.
  */
@@ -14,6 +19,7 @@
     private int mRatioWidth = 720;
     private int mRatioHeight = 1280;
     private final int mSize;
+    private final List<Rect> mBounds = Collections.singletonList(new Rect());
 
     public AutoFitTextureView(Context context) {
         this(context, null);
@@ -28,6 +34,13 @@
         mSize = Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 192, context.getResources().getDisplayMetrics()));
     }
 
+    @Override
+    protected void onLayout(boolean changed, int left, int top, int right, int bottom) {
+        super.onLayout(changed, left, top, right, bottom);
+        mBounds.get(0).set(left, top, right, bottom);
+        ViewCompat.setSystemGestureExclusionRects(this, mBounds);
+    }
+
     /**
      * Sets the aspect ratio for this view. The size of the view will be measured based on the ratio
      * calculated from the parameters. Note that the actual sizes of parameters don't matter, that
diff --git a/ring-android/app/src/main/res/drawable/ic_chevron_left_24px.xml b/ring-android/app/src/main/res/drawable/ic_chevron_left_24px.xml
new file mode 100644
index 0000000..272e1fb
--- /dev/null
+++ b/ring-android/app/src/main/res/drawable/ic_chevron_left_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M15.41,7.41L14,6l-6,6 6,6 1.41,-1.41L10.83,12z"/>
+</vector>
diff --git a/ring-android/app/src/main/res/drawable/ic_chevron_right_24px.xml b/ring-android/app/src/main/res/drawable/ic_chevron_right_24px.xml
new file mode 100644
index 0000000..70a53ea
--- /dev/null
+++ b/ring-android/app/src/main/res/drawable/ic_chevron_right_24px.xml
@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+  <path
+      android:fillColor="#FF000000"
+      android:pathData="M10,6L8.59,7.41 13.17,12l-4.58,4.59L10,18l6,-6z"/>
+</vector>
diff --git a/ring-android/app/src/main/res/drawable/ic_preview_handle.xml b/ring-android/app/src/main/res/drawable/ic_preview_handle.xml
new file mode 100644
index 0000000..d6a5af0
--- /dev/null
+++ b/ring-android/app/src/main/res/drawable/ic_preview_handle.xml
@@ -0,0 +1,10 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="3dp"
+    android:height="60dp"
+    android:viewportWidth="1.5272485"
+    android:viewportHeight="48.024227">
+  <path
+      android:pathData="M0.7636,-0L0.7636,-0A0.8484,0.7636 90,0 1,1.5272 0.8484L1.5272,47.1759A0.8484,0.7636 90,0 1,0.7636 48.0242L0.7636,48.0242A0.8484,0.7636 90,0 1,0 47.1759L0,0.8484A0.8484,0.7636 90,0 1,0.7636 -0z"
+      android:strokeWidth="0.0746897"
+      android:fillColor="#80ffffff"/>
+</vector>
diff --git a/ring-android/app/src/main/res/drawable/show_preview.xml b/ring-android/app/src/main/res/drawable/show_preview.xml
new file mode 100644
index 0000000..db8a3be
--- /dev/null
+++ b/ring-android/app/src/main/res/drawable/show_preview.xml
@@ -0,0 +1,18 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="35dp"
+    android:height="207dp"
+    android:viewportWidth="35"
+    android:viewportHeight="207">
+  <path
+      android:pathData="M4.082,0.001L30.917,0.001A4.783,4.083 90,0 1,34.999 4.783L34.999,202.216A4.783,4.083 90,0 1,30.917 206.999L4.082,206.999A4.783,4.083 90,0 1,-0.001 202.216L-0.001,4.783A4.783,4.083 90,0 1,4.082 0.001z"
+      android:strokeWidth="0.210926"
+      android:fillColor="#c8beb7"/>
+  <path
+      android:pathData="M5.329,79.488L5.329,79.488A0.848,0.764 90,0 1,6.092 80.336L6.092,126.664A0.848,0.764 90,0 1,5.329 127.512L5.329,127.512A0.848,0.764 90,0 1,4.565 126.664L4.565,80.336A0.848,0.764 90,0 1,5.329 79.488z"
+      android:strokeWidth="0.0746897"
+      android:fillColor="#241c1c"/>
+  <path
+      android:pathData="M29.738,79.488L29.738,79.488A0.905,0.764 90,0 1,30.501 80.393L30.501,126.606A0.905,0.764 90,0 1,29.738 127.512L29.738,127.512A0.905,0.764 90,0 1,28.974 126.606L28.974,80.393A0.905,0.764 90,0 1,29.738 79.488z"
+      android:strokeWidth="0.0746894"
+      android:fillColor="#241c1c"/>
+</vector>
diff --git a/ring-android/app/src/main/res/drawable/transparent_round_grey.xml b/ring-android/app/src/main/res/drawable/transparent_round_grey.xml
new file mode 100644
index 0000000..0a557ee
--- /dev/null
+++ b/ring-android/app/src/main/res/drawable/transparent_round_grey.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="rectangle">
+    <solid android:color="#D84F4F4F" />
+</shape>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/frag_call.xml b/ring-android/app/src/main/res/layout/frag_call.xml
index d738c9e..dff201d 100644
--- a/ring-android/app/src/main/res/layout/frag_call.xml
+++ b/ring-android/app/src/main/res/layout/frag_call.xml
@@ -60,14 +60,25 @@
                 android:visibility="gone"
                 app:cardCornerRadius="16dp"
                 app:cardPreventCornerOverlap="false"
-                tools:visibility="visible">
+                tools:visibility="visible"
+                app:cardBackgroundColor="@color/black">
 
                 <cx.ring.views.AutoFitTextureView
                     android:id="@+id/preview_surface"
                     android:layout_width="wrap_content"
                     android:layout_height="wrap_content"
+                    android:visibility="visible"/>
+
+                <ImageView
+                    android:id="@+id/preview_handle"
+                    android:layout_width="wrap_content"
+                    android:layout_height="wrap_content"
+                    android:layout_gravity="left|center_vertical"
+                    android:layout_marginHorizontal="@dimen/call_preview_margin_handle"
                     android:visibility="visible"
-                    tools:visibility="visible" />
+                    android:alpha="0"
+                    app:srcCompat="@drawable/ic_preview_handle" />
+
             </androidx.cardview.widget.CardView>
 
         </RelativeLayout>
@@ -85,7 +96,7 @@
                 android:layout_height="wrap_content"
                 android:layout_centerInParent="true"
                 android:orientation="vertical"
-                android:visibility="visible"
+                android:visibility="gone"
                 app:flexDirection="column"
                 app:flexWrap="wrap"
                 tools:visibility="visible">
@@ -158,8 +169,7 @@
                     <LinearLayout
                         android:layout_width="wrap_content"
                         android:layout_height="wrap_content"
-                        android:orientation="horizontal"
-                        tools:visibility="visible">
+                        android:orientation="horizontal">
 
                         <com.google.android.material.floatingactionbutton.FloatingActionButton
                             android:id="@+id/call_refuse_btn"
@@ -169,14 +179,15 @@
                             android:contentDescription="@string/action_call_decline"
                             android:onClick="@{() -> presenter.refuseClicked()}"
                             android:tint="@color/white"
-                            tools:visibility="visible"
+                            android:visibility="gone"
                             app:backgroundTint="@color/colorError"
                             app:elevation="6dp"
                             app:fabSize="normal"
                             app:pressedTranslationZ="12dp"
                             app:rippleColor="@android:color/white"
                             app:srcCompat="@drawable/baseline_call_end_24"
-                            app:useCompatPadding="true" />
+                            app:useCompatPadding="true"
+                            tools:visibility="visible" />
 
                         <com.google.android.material.floatingactionbutton.FloatingActionButton
                             android:id="@+id/call_accept_btn"
@@ -185,14 +196,15 @@
                             android:layout_margin="16dp"
                             android:contentDescription="@string/action_call_accept"
                             android:onClick="@{() -> presenter.acceptClicked()}"
-                            android:visibility="visible"
+                            android:visibility="gone"
                             app:backgroundTint="@color/green_500"
                             app:elevation="6dp"
                             app:fabSize="normal"
                             app:pressedTranslationZ="12dp"
                             app:rippleColor="@android:color/white"
                             app:srcCompat="@drawable/baseline_call_24"
-                            app:useCompatPadding="true" />
+                            app:useCompatPadding="true"
+                            tools:visibility="visible" />
                     </LinearLayout>
 
                 </LinearLayout>
@@ -276,14 +288,14 @@
             </com.google.android.flexbox.FlexboxLayout>
 
             <androidx.recyclerview.widget.RecyclerView
+                android:id="@+id/conf_control_group"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:id="@+id/conf_control_group"
-                android:layout_alignParentEnd="true"
                 android:layout_alignParentTop="true"
+                android:layout_alignParentEnd="true"
                 app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
-                tools:listitem="@layout/item_conference_participant"
-                tools:itemCount="4" />
+                tools:itemCount="4"
+                tools:listitem="@layout/item_conference_participant" />
 
             <EditText
                 android:id="@+id/dialpad_edit_text"
@@ -313,5 +325,6 @@
                 app:useCompatPadding="true" />
 
         </RelativeLayout>
+
     </FrameLayout>
 </layout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/values/dimens.xml b/ring-android/app/src/main/res/values/dimens.xml
index 275788b..2866f91 100644
--- a/ring-android/app/src/main/res/values/dimens.xml
+++ b/ring-android/app/src/main/res/values/dimens.xml
@@ -72,6 +72,8 @@
     <dimen name="call_preview_elevation">8dp</dimen>
     <dimen name="call_preview_elevation_dragged">16dp</dimen>
     <dimen name="call_preview_margin">12dp</dimen>
+    <dimen name="call_preview_margin_big">65dp</dimen>
+    <dimen name="call_preview_margin_handle">12dp</dimen>
 
     <dimen name="wizard_button_width">340dp</dimen>
     <dimen name="wizard_button_corner_radius">12dp</dimen>
diff --git a/ring-android/app/src/main/res/values/strings.xml b/ring-android/app/src/main/res/values/strings.xml
index 68c0be4..5fb04f3 100644
--- a/ring-android/app/src/main/res/values/strings.xml
+++ b/ring-android/app/src/main/res/values/strings.xml
@@ -154,6 +154,7 @@
     <string name="write_a_message">Write a message</string>
     <string name="scan_qr">Scan QR Code</string>
     <string name="ab_action_flipcamera">Flip camera</string>
+    <string name="ab_action_hidepreview">Hide preview</string>
 
     <!-- Text messages -->
     <string name="send_message">Send message</string>