From 5f420e2b26f0da3fea065c62d3bf6d347cacbe25 Mon Sep 17 00:00:00 2001
From: Hadrien De Sousa <hadrien.desousa@savoirfairelinux.com>
Date: Wed, 17 May 2017 16:37:25 -0400
Subject: [PATCH] mvp: refactor ProfileCreationFragment

Apply MVP to ProfileCreationFragment

Tuleap: #1369
Change-Id: Id4434fb1d663d001350a7c0da51340da284d23a3
Reviewed-by: Aline Bonnet <aline.bonnet@savoirfairelinux.com>
---
 .../ProfileCreationFragment.java              | 128 ++++++++++--------
 .../account/ProfileCreationPresenter.java     |  82 +++++++++++
 .../cx/ring/account/ProfileCreationView.java  |  39 ++++++
 .../java/cx/ring/client/AccountWizard.java    |  22 +--
 .../RingInjectionComponent.java               |   2 +-
 .../services/DeviceRuntimeServiceImpl.java    |  18 +++
 .../ring/services/DeviceRuntimeService.java   |   2 +
 7 files changed, 218 insertions(+), 75 deletions(-)
 rename ring-android/app/src/main/java/cx/ring/{fragments => account}/ProfileCreationFragment.java (66%)
 create mode 100644 ring-android/app/src/main/java/cx/ring/account/ProfileCreationPresenter.java
 create mode 100644 ring-android/app/src/main/java/cx/ring/account/ProfileCreationView.java

diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ProfileCreationFragment.java b/ring-android/app/src/main/java/cx/ring/account/ProfileCreationFragment.java
similarity index 66%
rename from ring-android/app/src/main/java/cx/ring/fragments/ProfileCreationFragment.java
rename to ring-android/app/src/main/java/cx/ring/account/ProfileCreationFragment.java
index a99d06b14..1993372a6 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/ProfileCreationFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/account/ProfileCreationFragment.java
@@ -18,10 +18,10 @@
  *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  */
 
-package cx.ring.fragments;
+package cx.ring.account;
 
 import android.Manifest;
-import android.app.Fragment;
+import android.app.Activity;
 import android.content.Intent;
 import android.database.Cursor;
 import android.graphics.Bitmap;
@@ -51,12 +51,12 @@ import cx.ring.R;
 import cx.ring.adapters.ContactDetailsTask;
 import cx.ring.application.RingApplication;
 import cx.ring.client.AccountWizard;
+import cx.ring.mvp.BaseFragment;
 import cx.ring.services.DeviceRuntimeService;
 import cx.ring.utils.BitmapUtils;
 
-public class ProfileCreationFragment extends Fragment {
+public class ProfileCreationFragment extends BaseFragment<ProfileCreationPresenter> implements ProfileCreationView {
     static final String TAG = ProfileCreationFragment.class.getSimpleName();
-    private static final String[] PROFILE_PROJECTION = new String[]{ContactsContract.Profile._ID, ContactsContract.Profile.DISPLAY_NAME_PRIMARY, ContactsContract.Profile.PHOTO_ID};
     public static final int REQUEST_CODE_PHOTO = 1;
     public static final int REQUEST_CODE_GALLERY = 2;
     public static final int REQUEST_PERMISSION_CAMERA = 3;
@@ -64,31 +64,33 @@ public class ProfileCreationFragment extends Fragment {
 
     public static final String PHOTO_TAG = "Photo";
 
-    @Inject
-    DeviceRuntimeService mDeviceRuntimeService;
-
     @BindView(R.id.profile_photo)
-    ImageView mPhotoView;
+    protected ImageView mPhotoView;
 
     @BindView(R.id.user_name)
-    EditText mFullnameView;
+    protected EditText mFullnameView;
 
     @BindView(R.id.gallery)
-    ImageButton mGalleryButton;
+    protected ImageButton mGalleryButton;
 
     @BindView(R.id.camera)
-    ImageButton mCameraButton;
+    protected ImageButton mCameraButton;
 
     @BindView(R.id.next_create_account)
-    Button mNextButton;
+    protected Button mNextButton;
 
     @BindView(R.id.last_create_account)
-    Button mLastButton;
+    protected Button mLastButton;
 
     private Bitmap mSourcePhoto;
 
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
+        final View view = inflater.inflate(R.layout.frag_acc_profile_create, parent, false);
+        ButterKnife.bind(this, view);
+
+        // dependency injection
+        ((RingApplication) getActivity().getApplication()).getRingInjectionComponent().inject(this);
 
         if (savedInstanceState != null) {
             byte[] bytes = savedInstanceState.getByteArray(PHOTO_TAG);
@@ -97,13 +99,7 @@ public class ProfileCreationFragment extends Fragment {
             }
         }
 
-        final View view = inflater.inflate(R.layout.frag_acc_profile_create, parent, false);
-        ButterKnife.bind(this, view);
-
-        // dependency injection
-        ((RingApplication) getActivity().getApplication()).getRingInjectionComponent().inject(this);
-
-        initProfile();
+        presenter.initPresenter();
         if (mPhotoView.getDrawable() == null) {
             if (mSourcePhoto == null) {
                 mSourcePhoto = BitmapFactory.decodeResource(getActivity().getResources(), R.drawable.ic_contact_picture);
@@ -123,19 +119,21 @@ public class ProfileCreationFragment extends Fragment {
         }
     }
 
-    private void initProfile() {
-        //~ Checking the state of the READ_CONTACTS permission
-        if (mDeviceRuntimeService.hasContactPermission()) {
-            Cursor mProfileCursor = getActivity().getContentResolver().query(ContactsContract.Profile.CONTENT_URI, PROFILE_PROJECTION, null, null, null);
-            if (mProfileCursor != null) {
-                if (mProfileCursor.moveToFirst()) {
-                    String displayName = mProfileCursor.getString(mProfileCursor.getColumnIndex(ContactsContract.Profile.DISPLAY_NAME_PRIMARY));
-                    mFullnameView.setText(displayName);
+    @Override
+    public void onActivityResult(int requestCode, int resultCode, Intent data) {
+        switch (requestCode) {
+            case ProfileCreationFragment.REQUEST_CODE_PHOTO:
+                if (resultCode == Activity.RESULT_OK && data != null) {
+                    updatePhoto((Bitmap) data.getExtras().get("data"));
                 }
-                mProfileCursor.close();
-            }
-        } else {
-            Log.d(TAG, "READ_CONTACTS permission is not granted.");
+                break;
+            case ProfileCreationFragment.REQUEST_CODE_GALLERY:
+                if (resultCode == Activity.RESULT_OK && data != null) {
+                    updatePhoto(data.getData());
+                }
+                break;
+            default:
+                break;
         }
     }
 
@@ -150,39 +148,63 @@ public class ProfileCreationFragment extends Fragment {
 
     @OnClick(R.id.gallery)
     public void galleryClicked() {
-        boolean hasPermission = mDeviceRuntimeService.hasGalleryPermission();
-        if (hasPermission) {
-            Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
-            getActivity().startActivityForResult(intent, REQUEST_CODE_GALLERY);
-        } else {
-            ActivityCompat.requestPermissions(getActivity(),
-                    new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
-                    REQUEST_PERMISSION_READ_STORAGE);
-        }
+        presenter.galleryClick();
     }
 
     @OnClick(R.id.camera)
     public void cameraClicked() {
-        boolean hasPermission = mDeviceRuntimeService.hasVideoPermission() &&
-                mDeviceRuntimeService.hasPhotoPermission();
-        if (hasPermission) {
-            Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
-            getActivity().startActivityForResult(intent, REQUEST_CODE_PHOTO);
-        } else {
-            ActivityCompat.requestPermissions(getActivity(),
-                    new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
-                    REQUEST_PERMISSION_CAMERA);
-        }
+        presenter.cameraClick();
     }
 
     @OnClick(R.id.next_create_account)
     public void nextClicked() {
-        String fullname = mFullnameView.getText().toString().trim();
-        ((AccountWizard) getActivity()).profileNext(fullname, mSourcePhoto);
+        presenter.nextClick();
     }
 
     @OnClick(R.id.last_create_account)
     public void lastClicked() {
+        presenter.lastClick();
+    }
+
+    @Override
+    public void displayProfileName(String profileName) {
+        mFullnameView.setText(profileName);
+    }
+
+    @Override
+    public void goToGallery() {
+        Intent intent = new Intent(Intent.ACTION_PICK, MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
+        startActivityForResult(intent, REQUEST_CODE_GALLERY);
+    }
+
+    @Override
+    public void goToPhotoCapture() {
+        Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);
+        startActivityForResult(intent, REQUEST_CODE_PHOTO);
+    }
+
+    @Override
+    public void askStoragePermission() {
+        ActivityCompat.requestPermissions(getActivity(),
+                new String[]{Manifest.permission.READ_EXTERNAL_STORAGE},
+                REQUEST_PERMISSION_READ_STORAGE);
+    }
+
+    @Override
+    public void askPhotoPermission() {
+        ActivityCompat.requestPermissions(getActivity(),
+                new String[]{Manifest.permission.CAMERA, Manifest.permission.WRITE_EXTERNAL_STORAGE},
+                REQUEST_PERMISSION_CAMERA);
+    }
+
+    @Override
+    public void goToNext() {
+        String fullname = mFullnameView.getText().toString().trim();
+        ((AccountWizard) getActivity()).profileNext(fullname, mSourcePhoto);
+    }
+
+    @Override
+    public void goToLast() {
         ((AccountWizard) getActivity()).profileLast();
     }
 }
diff --git a/ring-android/app/src/main/java/cx/ring/account/ProfileCreationPresenter.java b/ring-android/app/src/main/java/cx/ring/account/ProfileCreationPresenter.java
new file mode 100644
index 000000000..3a2c860d6
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/account/ProfileCreationPresenter.java
@@ -0,0 +1,82 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Hadrien De Sousa <hadrien.desousa@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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package cx.ring.account;
+
+import javax.inject.Inject;
+
+import cx.ring.mvp.RootPresenter;
+import cx.ring.services.DeviceRuntimeService;
+import cx.ring.utils.Log;
+
+public class ProfileCreationPresenter extends RootPresenter<ProfileCreationView> {
+
+    public static final String TAG = ProfileCreationPresenter.class.getSimpleName();
+
+    protected DeviceRuntimeService mDeviceRuntimeService;
+
+    @Inject
+    public ProfileCreationPresenter(DeviceRuntimeService deviceRuntimeService) {
+        this.mDeviceRuntimeService = deviceRuntimeService;
+    }
+
+    public void initPresenter() {
+        //~ Checking the state of the READ_CONTACTS permission
+        if (mDeviceRuntimeService.hasContactPermission()) {
+            String profileName = mDeviceRuntimeService.getProfileName();
+            if (profileName != null) {
+                getView().displayProfileName(profileName);
+            }
+        } else {
+            Log.d(TAG, "READ_CONTACTS permission is not granted.");
+        }
+    }
+
+    public void galleryClick() {
+        boolean hasPermission = mDeviceRuntimeService.hasGalleryPermission();
+        if (hasPermission) {
+            getView().goToGallery();
+        } else {
+            getView().askStoragePermission();
+        }
+    }
+
+    public void cameraClick() {
+        boolean hasPermission = mDeviceRuntimeService.hasVideoPermission() &&
+                mDeviceRuntimeService.hasPhotoPermission();
+        if (hasPermission) {
+            getView().goToPhotoCapture();
+        } else {
+            getView().askPhotoPermission();
+        }
+    }
+
+    public void nextClick() {
+        getView().goToNext();
+    }
+
+    public void lastClick() {
+        getView().goToLast();
+    }
+
+    @Override
+    public void afterInjection() {
+
+    }
+}
diff --git a/ring-android/app/src/main/java/cx/ring/account/ProfileCreationView.java b/ring-android/app/src/main/java/cx/ring/account/ProfileCreationView.java
new file mode 100644
index 000000000..75043a338
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/account/ProfileCreationView.java
@@ -0,0 +1,39 @@
+/*
+ *  Copyright (C) 2017 Savoir-faire Linux Inc.
+ *
+ *  Author: Hadrien De Sousa <hadrien.desousa@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, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+package cx.ring.account;
+
+
+public interface ProfileCreationView {
+
+    void displayProfileName(String profileName);
+
+    void goToGallery();
+
+    void goToPhotoCapture();
+
+    void askStoragePermission();
+
+    void askPhotoPermission();
+
+    void goToNext();
+
+    void goToLast();
+
+}
diff --git a/ring-android/app/src/main/java/cx/ring/client/AccountWizard.java b/ring-android/app/src/main/java/cx/ring/client/AccountWizard.java
index 51455e1f5..d278cbb13 100644
--- a/ring-android/app/src/main/java/cx/ring/client/AccountWizard.java
+++ b/ring-android/app/src/main/java/cx/ring/client/AccountWizard.java
@@ -54,7 +54,7 @@ import cx.ring.R;
 import cx.ring.application.RingApplication;
 import cx.ring.fragments.AccountMigrationFragment;
 import cx.ring.account.HomeAccountCreationFragment;
-import cx.ring.fragments.ProfileCreationFragment;
+import cx.ring.account.ProfileCreationFragment;
 import cx.ring.fragments.RingAccountCreationFragment;
 import cx.ring.fragments.RingLinkAccountFragment;
 import cx.ring.fragments.SIPAccountCreationFragment;
@@ -509,26 +509,6 @@ public class AccountWizard extends AppCompatActivity implements Observer<Service
         new CreateAccountTask(this).execute(accountDetails);
     }
 
-    @Override
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-
-        switch (requestCode) {
-            case ProfileCreationFragment.REQUEST_CODE_PHOTO:
-                if (resultCode == RESULT_OK && data != null) {
-                    mProfileFragment.updatePhoto((Bitmap) data.getExtras().get("data"));
-                }
-                break;
-            case ProfileCreationFragment.REQUEST_CODE_GALLERY:
-                if (resultCode == RESULT_OK && data != null) {
-                    mProfileFragment.updatePhoto(data.getData());
-                }
-                break;
-            default:
-                break;
-        }
-    }
-
     private class WizardPagerAdapter extends FragmentStatePagerAdapter {
 
         WizardPagerAdapter(FragmentManager fm) {
diff --git a/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java b/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java
index 8a483bac8..005287480 100755
--- a/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java
+++ b/ring-android/app/src/main/java/cx/ring/dependencyinjection/RingInjectionComponent.java
@@ -41,7 +41,7 @@ import cx.ring.fragments.CallFragment;
 import cx.ring.fragments.ConversationFragment;
 import cx.ring.fragments.GeneralAccountFragment;
 import cx.ring.fragments.MediaPreferenceFragment;
-import cx.ring.fragments.ProfileCreationFragment;
+import cx.ring.account.ProfileCreationFragment;
 import cx.ring.fragments.RingAccountCreationFragment;
 import cx.ring.fragments.SIPAccountCreationFragment;
 import cx.ring.fragments.SecurityAccountFragment;
diff --git a/ring-android/app/src/main/java/cx/ring/services/DeviceRuntimeServiceImpl.java b/ring-android/app/src/main/java/cx/ring/services/DeviceRuntimeServiceImpl.java
index aeaeedf36..018e85120 100644
--- a/ring-android/app/src/main/java/cx/ring/services/DeviceRuntimeServiceImpl.java
+++ b/ring-android/app/src/main/java/cx/ring/services/DeviceRuntimeServiceImpl.java
@@ -22,10 +22,12 @@ package cx.ring.services;
 import android.Manifest;
 import android.content.Context;
 import android.content.pm.PackageManager;
+import android.database.Cursor;
 import android.media.AudioManager;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
 import android.os.Handler;
+import android.provider.ContactsContract;
 import android.support.v4.content.ContextCompat;
 
 import java.io.File;
@@ -43,6 +45,9 @@ import cx.ring.utils.NetworkUtils;
 public class DeviceRuntimeServiceImpl extends DeviceRuntimeService {
 
     private static final String TAG = DeviceRuntimeServiceImpl.class.getName();
+    private static final String[] PROFILE_PROJECTION = new String[]{ContactsContract.Profile._ID,
+            ContactsContract.Profile.DISPLAY_NAME_PRIMARY,
+            ContactsContract.Profile.PHOTO_ID};
 
     @Inject
     @Named("DaemonExecutor")
@@ -157,6 +162,19 @@ public class DeviceRuntimeServiceImpl extends DeviceRuntimeService {
         return checkPermission(Manifest.permission.READ_EXTERNAL_STORAGE);
     }
 
+    @Override
+    public String getProfileName() {
+        Cursor mProfileCursor = mContext.getContentResolver().query(ContactsContract.Profile.CONTENT_URI, PROFILE_PROJECTION, null, null, null);
+        if (mProfileCursor != null) {
+            if (mProfileCursor.moveToFirst()) {
+                mProfileCursor.close();
+                return mProfileCursor.getString(mProfileCursor.getColumnIndex(ContactsContract.Profile.DISPLAY_NAME_PRIMARY));
+            }
+            mProfileCursor.close();
+        }
+        return null;
+    }
+
     private boolean checkPermission(String permission) {
         return ContextCompat.checkSelfPermission(mContext, permission) == PackageManager.PERMISSION_GRANTED;
     }
diff --git a/ring-android/libringclient/src/main/java/cx/ring/services/DeviceRuntimeService.java b/ring-android/libringclient/src/main/java/cx/ring/services/DeviceRuntimeService.java
index b98b294d0..f21538b22 100644
--- a/ring-android/libringclient/src/main/java/cx/ring/services/DeviceRuntimeService.java
+++ b/ring-android/libringclient/src/main/java/cx/ring/services/DeviceRuntimeService.java
@@ -53,4 +53,6 @@ public abstract class DeviceRuntimeService {
 
     public abstract boolean hasGalleryPermission();
 
+    public abstract String getProfileName();
+
 }
-- 
GitLab