account: add device name edition

Change the device list:
* add "this device" indication
* add dialog to rename our device
* minor bug fix in revocation dialog:
  getDialog() is always null in onCreateDialog()

Change-Id: I8e5b7256268bf4018cba135402e6f6de00b745cc
Tuleap: #1494
diff --git a/ring-android/app/src/main/java/cx/ring/account/ConfirmRevocationDialog.java b/ring-android/app/src/main/java/cx/ring/account/ConfirmRevocationDialog.java
index 7eb5355..5b97ac0 100644
--- a/ring-android/app/src/main/java/cx/ring/account/ConfirmRevocationDialog.java
+++ b/ring-android/app/src/main/java/cx/ring/account/ConfirmRevocationDialog.java
@@ -2,6 +2,7 @@
  *  Copyright (C) 2017 Savoir-faire Linux Inc.
  *
  *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *          Adrien Beraud <adrien.beraud@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -73,12 +74,6 @@
 
         mDeviceId = getArguments().getString(DEVICEID_KEY);
 
-        AlertDialog dialog = (AlertDialog) getDialog();
-        if (dialog != null) {
-            dialog.setView(view);
-            dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
-        }
-
         final AlertDialog result = new AlertDialog.Builder(getActivity())
                 .setView(view)
                 .setMessage(getString(R.string.revoke_device_message, mDeviceId))
@@ -106,7 +101,7 @@
                 });
             }
         });
-
+        result.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
         return result;
     }
 
diff --git a/ring-android/app/src/main/java/cx/ring/account/DeviceAdapter.java b/ring-android/app/src/main/java/cx/ring/account/DeviceAdapter.java
index b51b78a..0eb61ce 100644
--- a/ring-android/app/src/main/java/cx/ring/account/DeviceAdapter.java
+++ b/ring-android/app/src/main/java/cx/ring/account/DeviceAdapter.java
@@ -40,6 +40,7 @@
 
     public interface DeviceRevocationListener {
         void onDeviceRevocationAsked(String deviceId);
+        void onDeviceRename();
     }
 
     public DeviceAdapter(Context c, Map<String, String> devices, String currentDeviceId,
@@ -81,17 +82,29 @@
         if (view == null) {
             view = LayoutInflater.from(mContext).inflate(R.layout.item_device, parent, false);
         }
+        boolean isCurrentDevice = mDevices.get(i).getKey().contentEquals(mCurrentDeviceId);
 
         TextView devId = (TextView) view.findViewById(R.id.txt_device_id);
         devId.setText(mDevices.get(i).getKey());
 
         TextView devName = (TextView) view.findViewById(R.id.txt_device_label);
         devName.setText(mDevices.get(i).getValue());
-
         ImageButton revokeButton = (ImageButton) view.findViewById(R.id.revoke_button);
-
-        boolean isCurrentDevice = mDevices.get(i).getKey().contentEquals(mCurrentDeviceId);
-        revokeButton.setVisibility(isCurrentDevice ? View.INVISIBLE : View.VISIBLE);
+        ImageButton editButton = (ImageButton) view.findViewById(R.id.rename_button);
+        revokeButton.setVisibility(isCurrentDevice ? View.GONE : View.VISIBLE);
+        editButton.setVisibility(isCurrentDevice ? View.VISIBLE : View.GONE);
+        TextView thisDeviceText = (TextView) view.findViewById(R.id.txt_device_thisflag);
+        thisDeviceText.setVisibility(isCurrentDevice ? View.VISIBLE : View.GONE);
+        if (isCurrentDevice) {
+            editButton.setOnClickListener(new View.OnClickListener() {
+                @Override
+                public void onClick(View view) {
+                    if (mListener != null) {
+                        mListener.onDeviceRename();
+                    }
+                }
+            });
+        }
 
         revokeButton.setOnClickListener(new View.OnClickListener() {
             @Override
diff --git a/ring-android/app/src/main/java/cx/ring/account/RenameDeviceDialog.java b/ring-android/app/src/main/java/cx/ring/account/RenameDeviceDialog.java
new file mode 100644
index 0000000..db849cf
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/account/RenameDeviceDialog.java
@@ -0,0 +1,130 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Adrien Beraud <adrien.beraud@savoirfairelinux.com>
+ *
+ *  This program 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.
+ *
+ *  This program 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 this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+package cx.ring.account;
+
+import android.app.AlertDialog;
+import android.app.Dialog;
+import android.app.DialogFragment;
+import android.content.DialogInterface;
+import android.os.Bundle;
+import android.support.design.widget.TextInputLayout;
+import android.view.KeyEvent;
+import android.view.View;
+import android.view.WindowManager;
+import android.view.inputmethod.EditorInfo;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import butterknife.BindString;
+import butterknife.BindView;
+import butterknife.ButterKnife;
+import butterknife.OnEditorAction;
+import cx.ring.R;
+
+public class RenameDeviceDialog extends DialogFragment {
+    static final String TAG = RenameDeviceDialog.class.getSimpleName();
+    public static final String DEVICENAME_KEY = "devicename_key";
+
+    public interface RenameDeviceListener {
+        void onDeviceRename(String newName);
+    }
+
+    @BindView(R.id.ring_device_name_txt_box)
+    public TextInputLayout mDeviceNameTxtBox;
+
+    @BindString(R.string.account_device_name_empty)
+    protected String mPromptDeviceName;
+
+    @BindView(R.id.ring_device_name_txt)
+    public EditText mDeviceNameTxt;
+
+    private RenameDeviceListener mListener = null;
+
+    public void setListener(RenameDeviceListener listener) {
+        mListener = listener;
+    }
+
+    @Override
+    public Dialog onCreateDialog(Bundle savedInstanceState) {
+        View view = getActivity().getLayoutInflater().inflate(R.layout.dialog_device_rename, null);
+        ButterKnife.bind(this, view);
+
+        mDeviceNameTxt.setText(getArguments().getString(DEVICENAME_KEY));
+
+        final AlertDialog dialog = new AlertDialog.Builder(getActivity())
+                .setView(view)
+                .setTitle(R.string.rename_device_title)
+                .setMessage(R.string.rename_device_message)
+                .setPositiveButton(R.string.rename_device_button, null)
+                .setNegativeButton(android.R.string.cancel, null)
+                .create();
+        dialog.setOnShowListener(new DialogInterface.OnShowListener() {
+            @Override
+            public void onShow(final DialogInterface dialog) {
+                Button button = ((AlertDialog) dialog).getButton(AlertDialog.BUTTON_POSITIVE);
+                button.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View view) {
+                        if (validate()) {
+                            dialog.dismiss();
+                        }
+                    }
+                });
+            }
+        });
+        dialog.getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_VISIBLE);
+        return dialog;
+    }
+
+    public boolean checkInput(String input) {
+        if (input.isEmpty()) {
+            mDeviceNameTxtBox.setErrorEnabled(true);
+            mDeviceNameTxtBox.setError(mPromptDeviceName);
+            return false;
+        } else {
+            mDeviceNameTxtBox.setErrorEnabled(false);
+            mDeviceNameTxtBox.setError(null);
+        }
+        return true;
+    }
+
+    boolean validate() {
+        String input = mDeviceNameTxt.getText().toString().trim();
+        if (checkInput(input) && mListener != null) {
+            mListener.onDeviceRename(input);
+            return true;
+        }
+        return false;
+    }
+
+    @OnEditorAction({R.id.ring_device_name_txt})
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+        if (v == mDeviceNameTxt) {
+            if (actionId == EditorInfo.IME_ACTION_DONE) {
+                boolean validationResult = validate();
+                if (validationResult) {
+                    getDialog().dismiss();
+                }
+                return validationResult;
+            }
+        }
+        return false;
+    }
+}
diff --git a/ring-android/app/src/main/java/cx/ring/account/RingAccountSummaryFragment.java b/ring-android/app/src/main/java/cx/ring/account/RingAccountSummaryFragment.java
index ab2e0e5..df5af32 100644
--- a/ring-android/app/src/main/java/cx/ring/account/RingAccountSummaryFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/account/RingAccountSummaryFragment.java
@@ -67,6 +67,7 @@
 
 public class RingAccountSummaryFragment extends Fragment implements BackHandlerInterface,
         RegisterNameDialog.RegisterNameDialogListener,
+        RenameDeviceDialog.RenameDeviceListener,
         DeviceAdapter.DeviceRevocationListener,
         ConfirmRevocationDialog.ConfirmRevocationListener,
         RingAccountSummaryView {
@@ -478,4 +479,21 @@
         dialog.setListener(this);
         dialog.show(getFragmentManager(), FRAGMENT_DIALOG_REVOCATION);
     }
+
+    @Override
+    public void onDeviceRename() {
+        final String dev_name = mRingAccountSummaryPresenter.getDeviceName();
+        RenameDeviceDialog dialog = new RenameDeviceDialog();
+        Bundle args = new Bundle();
+        args.putString(RenameDeviceDialog.DEVICENAME_KEY, dev_name);
+        dialog.setArguments(args);
+        dialog.setListener(this);
+        dialog.show(getFragmentManager(), TAG);
+    }
+
+    @Override
+    public void onDeviceRename(String newName) {
+        Log.d(TAG, "onDeviceRename " + mRingAccountSummaryPresenter.getDeviceName() + " -> " + newName);
+        mRingAccountSummaryPresenter.renameDevice(newName);
+    }
 }
diff --git a/ring-android/app/src/main/res/layout/dialog_device_rename.xml b/ring-android/app/src/main/res/layout/dialog_device_rename.xml
new file mode 100644
index 0000000..b7a04a3
--- /dev/null
+++ b/ring-android/app/src/main/res/layout/dialog_device_rename.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:orientation="vertical"
+    android:paddingTop="16dp">
+
+    <android.support.design.widget.TextInputLayout
+        android:id="@+id/ring_device_name_txt_box"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_marginBottom="16dp"
+        android:layout_marginLeft="12dp"
+        android:layout_marginRight="12dp">
+
+        <android.support.design.widget.TextInputEditText
+            android:id="@+id/ring_device_name_txt"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:hint="@string/account_rename_device_hint"
+            android:imeOptions="actionDone"
+            android:inputType="textCapWords"
+            android:lines="1"
+            android:maxLines="1" />
+    </android.support.design.widget.TextInputLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/frag_device_list.xml b/ring-android/app/src/main/res/layout/frag_device_list.xml
index 286613f..4672b3d 100644
--- a/ring-android/app/src/main/res/layout/frag_device_list.xml
+++ b/ring-android/app/src/main/res/layout/frag_device_list.xml
@@ -92,14 +92,14 @@
                     style="@style/Subheader"
                     android:layout_width="match_parent"
                     android:layout_height="wrap_content"
-                    android:ellipsize="end"
+                    android:ellipsize="middle"
                     android:gravity="center_vertical"
                     android:lines="1"
                     android:paddingBottom="8dp"
                     android:paddingLeft="16dp"
                     android:paddingRight="16dp"
                     android:paddingTop="8dp"
-                    android:textIsSelectable="false"
+                    android:singleLine="true"
                     android:textStyle="bold"
                     tools:text="ring:8F29045378ACA68F2ACA2346078ACA68F2ACA290" />
 
@@ -189,6 +189,7 @@
                         android:paddingStart="16dp"
                         android:paddingTop="4dp"
                         android:textAlignment="viewStart"
+                        android:textIsSelectable="true"
                         tools:text="blockchain_name" />
 
                 </LinearLayout>
@@ -241,8 +242,8 @@
     </ScrollView>
 
     <include
-        layout="@layout/add_new_device_layout"
         android:id="@+id/add_new_device"
+        layout="@layout/add_new_device_layout"
         android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true" />
diff --git a/ring-android/app/src/main/res/layout/item_account.xml b/ring-android/app/src/main/res/layout/item_account.xml
index 5d5480a..f51179a 100644
--- a/ring-android/app/src/main/res/layout/item_account.xml
+++ b/ring-android/app/src/main/res/layout/item_account.xml
@@ -41,7 +41,8 @@
         android:layout_toRightOf="@+id/account_photo"
         android:layout_toStartOf="@+id/error_indicator"
         android:ellipsize="end"
-        android:textAppearance="@style/ListPrimary" />
+        android:textAppearance="@style/ListPrimary"
+        tools:text="Ring account" />
 
     <TextView
         android:id="@+id/account_host"
@@ -57,14 +58,14 @@
         android:ellipsize="end"
         android:maxLines="1"
         android:singleLine="true"
-        android:textAppearance="@style/ListSecondary" />
+        android:textAppearance="@style/ListSecondary"
+        tools:text="ring:b982672502b9f1236a68353d74734cb82f9d1fab" />
 
     <android.support.v7.widget.AppCompatImageView
         android:id="@+id/error_indicator"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
         android:layout_alignParentEnd="true"
-        android:layout_alignParentRight="false"
         android:layout_centerVertical="true"
         android:layout_marginLeft="16dp"
         android:layout_marginStart="16dp"
@@ -72,6 +73,7 @@
         android:focusable="false"
         android:focusableInTouchMode="false"
         android:src="@drawable/ic_error_white"
-        android:tint="@android:color/holo_red_light" />
+        android:tint="@android:color/holo_red_light"
+        android:layout_alignParentRight="true" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/item_device.xml b/ring-android/app/src/main/res/layout/item_device.xml
index e9b68d1..0027516 100644
--- a/ring-android/app/src/main/res/layout/item_device.xml
+++ b/ring-android/app/src/main/res/layout/item_device.xml
@@ -41,8 +41,12 @@
         android:layout_centerVertical="true"
         android:layout_marginLeft="56dp"
         android:layout_marginStart="56dp"
+        android:layout_toLeftOf="@+id/txt_device_thisflag"
+        android:layout_toStartOf="@+id/txt_device_thisflag"
+        android:ellipsize="end"
+        android:lines="1"
         android:textAppearance="@style/ListPrimary"
-        tools:text="8E24CCF4" />
+        tools:text="My device" />
 
     <TextView
         android:id="@+id/txt_device_id"
@@ -51,13 +55,39 @@
         android:layout_alignLeft="@id/txt_device_label"
         android:layout_alignStart="@+id/txt_device_label"
         android:layout_below="@id/txt_device_label"
-        android:layout_toLeftOf="@+id/revoke_button"
-        android:layout_toStartOf="@+id/revoke_button"
+        android:layout_toLeftOf="@+id/rename_button"
+        android:layout_toStartOf="@+id/rename_button"
         android:ellipsize="middle"
         android:maxLines="1"
-        android:maxWidth="150dp"
         android:textAppearance="@style/TextAppearance.AppCompat.Caption"
-        tools:text="e3806a4963993ed1e8adc5c0ed9809c354dfc872" />
+        tools:text="b982672502b9f1236a68353d74734cb82f9d1fab" />
+
+    <TextView
+        android:id="@+id/txt_device_thisflag"
+        style="@style/TextAppearance.AppCompat.Small"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignBaseline="@+id/txt_device_label"
+        android:layout_marginLeft="8dp"
+        android:layout_marginStart="8dp"
+        android:layout_toLeftOf="@+id/rename_button"
+        android:layout_toStartOf="@+id/rename_button"
+        android:text="@string/account_device_this_indicator"
+        android:textStyle="italic" />
+
+    <ImageButton
+        android:id="@+id/rename_button"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignWithParentIfMissing="true"
+        android:layout_centerVertical="true"
+        android:layout_toLeftOf="@+id/revoke_button"
+        android:layout_toStartOf="@+id/revoke_button"
+        android:background="?selectableItemBackgroundBorderless"
+        android:contentDescription="@string/account_device_revoke"
+        android:padding="8dp"
+        android:tint="@color/black"
+        app:srcCompat="@drawable/ic_action_edit" />
 
     <ImageButton
         android:id="@+id/revoke_button"
diff --git a/ring-android/app/src/main/res/values/strings_account.xml b/ring-android/app/src/main/res/values/strings_account.xml
index 647d338..01993b6 100644
--- a/ring-android/app/src/main/res/values/strings_account.xml
+++ b/ring-android/app/src/main/res/values/strings_account.xml
@@ -231,5 +231,11 @@
     <string name="revoke_device_message">Are you sure you want to revoke %1$s ?</string>
     <string name="revoke_device_wait_title">Please wait…</string>
     <string name="revoke_device_wait_message">Revoking device</string>
+    <string name="rename_device_title">Rename this device</string>
+    <string name="rename_device_message">Choose a new name to identify this device in your Ring account</string>
+    <string name="rename_device_button">Rename device</string>
+    <string name="account_rename_device_hint">Choose new device name</string>
+    <string name="account_device_name_empty">Device name can\'t be empty</string>
+    <string name="account_device_this_indicator">this device</string>
 
 </resources>