Browse Source

Refactored AccountRecoveryActivity. Changed default activity to GettingStarted. Cleaned up redirection logic (in case user starts in other activities). Renamed theme. Validation added to background tasks.

Víctor Hernández 3 years ago
parent
commit
cf183642fa

+ 12
- 12
app/src/main/AndroidManifest.xml View File

13
         android:label="TANIA"
13
         android:label="TANIA"
14
         android:roundIcon="@mipmap/ic_launcher"
14
         android:roundIcon="@mipmap/ic_launcher"
15
         android:supportsRtl="true"
15
         android:supportsRtl="true"
16
-        android:theme="@style/Theme.MarleApp"
16
+        android:theme="@style/Theme.TANIA"
17
         android:usesCleartextTraffic="true">
17
         android:usesCleartextTraffic="true">
18
 
18
 
19
         <activity
19
         <activity
20
             android:name=".activities.ConsentPdfViewerActivity"
20
             android:name=".activities.ConsentPdfViewerActivity"
21
             android:label="@string/title_activity_consent_pdf_viewer"
21
             android:label="@string/title_activity_consent_pdf_viewer"
22
-            android:theme="@style/Theme.MarleApp.NoActionBar" />
23
-        <activity android:name=".activities.GettingStartedActivity" />
24
-        <activity android:name=".activities.MainActivity">
22
+            android:theme="@style/Theme.TANIA.NoActionBar" />
23
+        <activity android:name=".activities.GettingStartedActivity">
25
             <intent-filter>
24
             <intent-filter>
26
                 <category android:name="android.intent.category.LAUNCHER" />
25
                 <category android:name="android.intent.category.LAUNCHER" />
27
                 <action android:name="android.intent.action.MAIN" />
26
                 <action android:name="android.intent.action.MAIN" />
28
             </intent-filter>
27
             </intent-filter>
29
-
28
+        </activity>
29
+        <activity android:name=".activities.MainActivity">
30
             <intent-filter>
30
             <intent-filter>
31
                 <action android:name="android.intent.action.VIEW" />
31
                 <action android:name="android.intent.action.VIEW" />
32
 
32
 
41
         <activity
41
         <activity
42
             android:name="org.researchstack.backbone.ui.ViewTaskActivity"
42
             android:name="org.researchstack.backbone.ui.ViewTaskActivity"
43
             android:parentActivityName=".activities.MainActivity"
43
             android:parentActivityName=".activities.MainActivity"
44
-            android:theme="@style/Theme.MarleApp"
44
+            android:theme="@style/Theme.TANIA"
45
             android:windowSoftInputMode="adjustResize" />
45
             android:windowSoftInputMode="adjustResize" />
46
         <activity
46
         <activity
47
             android:name="org.researchstack.backbone.ui.ViewWebDocumentActivity"
47
             android:name="org.researchstack.backbone.ui.ViewWebDocumentActivity"
48
             android:label="@string/appName"
48
             android:label="@string/appName"
49
             android:parentActivityName=".activities.MainActivity"
49
             android:parentActivityName=".activities.MainActivity"
50
-            android:theme="@style/Theme.MarleApp" />
50
+            android:theme="@style/Theme.TANIA" />
51
         <activity
51
         <activity
52
             android:name=".activities.RegisterActivity"
52
             android:name=".activities.RegisterActivity"
53
             android:parentActivityName=".activities.GettingStartedActivity">
53
             android:parentActivityName=".activities.GettingStartedActivity">
56
             </intent-filter>
56
             </intent-filter>
57
         </activity>
57
         </activity>
58
         <activity
58
         <activity
59
-            android:name=".activities.LoginActivity"
59
+            android:name=".activities.AccountRecoveryActivity"
60
             android:parentActivityName=".activities.GettingStartedActivity">
60
             android:parentActivityName=".activities.GettingStartedActivity">
61
             <intent-filter>
61
             <intent-filter>
62
                 <category android:name="android.intent.category.DEFAULT" />
62
                 <category android:name="android.intent.category.DEFAULT" />
64
         </activity>
64
         </activity>
65
         <activity
65
         <activity
66
             android:name=".activities.ForgotPasswordActivity"
66
             android:name=".activities.ForgotPasswordActivity"
67
-            android:parentActivityName=".activities.LoginActivity"
68
-            android:theme="@style/Theme.MarleApp">
67
+            android:parentActivityName=".activities.AccountRecoveryActivity"
68
+            android:theme="@style/Theme.TANIA">
69
             <intent-filter>
69
             <intent-filter>
70
                 <category android:name="android.intent.category.DEFAULT" />
70
                 <category android:name="android.intent.category.DEFAULT" />
71
             </intent-filter>
71
             </intent-filter>
73
         <activity
73
         <activity
74
             android:name=".activities.ResetPasswordActivity"
74
             android:name=".activities.ResetPasswordActivity"
75
             android:parentActivityName=".activities.ResetPasswordActivity"
75
             android:parentActivityName=".activities.ResetPasswordActivity"
76
-            android:theme="@style/Theme.MarleApp">
76
+            android:theme="@style/Theme.TANIA">
77
             <intent-filter>
77
             <intent-filter>
78
                 <action android:name="android.intent.action.VIEW" />
78
                 <action android:name="android.intent.action.VIEW" />
79
 
79
 
88
         <activity
88
         <activity
89
             android:name=".activities.ExperienceRegistrationActivity"
89
             android:name=".activities.ExperienceRegistrationActivity"
90
             android:parentActivityName=".activities.ExperienceRegistrationActivity"
90
             android:parentActivityName=".activities.ExperienceRegistrationActivity"
91
-            android:theme="@style/Theme.MarleApp">
91
+            android:theme="@style/Theme.TANIA">
92
             <intent-filter>
92
             <intent-filter>
93
                 <action android:name="android.intent.action.VIEW" />
93
                 <action android:name="android.intent.action.VIEW" />
94
 
94
 

+ 18
- 0
app/src/main/java/uprrp/tania/App.java View File

1
 package uprrp.tania;
1
 package uprrp.tania;
2
 
2
 
3
 import android.app.Application;
3
 import android.app.Application;
4
+import android.content.Intent;
5
+import android.content.SharedPreferences;
6
+import android.os.Build;
4
 import android.util.Log;
7
 import android.util.Log;
5
 import android.widget.Toast;
8
 import android.widget.Toast;
6
 
9
 
7
 import androidx.annotation.NonNull;
10
 import androidx.annotation.NonNull;
11
+import androidx.annotation.RequiresApi;
8
 
12
 
9
 import com.amazonaws.auth.CognitoCachingCredentialsProvider;
13
 import com.amazonaws.auth.CognitoCachingCredentialsProvider;
10
 import com.amazonaws.regions.Regions;
14
 import com.amazonaws.regions.Regions;
22
 import org.researchstack.backbone.storage.file.SimpleFileAccess;
26
 import org.researchstack.backbone.storage.file.SimpleFileAccess;
23
 import org.researchstack.backbone.storage.file.UnencryptedProvider;
27
 import org.researchstack.backbone.storage.file.UnencryptedProvider;
24
 
28
 
29
+import uprrp.tania.activities.GettingStartedActivity;
30
+
25
 public class App extends Application {
31
 public class App extends Application {
26
 
32
 
27
     private static final String TAG = "App";
33
     private static final String TAG = "App";
79
                     }
85
                     }
80
                 });
86
                 });
81
 
87
 
88
+        // If user hasn't already registered, redirect accordingly,
89
+        // JUST IN CASE user starts non-default activity from somewhere else (like a browser)
90
+        // TODO: find a way to not redirect twice to GettingStarted
91
+        SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
92
+        boolean needsToRegister = prefs.getBoolean("needsToRegister", true);
93
+        if(needsToRegister) {
94
+            Log.wtf(TAG, "Redirecting to GettingStarted");
95
+            Intent intent = new Intent(this, GettingStartedActivity.class);
96
+            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
97
+            startActivity(intent);
98
+        }
99
+
82
     }
100
     }
83
 }
101
 }

+ 0
- 137
app/src/main/java/uprrp/tania/SendLoginToServer.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.content.SharedPreferences;
11
-import android.content.res.Resources;
12
-import android.os.AsyncTask;
13
-import android.os.Environment;
14
-import android.util.Base64;
15
-import android.util.Log;
16
-import android.widget.Toast;
17
-
18
-import java.io.BufferedReader;
19
-import java.io.FileOutputStream;
20
-import java.io.IOException;
21
-import java.io.InputStreamReader;
22
-import java.io.OutputStreamWriter;
23
-import java.io.UnsupportedEncodingException;
24
-import java.net.URL;
25
-import java.net.URLConnection;
26
-import java.net.URLEncoder;
27
-
28
-import uprrp.tania.activities.MainActivity;
29
-
30
-public class SendLoginToServer extends AsyncTask<String, String, String> {
31
-
32
-    private static final String loginBaseURL = "https://tania.uprrp.edu/recoverAccount.php";
33
-    private Context context;
34
-
35
-    public SendLoginToServer(Context context){
36
-        this.context = context.getApplicationContext();
37
-    }
38
-
39
-    @Override
40
-    protected String doInBackground(String... strings) {
41
-
42
-        String json  = null;
43
-        try {
44
-            json = URLEncoder.encode("data", "UTF-8") + "=" + URLEncoder.encode(strings[0], "UTF-8");
45
-            Log.d("RECOVER ACCOUNT", json);
46
-        } catch (UnsupportedEncodingException e) {
47
-            Log.e("RECOVER ACCOUNT ERROR", e.getMessage());
48
-        }
49
-
50
-        String text = "";
51
-        BufferedReader reader = null;
52
-
53
-        // Send data
54
-        try
55
-        {
56
-            // Defined URL  where to send data
57
-            URL url = new URL(loginBaseURL);
58
-
59
-            // Send POST data request
60
-            URLConnection conn = url.openConnection();
61
-            conn.setDoOutput(true);
62
-            OutputStreamWriter wr = new OutputStreamWriter(conn.getOutputStream());
63
-            assert json != null;
64
-            wr.write(json);
65
-            wr.flush();
66
-
67
-            // Get the server response
68
-            reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
69
-            StringBuilder sb = new StringBuilder();
70
-            String line;
71
-
72
-            // Read Server Response
73
-            while((line = reader.readLine()) != null)
74
-            {
75
-                // Append server response in string
76
-                sb.append(line).append("\n");
77
-            }
78
-
79
-            text = sb.toString();
80
-        }
81
-        catch(Exception ex) {
82
-            Log.e("RECOVER ACCOUNT ERROR", ex.getMessage());
83
-        }
84
-        finally
85
-        {
86
-            try
87
-            {
88
-//                assert reader != null;
89
-                reader.close();
90
-            }
91
-            catch(Exception ex) {
92
-                Log.e("RECOVER ACCOUNT ERROR", ex.getMessage());
93
-            }
94
-        }
95
-
96
-        return text;
97
-
98
-    }
99
-
100
-    @Override
101
-    protected void onPostExecute(String s) {
102
-        Log.d("RECOVER ACCOUNT RESPOND", "The server's response is: " + s);
103
-
104
-        String se = s.substring(0, 5);
105
-        if (!se.equals("Error")) {
106
-
107
-            try {
108
-
109
-                FileOutputStream consentForm = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + "/consent-tania-app.pdf");
110
-
111
-                byte[] consentBytes = Base64.decode(s, Base64.NO_WRAP);
112
-                consentForm.write(consentBytes);
113
-                consentForm.close();
114
-
115
-                SharedPreferences prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE);
116
-                SharedPreferences.Editor editor = prefs.edit();
117
-                editor.putBoolean("needsToRegister", false);
118
-                editor.apply();
119
-
120
-                Intent intent = new Intent(context, MainActivity.class);
121
-                intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
122
-                context.startActivity(intent);
123
-
124
-            } catch (IOException e) {
125
-                Log.e("RECOVER CONSENT LOGIN", "File not found!");
126
-            }
127
-        }
128
-
129
-        else
130
-            {
131
-                Toast.makeText(context, "Can't recover account! Try again later. ", Toast.LENGTH_LONG).show();
132
-            }
133
-        }
134
-
135
-
136
-
137
-}

+ 135
- 0
app/src/main/java/uprrp/tania/activities/AccountRecoveryActivity.java View File

1
+package uprrp.tania.activities;
2
+
3
+import android.app.ProgressDialog;
4
+import android.content.Context;
5
+import android.content.Intent;
6
+import android.content.SharedPreferences;
7
+import android.os.Bundle;
8
+import android.os.Environment;
9
+import android.util.Base64;
10
+import android.util.Log;
11
+import android.view.View;
12
+import android.widget.Button;
13
+import android.widget.EditText;
14
+import android.widget.Toast;
15
+
16
+import androidx.appcompat.app.AppCompatActivity;
17
+
18
+import java.io.FileNotFoundException;
19
+import java.io.FileOutputStream;
20
+import java.io.IOException;
21
+
22
+import uprrp.tania.GlobalValues;
23
+import uprrp.tania.R;
24
+import uprrp.tania.networking.SendAccountRecovery;
25
+import uprrp.tania.utils.URLEventListener;
26
+
27
+public class AccountRecoveryActivity extends AppCompatActivity {
28
+
29
+    private static final String TAG = "AccountRecoveryActivity";
30
+
31
+    @Override
32
+    protected void onCreate(Bundle savedInstanceState) {
33
+
34
+        // Start constructor
35
+        super.onCreate(savedInstanceState);
36
+        setContentView(R.layout.activity_account_recovery);
37
+
38
+        // Change all caps text to normal capitalization and add onClick listeners
39
+        final Button recoverButton = findViewById(R.id.recoverButton);
40
+        final Button forgotPasswordButton = findViewById(R.id.forgotPasswordButton);
41
+        recoverButton.setTransformationMethod(null); // TODO: this is a workaround I found, any other acceptable solution is welcome
42
+        forgotPasswordButton.setTransformationMethod(null); // TODO: this is a workaround I found, any other acceptable solution is welcome
43
+        recoverButton.setOnClickListener(new View.OnClickListener() {
44
+            @Override
45
+            public void onClick(View v) {
46
+                sendAccountRecoveryRequest();
47
+            }
48
+        });
49
+        forgotPasswordButton.setOnClickListener(new View.OnClickListener() {
50
+            @Override
51
+            public void onClick(View v) {
52
+                Intent intent = new Intent(AccountRecoveryActivity.this, ForgotPasswordActivity.class);
53
+                startActivity(intent);
54
+            }
55
+        });
56
+
57
+    }
58
+
59
+    private void sendAccountRecoveryRequest() {
60
+
61
+        final EditText emailText = findViewById(R.id.emailTextRecover);
62
+        final EditText passwordText = findViewById(R.id.passwordTextRecover);
63
+
64
+        // Email and password are needed (make sure user knows); else, proceed
65
+        if(emailText.getText().toString().equals("") || passwordText.getText().toString().equals("")) {
66
+            Toast.makeText(AccountRecoveryActivity.this, "All fields are needed!", Toast.LENGTH_LONG).show();
67
+        } else {
68
+
69
+            // Initiate progress dialog
70
+            // TODO: find substitute for this deprecated dialog box
71
+            final ProgressDialog progressDialog = ProgressDialog.show(AccountRecoveryActivity.this,
72
+                    "Recovering Account",
73
+                    "This shouldn't take long");
74
+
75
+            // Send request to server
76
+            SendAccountRecovery accountRecoveryTask = new SendAccountRecovery(new URLEventListener() {
77
+
78
+                @Override
79
+                public void onSuccess(String response) {
80
+
81
+                    progressDialog.dismiss();
82
+                    restoreConsentForm(response);
83
+
84
+                    // Change user preferences to reflect login
85
+                    Context context = AccountRecoveryActivity.this;
86
+                    SharedPreferences prefs = context.getSharedPreferences("prefs", Context.MODE_PRIVATE);
87
+                    SharedPreferences.Editor editor = prefs.edit();
88
+                    editor.putBoolean("needsToRegister", false);
89
+                    editor.apply();
90
+
91
+                    // Start MainActivity
92
+                    Intent intent = new Intent(context, MainActivity.class);
93
+                    intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
94
+                    context.startActivity(intent);
95
+                    Toast.makeText(getApplicationContext(), "Login successful!", Toast.LENGTH_LONG).show();
96
+
97
+                }
98
+
99
+                @Override
100
+                public void onFailure(Exception e) {
101
+                    progressDialog.dismiss();
102
+                    Toast.makeText(AccountRecoveryActivity.this, "Couldn't recover account!\nTry again later with the correct credentials...", Toast.LENGTH_LONG).show();
103
+                    Log.e(TAG, "Error occurred while sending account recovery request to server...");
104
+                    e.printStackTrace();
105
+                }
106
+
107
+            });
108
+
109
+            // Start task
110
+            String deviceToken = GlobalValues.getInstance().getDeviceToken();
111
+            String email = emailText.getText().toString();
112
+            String password = passwordText.getText().toString();
113
+            accountRecoveryTask.execute(deviceToken, email, password);
114
+
115
+        }
116
+
117
+    }
118
+
119
+    // TODO: IO should be moved to a background task
120
+    private void restoreConsentForm(String response) {
121
+        try {
122
+            byte[] consentBytes = Base64.decode(response, Base64.NO_WRAP);
123
+            FileOutputStream consentForm = new FileOutputStream(Environment.getExternalStorageDirectory().getPath() + getString(R.string.consentFileName));
124
+            consentForm.write(consentBytes);
125
+            consentForm.close();
126
+        } catch (FileNotFoundException e) {
127
+            Log.e(TAG, "Couldn't find consent form (we were going to write to it)!");
128
+            e.printStackTrace();
129
+        } catch (IOException e) {
130
+            Log.e(TAG, "Couldn't rewrite consent form!");
131
+            e.printStackTrace();
132
+        }
133
+    }
134
+
135
+}

+ 17
- 7
app/src/main/java/uprrp/tania/activities/ExperienceRegistrationActivity.java View File

3
 import android.app.ProgressDialog;
3
 import android.app.ProgressDialog;
4
 import android.content.Context;
4
 import android.content.Context;
5
 import android.content.Intent;
5
 import android.content.Intent;
6
+import android.content.SharedPreferences;
6
 import android.net.Uri;
7
 import android.net.Uri;
7
 import android.os.Bundle;
8
 import android.os.Bundle;
8
 import android.util.Log;
9
 import android.util.Log;
19
 
20
 
20
 import uprrp.tania.GlobalValues;
21
 import uprrp.tania.GlobalValues;
21
 import uprrp.tania.R;
22
 import uprrp.tania.R;
22
-import uprrp.tania.URLEventListener;
23
+import uprrp.tania.utils.URLEventListener;
23
 import uprrp.tania.networking.SendExperienceRegistration;
24
 import uprrp.tania.networking.SendExperienceRegistration;
24
 
25
 
25
 public class ExperienceRegistrationActivity  extends AppCompatActivity implements Observer {
26
 public class ExperienceRegistrationActivity  extends AppCompatActivity implements Observer {
26
 
27
 
27
     private static final String TAG = "ExperienceRegistrationActivity";
28
     private static final String TAG = "ExperienceRegistrationActivity";
28
-    private String EXPERIENCE_ID;
29
+    private String EXPERIENCE_TOKEN;
29
 
30
 
30
     @Override
31
     @Override
31
     protected void onCreate(@Nullable Bundle savedInstanceState) {
32
     protected void onCreate(@Nullable Bundle savedInstanceState) {
34
         super.onCreate(savedInstanceState);
35
         super.onCreate(savedInstanceState);
35
         setContentView(R.layout.activity_experience_registration);
36
         setContentView(R.layout.activity_experience_registration);
36
 
37
 
37
-        // Fetch experience ID from URL (only if we launched this Activity from Browser)
38
+
39
+        // Fetch experience token from URL (only if we launched this Activity from Browser)
38
         Intent intent = getIntent();
40
         Intent intent = getIntent();
39
         if(Intent.ACTION_VIEW.equals(intent.getAction())) {
41
         if(Intent.ACTION_VIEW.equals(intent.getAction())) {
40
             Uri uri = intent.getData();
42
             Uri uri = intent.getData();
41
             assert uri != null; // TODO: figure out if this causes crashes...
43
             assert uri != null; // TODO: figure out if this causes crashes...
42
-            EXPERIENCE_ID = uri.getQueryParameter("id");
43
-            Log.wtf("EXPERIENCE ID", EXPERIENCE_ID);
44
+            EXPERIENCE_TOKEN = uri.getQueryParameter("id");
45
+            Log.d(TAG, "Experience Token is " + EXPERIENCE_TOKEN);
46
+        } else {
47
+            Log.wtf(TAG, "Activity started from somewhere other than the browser!");
48
+            disableInteraction();
44
         }
49
         }
45
 
50
 
51
+
46
         // Listen for device token changes
52
         // Listen for device token changes
47
         this.startObservingGlobals();
53
         this.startObservingGlobals();
48
 
54
 
55
+
49
         // Disable interaction initially while token is being fetched
56
         // Disable interaction initially while token is being fetched
50
         if(GlobalValues.getInstance().getDeviceToken() == null) {
57
         if(GlobalValues.getInstance().getDeviceToken() == null) {
51
-            Log.wtf("EXPERIENCE ID", "DISABLING");
52
             disableInteractionTemporarily();
58
             disableInteractionTemporarily();
53
         } else {
59
         } else {
54
             enableInteraction();
60
             enableInteraction();
55
         }
61
         }
56
 
62
 
63
+
57
         // Change all caps text to normal capitalization and add onClick listener
64
         // Change all caps text to normal capitalization and add onClick listener
58
         final Button experienceRegistrationButton = findViewById(R.id.buttonEnterExperience);
65
         final Button experienceRegistrationButton = findViewById(R.id.buttonEnterExperience);
59
         experienceRegistrationButton.setTransformationMethod(null); // TODO: this is a workaround I found, any other acceptable solution is welcome
66
         experienceRegistrationButton.setTransformationMethod(null); // TODO: this is a workaround I found, any other acceptable solution is welcome
140
             }
147
             }
141
         });
148
         });
142
 
149
 
143
-        experienceRegistrationTask.execute(GlobalValues.getInstance().getDeviceToken(), this.EXPERIENCE_ID);
150
+        // Start task
151
+        String deviceToken = GlobalValues.getInstance().getDeviceToken();
152
+        String experienceToken = this.EXPERIENCE_TOKEN;
153
+        experienceRegistrationTask.execute(deviceToken, experienceToken);
144
 
154
 
145
         // UNCOMMENT THIS FOR TESTING (REMEMBER TO COMMENT .execute() LINE)
155
         // UNCOMMENT THIS FOR TESTING (REMEMBER TO COMMENT .execute() LINE)
146
         /*
156
         /*

+ 12
- 2
app/src/main/java/uprrp/tania/activities/GettingStartedActivity.java View File

74
         String[] permissions = { Manifest.permission.WRITE_EXTERNAL_STORAGE };
74
         String[] permissions = { Manifest.permission.WRITE_EXTERNAL_STORAGE };
75
         requestPermissions(permissions, 1);
75
         requestPermissions(permissions, 1);
76
 
76
 
77
+        // If user is already logged in, go to MainActivity
78
+        SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
79
+        boolean needsToRegister = prefs.getBoolean("needsToRegister", true);
80
+        if(!needsToRegister) {
81
+            Intent intent = new Intent(GettingStartedActivity.this, MainActivity.class);
82
+            startActivity(intent);
83
+            return;
84
+        }
85
+
77
         // Attach onClick listeners to buttons
86
         // Attach onClick listeners to buttons
78
         Button createAccountButton = findViewById(R.id.buttonCreateAccount);
87
         Button createAccountButton = findViewById(R.id.buttonCreateAccount);
79
         Button loginAccountButton = findViewById(R.id.buttonRecoverAccount);
88
         Button loginAccountButton = findViewById(R.id.buttonRecoverAccount);
88
         loginAccountButton.setOnClickListener(new View.OnClickListener() {
97
         loginAccountButton.setOnClickListener(new View.OnClickListener() {
89
             @Override
98
             @Override
90
             public void onClick(View v) {
99
             public void onClick(View v) {
91
-                Intent loginAccountIntent = new Intent(GettingStartedActivity.this, LoginActivity.class);
100
+                Intent loginAccountIntent = new Intent(GettingStartedActivity.this, AccountRecoveryActivity.class);
92
                 startActivity(loginAccountIntent);
101
                 startActivity(loginAccountIntent);
93
             }
102
             }
94
         });
103
         });
115
 
124
 
116
 
125
 
117
     // TODO: decide which parts in this function to move to a background task
126
     // TODO: decide which parts in this function to move to a background task
127
+    // TODO: define a model for the JSON and use Gson to encode it
118
     private void processConsentResult(TaskResult result) {
128
     private void processConsentResult(TaskResult result) {
119
 
129
 
120
         boolean consented = (boolean) result.getStepResult(CONSENT_DOC).getResult();
130
         boolean consented = (boolean) result.getStepResult(CONSENT_DOC).getResult();
328
 
338
 
329
     }
339
     }
330
 
340
 
331
-
341
+    // TODO: IO should be moved to a background task
332
     private String createPdf(byte[] signatureBytes, String consentDate) {
342
     private String createPdf(byte[] signatureBytes, String consentDate) {
333
 
343
 
334
         try {
344
         try {

+ 0
- 78
app/src/main/java/uprrp/tania/activities/LoginActivity.java View File

1
-/*************************************************************
2
- * By: Coralys Cubero Rivera
3
- * Date: 2019
4
- *************************************************************/
5
-
6
-package uprrp.tania.activities;
7
-
8
-import android.content.Intent;
9
-import android.os.Bundle;
10
-import android.util.Log;
11
-import android.view.View;
12
-import android.widget.Button;
13
-import android.widget.EditText;
14
-import android.widget.Toast;
15
-
16
-import androidx.appcompat.app.AppCompatActivity;
17
-
18
-import org.json.JSONException;
19
-import org.json.JSONObject;
20
-
21
-import uprrp.tania.GlobalValues;
22
-import uprrp.tania.R;
23
-import uprrp.tania.SendLoginToServer;
24
-
25
-
26
-public class LoginActivity extends AppCompatActivity {
27
-
28
-    private JSONObject recoverAccount = new JSONObject();
29
-
30
-    @Override
31
-    protected void onCreate(Bundle savedInstanceState) {
32
-        super.onCreate(savedInstanceState);
33
-        setContentView(R.layout.activity_login);
34
-
35
-        final EditText emailText = findViewById(R.id.emailTextRecover);
36
-        final EditText passwordText = findViewById(R.id.passwordTextRecover);
37
-
38
-        final Button recoverButton = findViewById(R.id.recoverButton);
39
-        recoverButton.setOnClickListener(new View.OnClickListener() {
40
-            @Override
41
-            public void onClick(View v) {
42
-                try {
43
-
44
-                    //As long as the email and password have been provided, then we can log in
45
-                    if (!emailText.getText().toString().equals("")&& !passwordText.getText().toString().equals("")) {
46
-                        recoverAccount.put("email", emailText.getText());
47
-                        recoverAccount.put("password", passwordText.getText());
48
-                        recoverAccount.put("token", GlobalValues.getInstance().getDeviceToken());
49
-
50
-                        //Log.d("LOGIN ACCOUNT JSON", recoverAccount.toString());
51
-                        new SendLoginToServer(getApplicationContext()).execute(recoverAccount.toString());
52
-
53
-                    } else {
54
-                        Toast.makeText(LoginActivity.this, "All fields are needed to complete the login.", Toast.LENGTH_LONG).show();
55
-                    }
56
-
57
-
58
-                } catch (JSONException e) {
59
-                    Log.e("LOGIN ACCOUNT ERROR", e.getMessage());
60
-
61
-                }
62
-            }
63
-
64
-        });
65
-
66
-        //If by some chance they don't remember their password, then lets take them to the recovery activity
67
-        final Button forgotPasswordButton = findViewById(R.id.forgotPasswordButton);
68
-        forgotPasswordButton.setOnClickListener(new View.OnClickListener() {
69
-            @Override
70
-            public void onClick(View v) {
71
-
72
-                Intent needsRegisterIntent = new Intent(LoginActivity.this, ForgotPasswordActivity.class);
73
-                startActivity(needsRegisterIntent);
74
-
75
-            }
76
-        });
77
-    }
78
-}

+ 0
- 10
app/src/main/java/uprrp/tania/activities/MainActivity.java View File

31
         setContentView(R.layout.activity_main);
31
         setContentView(R.layout.activity_main);
32
 
32
 
33
 
33
 
34
-        // We need to know if the user has already registered, otherwise they need to do that first
35
-        SharedPreferences prefs = getSharedPreferences("prefs", MODE_PRIVATE);
36
-        boolean needsToRegister = prefs.getBoolean("needsToRegister", true);
37
-        if(needsToRegister) {
38
-            Intent needsRegisterIntent = new Intent(this, GettingStartedActivity.class);
39
-            startActivity(needsRegisterIntent);
40
-            return;
41
-        }
42
-
43
-
44
         // Create toolbar
34
         // Create toolbar
45
         Toolbar toolbar = findViewById(R.id.toolbar);
35
         Toolbar toolbar = findViewById(R.id.toolbar);
46
         setSupportActionBar(toolbar);
36
         setSupportActionBar(toolbar);

+ 1
- 1
app/src/main/java/uprrp/tania/fragments/AssessmentsFragment.java View File

38
 
38
 
39
 import uprrp.tania.GlobalValues;
39
 import uprrp.tania.GlobalValues;
40
 import uprrp.tania.R;
40
 import uprrp.tania.R;
41
-import uprrp.tania.URLEventListener;
41
+import uprrp.tania.utils.URLEventListener;
42
 import uprrp.tania.models.AnsweredAssessmentModel;
42
 import uprrp.tania.models.AnsweredAssessmentModel;
43
 import uprrp.tania.models.AnsweredQuestionModel;
43
 import uprrp.tania.models.AnsweredQuestionModel;
44
 import uprrp.tania.models.AssessmentModel;
44
 import uprrp.tania.models.AssessmentModel;

+ 1
- 1
app/src/main/java/uprrp/tania/fragments/WithdrawFragment.java View File

25
 
25
 
26
 import uprrp.tania.GlobalValues;
26
 import uprrp.tania.GlobalValues;
27
 import uprrp.tania.R;
27
 import uprrp.tania.R;
28
-import uprrp.tania.URLEventListener;
28
+import uprrp.tania.utils.URLEventListener;
29
 import uprrp.tania.activities.GettingStartedActivity;
29
 import uprrp.tania.activities.GettingStartedActivity;
30
 import uprrp.tania.networking.SendWithdrawal;
30
 import uprrp.tania.networking.SendWithdrawal;
31
 
31
 

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

18
 
18
 
19
 import javax.net.ssl.HttpsURLConnection;
19
 import javax.net.ssl.HttpsURLConnection;
20
 
20
 
21
-import uprrp.tania.URLEventListener;
21
+import uprrp.tania.utils.URLEventListener;
22
 import uprrp.tania.models.AssessmentModel;
22
 import uprrp.tania.models.AssessmentModel;
23
 import uprrp.tania.models.EmptyAssessmentModel;
23
 import uprrp.tania.models.EmptyAssessmentModel;
24
 
24
 

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

19
 
19
 
20
 import javax.net.ssl.HttpsURLConnection;
20
 import javax.net.ssl.HttpsURLConnection;
21
 
21
 
22
-import uprrp.tania.URLEventListener;
22
+import uprrp.tania.utils.URLEventListener;
23
 import uprrp.tania.models.EmptyUserStatusModel;
23
 import uprrp.tania.models.EmptyUserStatusModel;
24
 import uprrp.tania.models.UserStatusModel;
24
 import uprrp.tania.models.UserStatusModel;
25
 
25
 

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

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

18
 
18
 
19
 import javax.net.ssl.HttpsURLConnection;
19
 import javax.net.ssl.HttpsURLConnection;
20
 
20
 
21
-import uprrp.tania.URLEventListener;
21
+import uprrp.tania.utils.URLEventListener;
22
 import uprrp.tania.models.AnsweredAssessmentModel;
22
 import uprrp.tania.models.AnsweredAssessmentModel;
23
 
23
 
24
 public class SendAnswers extends AsyncTask<AnsweredAssessmentModel, Void, String> {
24
 public class SendAnswers extends AsyncTask<AnsweredAssessmentModel, Void, String> {

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

15
 
15
 
16
 import javax.net.ssl.HttpsURLConnection;
16
 import javax.net.ssl.HttpsURLConnection;
17
 
17
 
18
-import uprrp.tania.URLEventListener;
18
+import uprrp.tania.utils.URLEventListener;
19
 
19
 
20
 public class SendExperienceRegistration extends AsyncTask<String, String, String> {
20
 public class SendExperienceRegistration extends AsyncTask<String, String, String> {
21
 
21
 
27
         this.myCallback = callback;
27
         this.myCallback = callback;
28
     }
28
     }
29
 
29
 
30
+    private boolean validInputs(String... strings) {
31
+
32
+        if(strings.length != 2) {
33
+            Log.e(TAG, "Invalid string array length!");
34
+            return false;
35
+        }
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;
46
+        }
47
+
48
+        return true;
49
+
50
+    }
51
+
30
     // TODO: instead of making a normal POST request with
52
     // TODO: instead of making a normal POST request with
31
     //  the body data=<JSON>, we should just send the JSON itself
53
     //  the body data=<JSON>, we should just send the JSON itself
32
     //  This is adding unnecessary layers of complexity when decoding AND encoding
54
     //  This is adding unnecessary layers of complexity when decoding AND encoding
40
     @Override
62
     @Override
41
     protected String doInBackground(String... strings) {
63
     protected String doInBackground(String... strings) {
42
 
64
 
43
-        String deviceToken = strings[0];
44
-        String experienceID = strings[1];
45
-
46
-        if(experienceID == null) {
47
-            Log.e(TAG, "Encountered null experience ID!");
48
-            return null;
49
-        } else if (deviceToken == null) {
50
-            Log.e(TAG, "Encountered null device token!");
65
+        // Validation
66
+        if(!validInputs(strings)) {
67
+            Log.e(TAG, "Invalid inputs given!");
51
             return null;
68
             return null;
52
         }
69
         }
53
 
70
 
71
+        // Extract variables
72
+        String deviceToken = strings[0];
73
+        String experienceID = strings[1];
74
+
54
         try {
75
         try {
55
 
76
 
56
             // Create JSON
77
             // Create JSON

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

18
 
18
 
19
 import javax.net.ssl.HttpsURLConnection;
19
 import javax.net.ssl.HttpsURLConnection;
20
 
20
 
21
-import uprrp.tania.URLEventListener;
21
+import uprrp.tania.utils.URLEventListener;
22
 
22
 
23
 public class SendWithdrawal extends AsyncTask<String, String, String> {
23
 public class SendWithdrawal extends AsyncTask<String, String, String> {
24
 
24
 

app/src/main/java/uprrp/tania/URLEventListener.java → app/src/main/java/uprrp/tania/utils/URLEventListener.java View File

1
-package uprrp.tania;
1
+package uprrp.tania.utils;
2
 
2
 
3
 import uprrp.tania.models.AssessmentModel;
3
 import uprrp.tania.models.AssessmentModel;
4
 import uprrp.tania.models.UserStatusModel;
4
 import uprrp.tania.models.UserStatusModel;
5
 
5
 
6
 public class URLEventListener {
6
 public class URLEventListener {
7
     public void onSuccess() {}
7
     public void onSuccess() {}
8
+    public void onSuccess(String response) {}
8
     public void onSuccess(AssessmentModel assessment) {}
9
     public void onSuccess(AssessmentModel assessment) {}
9
     public void onSuccess(UserStatusModel userStatus) {}
10
     public void onSuccess(UserStatusModel userStatus) {}
10
     public void onFailure(Exception e) {}
11
     public void onFailure(Exception e) {}

app/src/main/res/layout/activity_login.xml → app/src/main/res/layout/activity_account_recovery.xml View File


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

24
         android:id="@+id/appBarLayout"
24
         android:id="@+id/appBarLayout"
25
         android:layout_width="match_parent"
25
         android:layout_width="match_parent"
26
         android:layout_height="61dp"
26
         android:layout_height="61dp"
27
-        android:theme="@style/Theme.MarleApp.AppBarOverlay"
27
+        android:theme="@style/Theme.TANIA.AppBarOverlay"
28
         app:layout_constraintEnd_toEndOf="parent"
28
         app:layout_constraintEnd_toEndOf="parent"
29
         app:layout_constraintStart_toStartOf="parent"
29
         app:layout_constraintStart_toStartOf="parent"
30
         app:layout_constraintTop_toTopOf="parent">
30
         app:layout_constraintTop_toTopOf="parent">
34
             android:layout_width="match_parent"
34
             android:layout_width="match_parent"
35
             android:layout_height="match_parent"
35
             android:layout_height="match_parent"
36
             android:background="?attr/colorPrimary"
36
             android:background="?attr/colorPrimary"
37
-            app:popupTheme="@style/Theme.MarleApp.PopupOverlay" />
37
+            app:popupTheme="@style/Theme.TANIA.PopupOverlay" />
38
 
38
 
39
     </com.google.android.material.appbar.AppBarLayout>
39
     </com.google.android.material.appbar.AppBarLayout>
40
 
40
 

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

61
     <!--  Getting Started Activity  -->
61
     <!--  Getting Started Activity  -->
62
     <string name="createAccountButtonText">Join the Study</string>
62
     <string name="createAccountButtonText">Join the Study</string>
63
     <string name="recoverAccountButtonText">Login</string>
63
     <string name="recoverAccountButtonText">Login</string>
64
+    <string name="bubbleDescription">Just a blue bubble for decoration</string>
64
     <string name="overviewTitleText">Welcome</string>
65
     <string name="overviewTitleText">Welcome</string>
65
     <string name="overviewConsentSectionSummaryText">You have been invited to participate in this study whose objectives are (1) to develop and demonstrate the utility of a mobile application (TANIA) to collect perception data of students participating in research experiences and (2) to use TANIA to determine the sources of self-efficacy that lead to career exploration and decision-making in undergraduate students.</string>
66
     <string name="overviewConsentSectionSummaryText">You have been invited to participate in this study whose objectives are (1) to develop and demonstrate the utility of a mobile application (TANIA) to collect perception data of students participating in research experiences and (2) to use TANIA to determine the sources of self-efficacy that lead to career exploration and decision-making in undergraduate students.</string>
66
     <string name="overviewConsentSectionContentText">This study is been carried out under the supervision of Dr. Juan S. Ramírez Lugo, Department of Biology and Dr. Carlos Corrada Bravo, Department of Computer Sciences at the University of Puerto Rico, Río Piedras Campus. You were selected to participate in this study because you are enrolled in a course that offers a research experience or you voluntarily participate in research with a professor affiliated to the Río Piedras Campus.</string>
67
     <string name="overviewConsentSectionContentText">This study is been carried out under the supervision of Dr. Juan S. Ramírez Lugo, Department of Biology and Dr. Carlos Corrada Bravo, Department of Computer Sciences at the University of Puerto Rico, Río Piedras Campus. You were selected to participate in this study because you are enrolled in a course that offers a research experience or you voluntarily participate in research with a professor affiliated to the Río Piedras Campus.</string>
77
     <string name="dataUseConsentSectionSummaryText">The data obtained will be used to improve academic offerings and research experiences. The results of this study may be part of a scientific publication on science education strategies and will serve as a basis to improve the teaching curriculum.</string>
78
     <string name="dataUseConsentSectionSummaryText">The data obtained will be used to improve academic offerings and research experiences. The results of this study may be part of a scientific publication on science education strategies and will serve as a basis to improve the teaching curriculum.</string>
78
     <string name="dataUseConsentSectionContentText">It may be used to develop proposals for obtaining external funds for research. The officials of the Río Piedras Campus of the University of Puerto Rico and / or federal agencies responsible for ensuring the integrity of the research may require the researcher to prove the data obtained in this study, including this informed consent. The information handled by your device can be intervened or revised by third parties. These people can be people with legitimate or illegitimate access to the device and its content such as a family member, employer, hackers, intruders, etc. In addition, the device that you use may keep track of the information you access or send over the Internet.</string>
79
     <string name="dataUseConsentSectionContentText">It may be used to develop proposals for obtaining external funds for research. The officials of the Río Piedras Campus of the University of Puerto Rico and / or federal agencies responsible for ensuring the integrity of the research may require the researcher to prove the data obtained in this study, including this informed consent. The information handled by your device can be intervened or revised by third parties. These people can be people with legitimate or illegitimate access to the device and its content such as a family member, employer, hackers, intruders, etc. In addition, the device that you use may keep track of the information you access or send over the Internet.</string>
79
     <string name="generalTitleText">General</string>
80
     <string name="generalTitleText">General</string>
80
-    <string name="bubbleDescription">Just a blue bubble for decoration</string>
81
 </resources>
81
 </resources>

+ 20
- 20
app/src/main/res/values/styles.xml View File

1
 <resources>
1
 <resources>
2
 
2
 
3
     <!-- Base application theme. -->
3
     <!-- Base application theme. -->
4
-    <style name="Theme.MarleApp" parent="Theme.Backbone">
4
+    <style name="Theme.TANIA" parent="Theme.Backbone">
5
         <!-- Customize your theme here. -->
5
         <!-- Customize your theme here. -->
6
         <item name="colorPrimary">@color/colorPrimary</item>
6
         <item name="colorPrimary">@color/colorPrimary</item>
7
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
7
         <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
8
         <item name="colorAccent">@color/colorAccent</item>
8
         <item name="colorAccent">@color/colorAccent</item>
9
-        <item name="alertDialogTheme">@style/Theme.MarleApp.Dialog</item>
10
-        <item name="toolbarTheme">@style/Theme.MarleApp.Toolbar</item>
9
+        <item name="alertDialogTheme">@style/Theme.TANIA.Dialog</item>
10
+        <item name="toolbarTheme">@style/Theme.TANIA.Toolbar</item>
11
         <item name="android:textColorSecondary">@color/textColor1</item>
11
         <item name="android:textColorSecondary">@color/textColor1</item>
12
     </style>
12
     </style>
13
 
13
 
14
-    <style name="Theme.MarleApp.Survey">
15
-        <item name="toolbarTheme">@style/Theme.MarleApp.Toolbar.Transparent</item>
14
+    <style name="Theme.TANIA.Survey">
15
+        <item name="toolbarTheme">@style/Theme.TANIA.Toolbar.Transparent</item>
16
         <item name="android:windowBackground">@android:color/white</item>
16
         <item name="android:windowBackground">@android:color/white</item>
17
         <item name="colorPrimaryDark">@color/dark_gray</item>
17
         <item name="colorPrimaryDark">@color/dark_gray</item>
18
         <item name="android:windowContentOverlay">@null</item>
18
         <item name="android:windowContentOverlay">@null</item>
19
     </style>
19
     </style>
20
 
20
 
21
-    <style name="Theme.MarleApp.Toolbar.Transparent">
21
+    <style name="Theme.TANIA.Toolbar.Transparent">
22
         <item name="colorControlNormal">@color/rsb_warm_gray</item>
22
         <item name="colorControlNormal">@color/rsb_warm_gray</item>
23
         <item name="colorPrimary">@android:color/white</item>
23
         <item name="colorPrimary">@android:color/white</item>
24
-        <item name="toolbarStyle">@style/Widget.MarleApp.Toolbar.Transparent</item>
24
+        <item name="toolbarStyle">@style/Widget.TANIA.Toolbar.Transparent</item>
25
     </style>
25
     </style>
26
 
26
 
27
-    <style name="Theme.MarleApp.Dialog" parent="Theme.AppCompat.Light.Dialog.Alert">
27
+    <style name="Theme.TANIA.Dialog" parent="Theme.AppCompat.Light.Dialog.Alert">
28
         <item name="colorAccent">@color/colorAccent</item>
28
         <item name="colorAccent">@color/colorAccent</item>
29
         <item name="android:textColorPrimary">@color/rsb_warm_gray</item>
29
         <item name="android:textColorPrimary">@color/rsb_warm_gray</item>
30
         <item name="android:background">@android:color/white</item>
30
         <item name="android:background">@android:color/white</item>
31
     </style>
31
     </style>
32
 
32
 
33
-    <style name="Theme.MarleApp.Toolbar">
33
+    <style name="Theme.TANIA.Toolbar">
34
         <item name="colorControlNormal">@android:color/white</item>
34
         <item name="colorControlNormal">@android:color/white</item>
35
-        <item name="toolbarStyle">@style/Widget.MarleApp.Toolbar</item>
35
+        <item name="toolbarStyle">@style/Widget.TANIA.Toolbar</item>
36
     </style>
36
     </style>
37
 
37
 
38
-    <style name="Base.Widget.MarleApp.Toolbar" parent="@style/Widget.AppCompat.Toolbar">
38
+    <style name="Base.Widget.TANIA.Toolbar" parent="@style/Widget.AppCompat.Toolbar">
39
         <item name="android:background">?attr/colorPrimary</item>
39
         <item name="android:background">?attr/colorPrimary</item>
40
         <item name="android:minHeight">56dp</item>
40
         <item name="android:minHeight">56dp</item>
41
-        <item name="titleTextAppearance">@style/TextAppearance.Widget.MarleApp.Toolbar.Title</item>
41
+        <item name="titleTextAppearance">@style/TextAppearance.Widget.TANIA.Toolbar.Title</item>
42
     </style>
42
     </style>
43
 
43
 
44
-    <style name="TextAppearance.Widget.MarleApp.Toolbar.Title" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Title">
44
+    <style name="TextAppearance.Widget.TANIA.Toolbar.Title" parent="@style/TextAppearance.Widget.AppCompat.Toolbar.Title">
45
         <item name="android:textColor">@color/textColor1</item>
45
         <item name="android:textColor">@color/textColor1</item>
46
         <item name="android:textSize">20sp</item>
46
         <item name="android:textSize">20sp</item>
47
     </style>
47
     </style>
48
 
48
 
49
-    <style name="TextAppearance.Widget.MarleApp.Toolbar.Title.Transparent">
49
+    <style name="TextAppearance.Widget.TANIA.Toolbar.Title.Transparent">
50
         <item name="android:textColor">@color/textColor1</item>
50
         <item name="android:textColor">@color/textColor1</item>
51
     </style>
51
     </style>
52
 
52
 
53
-    <style name="Widget.MarleApp.Toolbar" parent="@style/Base.Widget.MarleApp.Toolbar">
53
+    <style name="Widget.TANIA.Toolbar" parent="@style/Base.Widget.TANIA.Toolbar">
54
         <item name="android:elevation">4dp</item>
54
         <item name="android:elevation">4dp</item>
55
         <item name="android:outlineProvider">bounds</item>
55
         <item name="android:outlineProvider">bounds</item>
56
     </style>
56
     </style>
57
 
57
 
58
-    <style name="Widget.MarleApp.Toolbar.Transparent" parent="@style/Base.Widget.MarleApp.Toolbar">
58
+    <style name="Widget.TANIA.Toolbar.Transparent" parent="@style/Base.Widget.TANIA.Toolbar">
59
         <item name="android:elevation">0dp</item>
59
         <item name="android:elevation">0dp</item>
60
         <item name="android:outlineProvider">none</item>
60
         <item name="android:outlineProvider">none</item>
61
         <item name="titleTextAppearance">
61
         <item name="titleTextAppearance">
62
-            @style/TextAppearance.Widget.MarleApp.Toolbar.Title.Transparent
62
+            @style/TextAppearance.Widget.TANIA.Toolbar.Title.Transparent
63
         </item>
63
         </item>
64
     </style>
64
     </style>
65
 
65
 
66
-    <style name="Theme.MarleApp.NoActionBar">
66
+    <style name="Theme.TANIA.NoActionBar">
67
         <item name="windowActionBar">false</item>
67
         <item name="windowActionBar">false</item>
68
         <item name="windowNoTitle">true</item>
68
         <item name="windowNoTitle">true</item>
69
     </style>
69
     </style>
70
 
70
 
71
-    <style name="Theme.MarleApp.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
71
+    <style name="Theme.TANIA.AppBarOverlay" parent="ThemeOverlay.AppCompat.Dark.ActionBar" />
72
 
72
 
73
-    <style name="Theme.MarleApp.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
73
+    <style name="Theme.TANIA.PopupOverlay" parent="ThemeOverlay.AppCompat.Light" />
74
 
74
 
75
 
75
 
76
 </resources>
76
 </resources>