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
         android:theme="@style/Theme.TANIA"
16
         android:theme="@style/Theme.TANIA"
17
         android:usesCleartextTraffic="true">
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
         <activity android:name=".activities.GettingStartedActivity">
19
         <activity android:name=".activities.GettingStartedActivity">
24
             <intent-filter>
20
             <intent-filter>
25
                 <category android:name="android.intent.category.LAUNCHER" />
21
                 <category android:name="android.intent.category.LAUNCHER" />
81
                 <category android:name="android.intent.category.BROWSABLE" />
77
                 <category android:name="android.intent.category.BROWSABLE" />
82
 
78
 
83
                 <data
79
                 <data
84
-                    android:host="account"
80
+                    android:host="reset_password"
85
                     android:scheme="tania" />
81
                     android:scheme="tania" />
86
             </intent-filter>
82
             </intent-filter>
87
         </activity>
83
         </activity>

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

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
-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
 package uprrp.tania.activities;
1
 package uprrp.tania.activities;
2
 
2
 
3
-import android.content.Intent;
4
-import android.content.SharedPreferences;
5
 import android.os.Bundle;
3
 import android.os.Bundle;
4
+import android.util.Log;
6
 import android.view.MenuItem;
5
 import android.view.MenuItem;
7
 
6
 
8
 import androidx.annotation.NonNull;
7
 import androidx.annotation.NonNull;
48
 
47
 
49
                 Fragment selectedFragment;
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
                 getSupportFragmentManager()
62
                 getSupportFragmentManager()

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

1
-/*************************************************************
2
- * By: Coralys Cubero Rivera
3
- * Date: 2019
4
- *************************************************************/
5
-
6
 package uprrp.tania.activities;
1
 package uprrp.tania.activities;
7
 
2
 
3
+import android.app.ProgressDialog;
8
 import android.content.Intent;
4
 import android.content.Intent;
9
 import android.net.Uri;
5
 import android.net.Uri;
10
 import android.os.Bundle;
6
 import android.os.Bundle;
17
 import androidx.annotation.Nullable;
13
 import androidx.annotation.Nullable;
18
 import androidx.appcompat.app.AppCompatActivity;
14
 import androidx.appcompat.app.AppCompatActivity;
19
 
15
 
20
-import org.json.JSONObject;
21
-
22
 import uprrp.tania.GlobalValues;
16
 import uprrp.tania.GlobalValues;
23
 import uprrp.tania.R;
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
 public class ResetPasswordActivity extends AppCompatActivity {
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
     @Override
26
     @Override
30
     protected void onCreate(@Nullable Bundle savedInstanceState) {
27
     protected void onCreate(@Nullable Bundle savedInstanceState) {
28
+
29
+        // Constructor stuff
31
         super.onCreate(savedInstanceState);
30
         super.onCreate(savedInstanceState);
32
         setContentView(R.layout.activity_reset_password);
31
         setContentView(R.layout.activity_reset_password);
33
 
32
 
33
+        // Fetch experience token from URL (only if we launched this Activity from Browser)
34
         Intent intent = getIntent();
34
         Intent intent = getIntent();
35
-        if(Intent.ACTION_VIEW.equals(intent.getAction())){
35
+        if(Intent.ACTION_VIEW.equals(intent.getAction())) {
36
             Uri uri = intent.getData();
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
             @Override
48
             @Override
50
             public void onClick(View v) {
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
                     e.printStackTrace();
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
             return false;
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
         return true;
49
         return true;

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

40
             return false;
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
         return true;
50
         return true;

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

34
             return false;
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
         return true;
44
         return true;

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

31
         this.myCallback = callback;
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
             Log.e(TAG, "Invalid array length!");
37
             Log.e(TAG, "Invalid array length!");
38
             return false;
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
         return true;
48
         return true;
93
         }
93
         }
94
      */
94
      */
95
     @Override
95
     @Override
96
-    protected String doInBackground(AnsweredAssessmentModel... answeredAssessments) {
96
+    protected String doInBackground(AnsweredAssessmentModel... assessments) {
97
 
97
 
98
         // Validation
98
         // Validation
99
-        if(!validInputs(answeredAssessments)) {
99
+        if(!validInputs(assessments)) {
100
             Log.e(TAG, "Invalid inputs given!");
100
             Log.e(TAG, "Invalid inputs given!");
101
             return null;
101
             return null;
102
         }
102
         }
103
 
103
 
104
         // Extract variables
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
         try {
107
         try {
108
 
108
 

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

36
             return false;
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
         return true;
46
         return true;
123
             e.printStackTrace();
115
             e.printStackTrace();
124
             return null;
116
             return null;
125
         } catch (UnsupportedEncodingException e) {
117
         } catch (UnsupportedEncodingException e) {
126
-            Log.e(TAG, "Couldn't encode consentFormJSON");
118
+            Log.e(TAG, "Couldn't encode consentFormJSON!");
127
             e.printStackTrace();
119
             e.printStackTrace();
128
             return null;
120
             return null;
129
         } catch(Exception e) {
121
         } catch(Exception e) {

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

34
             return false;
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
         return true;
44
         return true;

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

34
             return false;
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
         return true;
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
     @Override
57
     @Override
49
     protected String doInBackground(String... strings) {
58
     protected String doInBackground(String... strings) {
50
 
59
 

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

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
             return false;
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
         return true;
47
         return true;

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

1
 <?xml version="1.0" encoding="utf-8"?>
1
 <?xml version="1.0" encoding="utf-8"?>
2
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
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
 </selector>
7
 </selector>

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

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
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
2
 <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
3
     xmlns:app="http://schemas.android.com/apk/res-auto"
3
     xmlns:app="http://schemas.android.com/apk/res-auto"
4
     xmlns:tools="http://schemas.android.com/tools"
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
     <TextView
9
     <TextView
9
         android:id="@+id/textViewResetPassword"
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
         android:textAlignment="center"
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
         app:layout_constraintEnd_toEndOf="parent"
23
         app:layout_constraintEnd_toEndOf="parent"
18
-        app:layout_constraintHorizontal_bias="0.495"
19
         app:layout_constraintStart_toStartOf="parent"
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
     <EditText
27
     <EditText
24
         android:id="@+id/editTextNewPassword"
28
         android:id="@+id/editTextNewPassword"
25
-        android:layout_width="wrap_content"
29
+        android:layout_width="0dp"
26
         android:layout_height="wrap_content"
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
         android:ems="10"
36
         android:ems="10"
28
-        android:fontFamily="@font/acme"
29
-        android:hint="New password"
37
+        android:hint="@string/newPasswordButtonHint"
30
         android:inputType="textPassword"
38
         android:inputType="textPassword"
31
-        android:textAlignment="center"
32
-        app:layout_constraintBottom_toBottomOf="parent"
39
+        android:textColor="@color/textColor2"
33
         app:layout_constraintEnd_toEndOf="parent"
40
         app:layout_constraintEnd_toEndOf="parent"
34
-        app:layout_constraintHorizontal_bias="0.497"
35
         app:layout_constraintStart_toStartOf="parent"
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
     <EditText
44
     <EditText
40
         android:id="@+id/editTextConfirmPassword"
45
         android:id="@+id/editTextConfirmPassword"
41
-        android:layout_width="wrap_content"
46
+        android:layout_width="0dp"
42
         android:layout_height="wrap_content"
47
         android:layout_height="wrap_content"
48
+        android:layout_marginTop="16dp"
49
+        android:autofillHints="AUTOFILL_HINT_PASSWORD"
50
+        android:backgroundTint="@color/colorPrimary"
43
         android:ems="10"
51
         android:ems="10"
44
-        android:fontFamily="@font/acme"
45
-        android:hint="Confirm password"
52
+        android:hint="@string/confirmPasswordButtonHint"
46
         android:inputType="textPassword"
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
     <Button
59
     <Button
56
         android:id="@+id/buttonResetPassword"
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
         android:textSize="18sp"
70
         android:textSize="18sp"
64
         app:layout_constraintBottom_toBottomOf="parent"
71
         app:layout_constraintBottom_toBottomOf="parent"
65
         app:layout_constraintEnd_toEndOf="parent"
72
         app:layout_constraintEnd_toEndOf="parent"
66
         app:layout_constraintStart_toStartOf="parent"
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
 </androidx.constraintlayout.widget.ConstraintLayout>
75
 </androidx.constraintlayout.widget.ConstraintLayout>

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

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
     <!--  Forgot Password Activity  -->
89
     <!--  Forgot Password Activity  -->
90
     <string name="sendEmailButtonText">Send Email</string>
90
     <string name="sendEmailButtonText">Send Email</string>
91
     <string name="forgotPasswordDescriptionText">Please provide the email associated to your account so you can reset your password:</string>
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
 </resources>
97
 </resources>