Browse Source

Refactored and gave ResetPasswordActivity a makover. Simplified input validation in background tasks. Changed the bottom navigation bar colors for the MainActivity.

Víctor Hernández 3 years ago
parent
commit
6246811d9f

+ 1
- 5
app/src/main/AndroidManifest.xml View File

@@ -16,10 +16,6 @@
16 16
         android:theme="@style/Theme.TANIA"
17 17
         android:usesCleartextTraffic="true">
18 18
 
19
-        <activity
20
-            android:name=".activities.ConsentPdfViewerActivity"
21
-            android:label="@string/title_activity_consent_pdf_viewer"
22
-            android:theme="@style/Theme.TANIA.NoActionBar" />
23 19
         <activity android:name=".activities.GettingStartedActivity">
24 20
             <intent-filter>
25 21
                 <category android:name="android.intent.category.LAUNCHER" />
@@ -81,7 +77,7 @@
81 77
                 <category android:name="android.intent.category.BROWSABLE" />
82 78
 
83 79
                 <data
84
-                    android:host="account"
80
+                    android:host="reset_password"
85 81
                     android:scheme="tania" />
86 82
             </intent-filter>
87 83
         </activity>

+ 0
- 122
app/src/main/java/uprrp/tania/SendResetPasswordToServer.java View File

@@ -1,122 +0,0 @@
1
-/*************************************************************
2
- * By: Coralys Cubero Rivera
3
- * Date: 2019
4
- *************************************************************/
5
-
6
-package uprrp.tania;
7
-
8
-import android.content.Context;
9
-import android.content.Intent;
10
-import android.os.AsyncTask;
11
-import android.util.Log;
12
-import android.widget.Toast;
13
-
14
-import java.io.BufferedReader;
15
-import java.io.BufferedWriter;
16
-import java.io.InputStream;
17
-import java.io.InputStreamReader;
18
-import java.io.OutputStreamWriter;
19
-import java.io.UnsupportedEncodingException;
20
-import java.io.Writer;
21
-import java.net.URL;
22
-import java.net.URLConnection;
23
-import java.net.URLEncoder;
24
-import java.nio.charset.StandardCharsets;
25
-
26
-import uprrp.tania.activities.MainActivity;
27
-
28
-public class SendResetPasswordToServer extends AsyncTask <String, String, String> {
29
-
30
-    private Context context;
31
-
32
-    public SendResetPasswordToServer(Context context){
33
-        this.context = context.getApplicationContext();
34
-    }
35
-
36
-    @Override
37
-    protected String doInBackground(String... strings) {
38
-        String jsonResetPassword  = "";
39
-
40
-        try {
41
-            jsonResetPassword = URLEncoder.encode("data", "UTF-8") + "=" + URLEncoder.encode(strings[0], "UTF-8");
42
-
43
-        }
44
-
45
-        catch (UnsupportedEncodingException e) {
46
-            e.printStackTrace();
47
-        }
48
-
49
-        String serverReply = "";
50
-        BufferedReader serverReader;
51
-
52
-        //Send the signature to TANIA's server
53
-        try
54
-        {
55
-            //Defined URL  where to send data
56
-            URL url = new URL("https://tania.uprrp.edu/resetPassword.php");
57
-
58
-            //Send POST data request
59
-            URLConnection conn = url.openConnection();
60
-            conn.setDoOutput(true);
61
-
62
-            Writer writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8));
63
-            writer.write(jsonResetPassword);
64
-            writer.close();
65
-
66
-            InputStream inputStream = conn.getInputStream();
67
-            StringBuffer buffer = new StringBuffer();
68
-
69
-            if (inputStream == null) {
70
-                return null;
71
-            }
72
-
73
-            //Get the server response
74
-            serverReader = new BufferedReader(new InputStreamReader(inputStream));
75
-            StringBuilder serverResponse = new StringBuilder();
76
-            String serverResponseLine;
77
-
78
-            // Read Server Response
79
-            while((serverResponseLine = serverReader.readLine()) != null)
80
-            {
81
-                //Append server response in string
82
-                serverResponse.append(serverResponseLine);
83
-            }
84
-
85
-            serverReply = serverResponse.toString();
86
-        }
87
-        catch(Exception ex) {
88
-            Log.e("ERROR RESET PASSWORD", ex.getMessage());
89
-        }
90
-
91
-        return serverReply;
92
-    }
93
-
94
-    @Override
95
-    protected void onPostExecute(String s) {
96
-        Log.d("RESET PASSWORD SERVER REPLY", s);
97
-
98
-        String ss = s.substring(0,6);
99
-        String se = s.substring(0,8);
100
-        if (ss.equals("Succes")){
101
-
102
-            try {
103
-                Intent intent = new Intent(context, MainActivity.class);
104
-                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
105
-                context.startActivity(intent);
106
-            }
107
-            catch (Exception e){
108
-                Log.d("REGISTRATION TO MAIN ACTIVITY", e.getMessage());
109
-            }
110
-
111
-        }
112
-
113
-        else if (se.equals("Error:fo")){
114
-            Toast.makeText(context, "", Toast.LENGTH_LONG).show();
115
-        }
116
-
117
-        else {
118
-            Toast.makeText(context, "An error occured while trying to register. Please start again.", Toast.LENGTH_LONG).show();
119
-        }
120
-
121
-    }
122
-}

+ 0
- 85
app/src/main/java/uprrp/tania/activities/ConsentPdfViewerActivity.java View File

@@ -1,85 +0,0 @@
1
-package uprrp.tania.activities;
2
-
3
-import android.graphics.Canvas;
4
-import android.graphics.Color;
5
-import android.os.Bundle;
6
-
7
-import com.github.barteksc.pdfviewer.PDFView;
8
-import com.github.barteksc.pdfviewer.listener.OnDrawListener;
9
-import com.github.barteksc.pdfviewer.listener.OnPageChangeListener;
10
-import com.github.barteksc.pdfviewer.listener.OnPageErrorListener;
11
-import com.github.barteksc.pdfviewer.listener.OnRenderListener;
12
-import com.github.barteksc.pdfviewer.listener.OnTapListener;
13
-
14
-import androidx.appcompat.app.AppCompatActivity;
15
-import androidx.appcompat.widget.Toolbar;
16
-
17
-import android.os.Environment;
18
-import android.view.MotionEvent;
19
-import android.widget.Toast;
20
-
21
-import java.io.File;
22
-
23
-import uprrp.tania.R;
24
-
25
-public class ConsentPdfViewerActivity extends AppCompatActivity {
26
-
27
-    PDFView pdfView;
28
-
29
-    @Override
30
-    protected void onCreate(Bundle savedInstanceState) {
31
-        super.onCreate(savedInstanceState);
32
-        setContentView(R.layout.activity_consent_pdf_viewer);
33
-        Toolbar toolbar = findViewById(R.id.toolbar);
34
-        setSupportActionBar(toolbar);
35
-        this.pdfView = findViewById(R.id.pdf_viewer);
36
-        File consentFile = new File(Environment.getExternalStorageDirectory().getPath() + "/consent-tania-app.pdf");
37
-
38
-        this.pdfView.fromFile(consentFile)
39
-            .password(null)
40
-            .defaultPage(0)
41
-            .enableSwipe(true)
42
-            .swipeHorizontal(false)
43
-            .enableDoubletap(true)
44
-            .onDraw(new OnDrawListener() {
45
-                @Override
46
-                public void onLayerDrawn(Canvas canvas, float pageWidth, float pageHeight, int displayedPage) {
47
-                   // Code here if you want to do something
48
-                }
49
-            })
50
-            .onDrawAll(new OnDrawListener() {
51
-                @Override
52
-                public void onLayerDrawn(Canvas canvas, float pageWidth, float pageHeight, int displayedPage) {
53
-                    // Code here if you want to do something
54
-                }
55
-            })
56
-            .onPageError(new OnPageErrorListener() {
57
-                @Override
58
-                public void onPageError(int page, Throwable t) {
59
-                    Toast.makeText(ConsentPdfViewerActivity.this, "Error opening page " + page, Toast.LENGTH_LONG).show();
60
-                }
61
-            })
62
-            .onPageChange(new OnPageChangeListener() {
63
-                @Override
64
-                public void onPageChanged(int page, int pageCount) {
65
-                    //Code here
66
-                }
67
-            })
68
-            .onTap(new OnTapListener() {
69
-                @Override
70
-                public boolean onTap(MotionEvent e) {
71
-                    return true;
72
-                }
73
-            })
74
-            .onRender(new OnRenderListener() {
75
-                @Override
76
-                public void onInitiallyRendered(int nbPages, float pageWidth, float pageHeight) {
77
-                    pdfView.fitToWidth();
78
-                }
79
-            })
80
-            .enableAnnotationRendering(true)
81
-            .invalidPageColor(Color.WHITE)
82
-            .load();
83
-    }
84
-
85
-}

+ 11
- 14
app/src/main/java/uprrp/tania/activities/MainActivity.java View File

@@ -1,8 +1,7 @@
1 1
 package uprrp.tania.activities;
2 2
 
3
-import android.content.Intent;
4
-import android.content.SharedPreferences;
5 3
 import android.os.Bundle;
4
+import android.util.Log;
6 5
 import android.view.MenuItem;
7 6
 
8 7
 import androidx.annotation.NonNull;
@@ -48,18 +47,16 @@ public class MainActivity extends PinCodeActivity {
48 47
 
49 48
                 Fragment selectedFragment;
50 49
 
51
-                switch (item.getItemId()) {
52
-                    case R.id.nav_assessments:
53
-                        selectedFragment = new AssessmentsFragment();
54
-                        break;
55
-                    case R.id.nav_consent:
56
-                        selectedFragment = new ConsentFragment();
57
-                        break;
58
-                    case R.id.nav_settings:
59
-                        selectedFragment = new WithdrawFragment();
60
-                        break;
61
-                    default:
62
-                        selectedFragment = new Fragment();
50
+                int id = item.getItemId();
51
+                if(id == R.id.nav_assessments) {
52
+                    selectedFragment = new AssessmentsFragment();
53
+                } else if(id == R.id.nav_consent) {
54
+                    selectedFragment = new ConsentFragment();
55
+                } else if(id == R.id.nav_settings) {
56
+                    selectedFragment = new WithdrawFragment();
57
+                } else {
58
+                    Log.wtf(TAG, "Illegal fragment reach attempt with id: " + id);
59
+                    selectedFragment = new Fragment(); // use empty fragment
63 60
                 }
64 61
 
65 62
                 getSupportFragmentManager()

+ 61
- 35
app/src/main/java/uprrp/tania/activities/ResetPasswordActivity.java View File

@@ -1,10 +1,6 @@
1
-/*************************************************************
2
- * By: Coralys Cubero Rivera
3
- * Date: 2019
4
- *************************************************************/
5
-
6 1
 package uprrp.tania.activities;
7 2
 
3
+import android.app.ProgressDialog;
8 4
 import android.content.Intent;
9 5
 import android.net.Uri;
10 6
 import android.os.Bundle;
@@ -17,60 +13,90 @@ import android.widget.Toast;
17 13
 import androidx.annotation.Nullable;
18 14
 import androidx.appcompat.app.AppCompatActivity;
19 15
 
20
-import org.json.JSONObject;
21
-
22 16
 import uprrp.tania.GlobalValues;
23 17
 import uprrp.tania.R;
24
-import uprrp.tania.SendResetPasswordToServer;
18
+import uprrp.tania.networking.SendResetPassword;
19
+import uprrp.tania.utils.URLEventListener;
25 20
 
26 21
 public class ResetPasswordActivity extends AppCompatActivity {
27 22
 
28
-    String forgotPasswordKey;
23
+    private static final String TAG = "ResetPasswordActivity";
24
+    private String FORGOT_PASSWORD_KEY;
25
+
29 26
     @Override
30 27
     protected void onCreate(@Nullable Bundle savedInstanceState) {
28
+
29
+        // Constructor stuff
31 30
         super.onCreate(savedInstanceState);
32 31
         setContentView(R.layout.activity_reset_password);
33 32
 
33
+        // Fetch experience token from URL (only if we launched this Activity from Browser)
34 34
         Intent intent = getIntent();
35
-        if(Intent.ACTION_VIEW.equals(intent.getAction())){
35
+        if(Intent.ACTION_VIEW.equals(intent.getAction())) {
36 36
             Uri uri = intent.getData();
37
-            assert uri != null;
38
-            forgotPasswordKey = uri.getQueryParameter("id");
37
+            assert uri != null; // TODO: figure out if this causes crashes...
38
+            FORGOT_PASSWORD_KEY = uri.getQueryParameter("forgotPasswordKey");
39
+            Log.d(TAG, "ForgotPasswordKey is " + FORGOT_PASSWORD_KEY);
40
+        } else {
41
+            Log.wtf(TAG, "Activity started from somewhere other than the browser!");
39 42
         }
40 43
 
41
-
42
-        final EditText newPassword = findViewById(R.id.editTextNewPassword);
43
-        final EditText confirmPassword = findViewById(R.id.editTextConfirmPassword);
44
-
45
-        final JSONObject resetPasswordJSON = new JSONObject();
46
-
47
-        final Button resetPassword = findViewById(R.id.buttonResetPassword);
48
-        resetPassword.setOnClickListener(new View.OnClickListener() {
44
+        // Change all caps text to normal capitalization and add onClick listeners
45
+        final Button resetPasswordButton = findViewById(R.id.buttonResetPassword);
46
+        resetPasswordButton.setTransformationMethod(null); // TODO: this is a workaround I found, any other acceptable solution is welcome
47
+        resetPasswordButton.setOnClickListener(new View.OnClickListener() {
49 48
             @Override
50 49
             public void onClick(View v) {
51
-                try {
52
-                    if (newPassword.getText().toString().equals(confirmPassword.getText().toString())){
53
-                        resetPasswordJSON.put("token", GlobalValues.getInstance().getDeviceToken());
54
-                        resetPasswordJSON.put("password", newPassword.getText().toString());
55
-                        resetPasswordJSON.put("forgotPasswordKey", forgotPasswordKey);
50
+                sendPasswordResetRequest();
51
+            }
52
+        });
56 53
 
57
-                        Log.d("RESET PASSWORD JSON", resetPasswordJSON.toString());
54
+    }
58 55
 
59
-                        SendResetPasswordToServer sendResetPasswordToServer = new SendResetPasswordToServer(getApplicationContext());
60
-                        sendResetPasswordToServer.execute(resetPasswordJSON.toString());
56
+    private void sendPasswordResetRequest() {
61 57
 
58
+        final EditText newPasswordEditText = findViewById(R.id.editTextNewPassword);
59
+        final EditText confirmPasswordEditText = findViewById(R.id.editTextConfirmPassword);
62 60
 
63
-                    }
64
-                    else{
65
-                        Toast.makeText(ResetPasswordActivity.this, "The password and confirmation must match!", Toast.LENGTH_LONG).show();
66
-                    }
61
+        String newPassword = newPasswordEditText.getText().toString();
62
+        String confirmPassword = confirmPasswordEditText.getText().toString();
67 63
 
64
+        if(newPassword.equals(confirmPassword) && !newPassword.equals("")) {
68 65
 
69
-                } catch (Exception e) {
66
+            // Initiate progress dialog
67
+            // TODO: find substitute for this deprecated dialog box
68
+            final ProgressDialog progressDialog = ProgressDialog.show(ResetPasswordActivity.this,
69
+                    "Resetting Password",
70
+                    getString(R.string.progressDialogDescriptionText));
71
+
72
+            // Define task
73
+            SendResetPassword sendResetPasswordTask = new SendResetPassword(new URLEventListener() {
74
+                @Override
75
+                public void onSuccess() {
76
+                    progressDialog.dismiss();
77
+                    Toast.makeText(getApplicationContext(), "Success!\nYou can login with your new password now.", Toast.LENGTH_SHORT).show();
78
+                    Intent intent = new Intent(getApplicationContext(), GettingStartedActivity.class);
79
+                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
80
+                    startActivity(intent);
81
+                }
82
+
83
+                @Override
84
+                public void onFailure(Exception e) {
85
+                    progressDialog.dismiss();
86
+                    Toast.makeText(getApplicationContext(), "An error occurred while trying to register. Please try again.", Toast.LENGTH_LONG).show();
87
+                    Log.e(TAG, "Couldn't reset password!");
70 88
                     e.printStackTrace();
71 89
                 }
72
-            }
73
-        });
90
+            });
91
+
92
+            // Start task
93
+            String deviceToken = GlobalValues.getInstance().getDeviceToken();
94
+            sendResetPasswordTask.execute(deviceToken, newPassword, FORGOT_PASSWORD_KEY);
95
+
96
+        } else {
97
+            Toast.makeText(ResetPasswordActivity.this, "Both fields must match and can't be blank!", Toast.LENGTH_LONG).show();
98
+        }
99
+
74 100
 
75 101
     }
76 102
 }

+ 5
- 5
app/src/main/java/uprrp/tania/networking/FetchAssessment.java View File

@@ -39,11 +39,11 @@ public class FetchAssessment extends AsyncTask<String, Void, JSONObject> {
39 39
             return false;
40 40
         }
41 41
 
42
-        String deviceToken = strings[0];
43
-
44
-        if(deviceToken == null) {
45
-            Log.e(TAG, "Encountered null device token!");
46
-            return false;
42
+        for(int i = 0; i < strings.length; i++) {
43
+            if(strings[i] == null) {
44
+                Log.e(TAG, "Encountered null parameter on index " + i);
45
+                return false;
46
+            }
47 47
         }
48 48
 
49 49
         return true;

+ 5
- 5
app/src/main/java/uprrp/tania/networking/FetchUserStatus.java View File

@@ -40,11 +40,11 @@ public class FetchUserStatus extends AsyncTask<String, Void, JSONArray> {
40 40
             return false;
41 41
         }
42 42
 
43
-        String deviceToken = strings[0];
44
-
45
-        if(deviceToken == null) {
46
-            Log.e(TAG, "Encountered null device token!");
47
-            return false;
43
+        for(int i = 0; i < strings.length; i++) {
44
+            if(strings[i] == null) {
45
+                Log.e(TAG, "Encountered null parameter on index " + i);
46
+                return false;
47
+            }
48 48
         }
49 49
 
50 50
         return true;

+ 5
- 13
app/src/main/java/uprrp/tania/networking/SendAccountRecovery.java View File

@@ -34,19 +34,11 @@ public class SendAccountRecovery extends AsyncTask<String, Void, String> {
34 34
             return false;
35 35
         }
36 36
 
37
-        String deviceToken = strings[0];
38
-        String email = strings[1];
39
-        String password = strings[2];
40
-
41
-        if(email == null) {
42
-            Log.e(TAG, "Encountered null email!");
43
-            return false;
44
-        } else if (deviceToken == null) {
45
-            Log.e(TAG, "Encountered null device token!");
46
-            return false;
47
-        } else if (password == null) {
48
-            Log.e(TAG, "Encountered null password!");
49
-            return false;
37
+        for(int i = 0; i < strings.length; i++) {
38
+            if(strings[i] == null) {
39
+                Log.e(TAG, "Encountered null parameter on index " + i);
40
+                return false;
41
+            }
50 42
         }
51 43
 
52 44
         return true;

+ 10
- 10
app/src/main/java/uprrp/tania/networking/SendAnswers.java View File

@@ -31,18 +31,18 @@ public class SendAnswers extends AsyncTask<AnsweredAssessmentModel, Void, String
31 31
         this.myCallback = callback;
32 32
     }
33 33
 
34
-    private boolean validInputs(AnsweredAssessmentModel... answeredAssessments) {
34
+    private boolean validInputs(AnsweredAssessmentModel... assessments) {
35 35
 
36
-        if(answeredAssessments.length != 1) {
36
+        if(assessments.length != 1) {
37 37
             Log.e(TAG, "Invalid array length!");
38 38
             return false;
39 39
         }
40 40
 
41
-        AnsweredAssessmentModel assessment = answeredAssessments[0];
42
-
43
-        if(assessment == null) {
44
-            Log.e(TAG, "Encountered null assessment!");
45
-            return false;
41
+        for(int i = 0; i < assessments.length; i++) {
42
+            if(assessments[i] == null) {
43
+                Log.e(TAG, "Encountered null parameter on index " + i);
44
+                return false;
45
+            }
46 46
         }
47 47
 
48 48
         return true;
@@ -93,16 +93,16 @@ public class SendAnswers extends AsyncTask<AnsweredAssessmentModel, Void, String
93 93
         }
94 94
      */
95 95
     @Override
96
-    protected String doInBackground(AnsweredAssessmentModel... answeredAssessments) {
96
+    protected String doInBackground(AnsweredAssessmentModel... assessments) {
97 97
 
98 98
         // Validation
99
-        if(!validInputs(answeredAssessments)) {
99
+        if(!validInputs(assessments)) {
100 100
             Log.e(TAG, "Invalid inputs given!");
101 101
             return null;
102 102
         }
103 103
 
104 104
         // Extract variables
105
-        AnsweredAssessmentModel answeredAssessment = answeredAssessments[0]; // array will only ever contain a single element
105
+        AnsweredAssessmentModel answeredAssessment = assessments[0]; // array will only ever contain a single element
106 106
 
107 107
         try {
108 108
 

+ 6
- 14
app/src/main/java/uprrp/tania/networking/SendConsentForm.java View File

@@ -36,19 +36,11 @@ public class SendConsentForm extends AsyncTask <String, Void, String> {
36 36
             return false;
37 37
         }
38 38
 
39
-        String deviceToken = strings[0];
40
-        String consentFormBase64 = strings[1];
41
-        String signatureDate = strings[2];
42
-
43
-        if(consentFormBase64 == null) {
44
-            Log.e(TAG, "Encountered null consent form!");
45
-            return false;
46
-        } else if (deviceToken == null) {
47
-            Log.e(TAG, "Encountered null device token!");
48
-            return false;
49
-        } else if (signatureDate == null) {
50
-            Log.e(TAG, "Encountered null signature date!");
51
-            return false;
39
+        for(int i = 0; i < strings.length; i++) {
40
+            if(strings[i] == null) {
41
+                Log.e(TAG, "Encountered null parameter on index " + i);
42
+                return false;
43
+            }
52 44
         }
53 45
 
54 46
         return true;
@@ -123,7 +115,7 @@ public class SendConsentForm extends AsyncTask <String, Void, String> {
123 115
             e.printStackTrace();
124 116
             return null;
125 117
         } catch (UnsupportedEncodingException e) {
126
-            Log.e(TAG, "Couldn't encode consentFormJSON");
118
+            Log.e(TAG, "Couldn't encode consentFormJSON!");
127 119
             e.printStackTrace();
128 120
             return null;
129 121
         } catch(Exception e) {

+ 5
- 9
app/src/main/java/uprrp/tania/networking/SendExperienceRegistration.java View File

@@ -34,15 +34,11 @@ public class SendExperienceRegistration extends AsyncTask<String, Void, String>
34 34
             return false;
35 35
         }
36 36
 
37
-        String deviceToken = strings[0];
38
-        String experienceID = strings[1];
39
-
40
-        if(experienceID == null) {
41
-            Log.e(TAG, "Encountered null experience ID!");
42
-            return false;
43
-        } else if (deviceToken == null) {
44
-            Log.e(TAG, "Encountered null device token!");
45
-            return false;
37
+        for(int i = 0; i < strings.length; i++) {
38
+            if(strings[i] == null) {
39
+                Log.e(TAG, "Encountered null parameter on index " + i);
40
+                return false;
41
+            }
46 42
         }
47 43
 
48 44
         return true;

+ 14
- 5
app/src/main/java/uprrp/tania/networking/SendRecoveryEmail.java View File

@@ -34,17 +34,26 @@ public class SendRecoveryEmail extends AsyncTask<String, String, String> {
34 34
             return false;
35 35
         }
36 36
 
37
-        String email = strings[0];
38
-
39
-        if(email == null) {
40
-            Log.e(TAG, "Encountered null email!");
41
-            return false;
37
+        for(int i = 0; i < strings.length; i++) {
38
+            if(strings[i] == null) {
39
+                Log.e(TAG, "Encountered null parameter on index " + i);
40
+                return false;
41
+            }
42 42
         }
43 43
 
44 44
         return true;
45 45
 
46 46
     }
47 47
 
48
+    // TODO: instead of making a normal POST request with
49
+    //  the body data=<JSON>, we should just send the JSON itself
50
+    //  This is adding unnecessary layers of complexity when decoding AND encoding
51
+    /*
52
+        JSON format:
53
+        {
54
+            "email": String,
55
+        }
56
+    */
48 57
     @Override
49 58
     protected String doInBackground(String... strings) {
50 59
 

+ 145
- 0
app/src/main/java/uprrp/tania/networking/SendResetPassword.java View File

@@ -0,0 +1,145 @@
1
+package uprrp.tania.networking;
2
+
3
+import android.os.AsyncTask;
4
+import android.util.Log;
5
+
6
+import org.json.JSONException;
7
+import org.json.JSONObject;
8
+
9
+import java.io.BufferedReader;
10
+import java.io.BufferedWriter;
11
+import java.io.InputStreamReader;
12
+import java.io.OutputStreamWriter;
13
+import java.io.UnsupportedEncodingException;
14
+import java.io.Writer;
15
+import java.net.URL;
16
+import java.net.URLConnection;
17
+import java.net.URLEncoder;
18
+import java.nio.charset.StandardCharsets;
19
+
20
+import uprrp.tania.utils.URLEventListener;
21
+
22
+public class SendResetPassword extends AsyncTask <String, Void, String> {
23
+
24
+    private static final String TAG = "SendResetPassword";
25
+    private static final String resetPasswordBaseURL = "https://tania.uprrp.edu/resetPassword.php";
26
+    private final URLEventListener myCallback;
27
+
28
+    public SendResetPassword(URLEventListener callback){
29
+        this.myCallback = callback;
30
+    }
31
+
32
+    private boolean validInputs(String... strings) {
33
+
34
+        if(strings.length != 3) {
35
+            Log.e(TAG, "Invalid string array length!");
36
+            return false;
37
+        }
38
+
39
+        for(int i = 0; i < strings.length; i++) {
40
+            if(strings[i] == null) {
41
+                Log.e(TAG, "Encountered null parameter on index " + i);
42
+                return false;
43
+            }
44
+        }
45
+
46
+        return true;
47
+
48
+    }
49
+
50
+    // TODO: instead of making a normal POST request with
51
+    //  the body data=<JSON>, we should just send the JSON itself
52
+    //  This is adding unnecessary layers of complexity when decoding AND encoding
53
+    /*
54
+        JSON format:
55
+        {
56
+            "forgotPasswordKey": String,
57
+            "password": String,
58
+            "token": String,
59
+        }
60
+    */
61
+    @Override
62
+    protected String doInBackground(String... strings) {
63
+
64
+        // Validation
65
+        if(!validInputs(strings)) {
66
+            Log.e(TAG, "Invalid inputs given!");
67
+            return null;
68
+        }
69
+
70
+        // Extract variables
71
+        String deviceToken = strings[0];
72
+        String newPassword = strings[1];
73
+        String forgotPasswordKey = strings[2];
74
+
75
+        try {
76
+
77
+            // Create JSON
78
+            JSONObject resetPasswordJSON = new JSONObject();
79
+            resetPasswordJSON.put("token", deviceToken);
80
+            resetPasswordJSON.put("password", newPassword);
81
+            resetPasswordJSON.put("forgotPasswordKey", forgotPasswordKey);
82
+            Log.d(TAG, "resetPasswordJSON is " + resetPasswordJSON.toString());
83
+
84
+            // Encode data
85
+            String encodedRequestBody = URLEncoder.encode("data", "UTF-8") + "=" + URLEncoder.encode(resetPasswordJSON.toString(), "UTF-8");
86
+
87
+            // Send POST data request
88
+            URL url = new URL(resetPasswordBaseURL);
89
+            URLConnection conn = url.openConnection();
90
+            conn.setDoOutput(true);
91
+            Writer writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream(), StandardCharsets.UTF_8));
92
+            writer.write(encodedRequestBody);
93
+            writer.close();
94
+
95
+            // Get the server response
96
+            BufferedReader serverReader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
97
+            StringBuilder serverResponse = new StringBuilder();
98
+
99
+            String line = "";
100
+            while(line != null) {
101
+                serverResponse.append(line);
102
+                line = serverReader.readLine();
103
+            }
104
+
105
+            String response = serverResponse.toString();
106
+            Log.d(TAG, "The server's response is " + response);
107
+            if(response.contains("Success")) {
108
+                return response;
109
+            } else {
110
+                return null;
111
+            }
112
+
113
+        } catch (JSONException e) {
114
+            Log.e(TAG, "Couldn't prepare resetPasswordJSON!");
115
+            e.printStackTrace();
116
+            return null;
117
+        } catch (UnsupportedEncodingException e) {
118
+            Log.e(TAG, "Couldn't encode resetPasswordJSON!");
119
+            e.printStackTrace();
120
+            return null;
121
+        } catch(Exception e) {
122
+            Log.e(TAG, "Couldn't communicate with server while resetting password!");
123
+            e.printStackTrace();
124
+            return null;
125
+        }
126
+
127
+    }
128
+
129
+    @Override
130
+    protected void onPostExecute(String response) {
131
+
132
+        if(this.myCallback == null) {
133
+            Log.e(TAG, "Callback wasn't initialized first!");
134
+            return;
135
+        }
136
+
137
+        if(response == null) {
138
+            this.myCallback.onFailure(new Exception("Error occurred during transaction!"));
139
+            return;
140
+        }
141
+
142
+        this.myCallback.onSuccess();
143
+
144
+    }
145
+}

+ 5
- 5
app/src/main/java/uprrp/tania/networking/SendWithdrawal.java View File

@@ -37,11 +37,11 @@ public class SendWithdrawal extends AsyncTask<String, Void, String> {
37 37
             return false;
38 38
         }
39 39
 
40
-        String deviceToken = strings[0];
41
-
42
-        if(deviceToken == null) {
43
-            Log.e(TAG, "Encountered null device token!");
44
-            return false;
40
+        for(int i = 0; i < strings.length; i++) {
41
+            if(strings[i] == null) {
42
+                Log.e(TAG, "Encountered null parameter on index " + i);
43
+                return false;
44
+            }
45 45
         }
46 46
 
47 47
         return true;

+ 2
- 2
app/src/main/res/color/bottom_nav_selector.xml View File

@@ -1,7 +1,7 @@
1 1
 <?xml version="1.0" encoding="utf-8"?>
2 2
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
3 3
 
4
-    <item android:state_checked="true" android:color="@color/colorAccent" />
5
-    <item android:color="@color/textColor1"  />
4
+    <item android:state_checked="true" android:color="@android:color/white" />
5
+    <item android:color="#80FFFFFF" />
6 6
 
7 7
 </selector>

+ 0
- 42
app/src/main/res/layout/activity_consent_pdf_viewer.xml View File

@@ -1,42 +0,0 @@
1
-<?xml version="1.0" encoding="utf-8"?>
2
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
-    xmlns:app="http://schemas.android.com/apk/res-auto"
4
-    xmlns:tools="http://schemas.android.com/tools"
5
-    android:id="@+id/ConstraintLayout"
6
-    android:layout_width="match_parent"
7
-    android:layout_height="match_parent"
8
-    tools:context="uprrp.tania.activities.ConsentPdfViewerActivity">
9
-
10
-
11
-    <com.github.barteksc.pdfviewer.PDFView
12
-        android:id="@+id/pdf_viewer"
13
-        android:layout_width="0dp"
14
-        android:layout_height="0dp"
15
-        app:layout_constraintBottom_toBottomOf="parent"
16
-        app:layout_constraintEnd_toEndOf="parent"
17
-        app:layout_constraintHorizontal_bias="0.0"
18
-        app:layout_constraintStart_toStartOf="parent"
19
-        app:layout_constraintTop_toBottomOf="@+id/appBarLayout">
20
-
21
-    </com.github.barteksc.pdfviewer.PDFView>
22
-
23
-    <com.google.android.material.appbar.AppBarLayout
24
-        android:id="@+id/appBarLayout"
25
-        android:layout_width="match_parent"
26
-        android:layout_height="61dp"
27
-        android:theme="@style/Theme.TANIA.AppBarOverlay"
28
-        app:layout_constraintEnd_toEndOf="parent"
29
-        app:layout_constraintStart_toStartOf="parent"
30
-        app:layout_constraintTop_toTopOf="parent">
31
-
32
-        <androidx.appcompat.widget.Toolbar
33
-            android:id="@+id/toolbar"
34
-            android:layout_width="match_parent"
35
-            android:layout_height="match_parent"
36
-            android:background="?attr/colorPrimary"
37
-            app:popupTheme="@style/Theme.TANIA.PopupOverlay" />
38
-
39
-    </com.google.android.material.appbar.AppBarLayout>
40
-
41
-
42
-</androidx.constraintlayout.widget.ConstraintLayout>

+ 43
- 37
app/src/main/res/layout/activity_reset_password.xml View File

@@ -2,68 +2,74 @@
2 2
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3 3
     xmlns:app="http://schemas.android.com/apk/res-auto"
4 4
     xmlns:tools="http://schemas.android.com/tools"
5
-    android:orientation="vertical" android:layout_width="match_parent"
6
-    android:layout_height="match_parent">
5
+    android:layout_width="match_parent"
6
+    android:layout_height="match_parent"
7
+    android:orientation="vertical">
7 8
 
8 9
     <TextView
9 10
         android:id="@+id/textViewResetPassword"
10
-        android:layout_width="310dp"
11
-        android:layout_height="34dp"
12
-        android:fontFamily="@font/acme"
13
-        android:text="Reset your password:"
11
+        android:layout_width="0dp"
12
+        android:layout_height="wrap_content"
13
+        android:layout_marginStart="@dimen/horizontalMargin"
14
+        android:layout_marginTop="@dimen/verticalMargin"
15
+        android:layout_marginEnd="@dimen/horizontalMargin"
16
+        android:fontFamily="@font/cabin"
17
+        android:text="@string/resetPasswordDescriptionText"
14 18
         android:textAlignment="center"
15
-        android:textSize="18sp"
16
-        app:layout_constraintBottom_toBottomOf="parent"
19
+        android:textColor="@color/textColor2"
20
+        android:textSize="24sp"
21
+        android:textStyle="bold"
22
+        app:layout_constraintBottom_toTopOf="@+id/buttonResetPassword"
17 23
         app:layout_constraintEnd_toEndOf="parent"
18
-        app:layout_constraintHorizontal_bias="0.495"
19 24
         app:layout_constraintStart_toStartOf="parent"
20
-        app:layout_constraintTop_toTopOf="parent"
21
-        app:layout_constraintVertical_bias="0.318" />
25
+        app:layout_constraintTop_toTopOf="parent" />
22 26
 
23 27
     <EditText
24 28
         android:id="@+id/editTextNewPassword"
25
-        android:layout_width="wrap_content"
29
+        android:layout_width="0dp"
26 30
         android:layout_height="wrap_content"
31
+        android:layout_marginStart="@dimen/horizontalMargin"
32
+        android:layout_marginTop="24dp"
33
+        android:layout_marginEnd="@dimen/horizontalMargin"
34
+        android:autofillHints="AUTOFILL_HINT_PASSWORD"
35
+        android:backgroundTint="@color/colorPrimary"
27 36
         android:ems="10"
28
-        android:fontFamily="@font/acme"
29
-        android:hint="New password"
37
+        android:hint="@string/newPasswordButtonHint"
30 38
         android:inputType="textPassword"
31
-        android:textAlignment="center"
32
-        app:layout_constraintBottom_toBottomOf="parent"
39
+        android:textColor="@color/textColor2"
33 40
         app:layout_constraintEnd_toEndOf="parent"
34
-        app:layout_constraintHorizontal_bias="0.497"
35 41
         app:layout_constraintStart_toStartOf="parent"
36
-        app:layout_constraintTop_toBottomOf="@+id/textViewResetPassword"
37
-        app:layout_constraintVertical_bias="0.055" />
42
+        app:layout_constraintTop_toBottomOf="@+id/textViewResetPassword" />
38 43
 
39 44
     <EditText
40 45
         android:id="@+id/editTextConfirmPassword"
41
-        android:layout_width="wrap_content"
46
+        android:layout_width="0dp"
42 47
         android:layout_height="wrap_content"
48
+        android:layout_marginTop="16dp"
49
+        android:autofillHints="AUTOFILL_HINT_PASSWORD"
50
+        android:backgroundTint="@color/colorPrimary"
43 51
         android:ems="10"
44
-        android:fontFamily="@font/acme"
45
-        android:hint="Confirm password"
52
+        android:hint="@string/confirmPasswordButtonHint"
46 53
         android:inputType="textPassword"
47
-        android:textAlignment="center"
48
-        app:layout_constraintBottom_toBottomOf="parent"
49
-        app:layout_constraintEnd_toEndOf="parent"
50
-        app:layout_constraintHorizontal_bias="0.494"
51
-        app:layout_constraintStart_toStartOf="parent"
52
-        app:layout_constraintTop_toBottomOf="@+id/editTextNewPassword"
53
-        app:layout_constraintVertical_bias="0.019" />
54
+        android:textColor="@color/textColor2"
55
+        app:layout_constraintEnd_toEndOf="@+id/editTextNewPassword"
56
+        app:layout_constraintStart_toStartOf="@+id/editTextNewPassword"
57
+        app:layout_constraintTop_toBottomOf="@+id/editTextNewPassword" />
54 58
 
55 59
     <Button
56 60
         android:id="@+id/buttonResetPassword"
57
-        android:layout_width="309dp"
58
-        android:layout_height="47dp"
59
-        android:background="@color/colorPrimary"
60
-        android:fontFamily="@font/acme"
61
-        android:text="Reset Password"
62
-        android:textColor="@color/textColor1"
61
+        android:layout_width="0dp"
62
+        android:layout_height="wrap_content"
63
+        android:layout_marginStart="@dimen/horizontalMargin"
64
+        android:layout_marginEnd="@dimen/horizontalMargin"
65
+        android:layout_marginBottom="@dimen/verticalMargin"
66
+        android:background="@drawable/button_background"
67
+        android:fontFamily="sans-serif-black"
68
+        android:text="@string/resetPasswordButtonText"
69
+        android:textColor="@android:color/white"
63 70
         android:textSize="18sp"
64 71
         app:layout_constraintBottom_toBottomOf="parent"
65 72
         app:layout_constraintEnd_toEndOf="parent"
66 73
         app:layout_constraintStart_toStartOf="parent"
67
-        app:layout_constraintTop_toBottomOf="@+id/editTextConfirmPassword"
68
-        app:layout_constraintVertical_bias="0.095" />
74
+        app:layout_constraintTop_toBottomOf="@+id/textViewResetPassword" />
69 75
 </androidx.constraintlayout.widget.ConstraintLayout>

+ 0
- 11
app/src/main/res/layout/content_consent_pdf_viewer.xml View File

@@ -1,11 +0,0 @@
1
-<?xml version="1.0" encoding="utf-8"?>
2
-<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
-    xmlns:app="http://schemas.android.com/apk/res-auto"
4
-    xmlns:tools="http://schemas.android.com/tools"
5
-    android:layout_width="match_parent"
6
-    android:layout_height="match_parent"
7
-    app:layout_behavior="@string/appbar_scrolling_view_behavior"
8
-    tools:context="uprrp.tania.activities.ConsentPdfViewerActivity"
9
-    tools:showIn="@layout/activity_consent_pdf_viewer">
10
-
11
-</androidx.constraintlayout.widget.ConstraintLayout>

+ 5
- 0
app/src/main/res/values/strings.xml View File

@@ -89,4 +89,9 @@
89 89
     <!--  Forgot Password Activity  -->
90 90
     <string name="sendEmailButtonText">Send Email</string>
91 91
     <string name="forgotPasswordDescriptionText">Please provide the email associated to your account so you can reset your password:</string>
92
+    <!--  Reset Password Activity  -->
93
+    <string name="resetPasswordDescriptionText">Reset your Password</string>
94
+    <string name="confirmPasswordButtonHint">Confirm Password</string>
95
+    <string name="newPasswordButtonHint">New Password</string>
96
+    <string name="resetPasswordButtonText">Reset Password</string>
92 97
 </resources>