|
@@ -12,14 +12,11 @@ import android.view.ViewGroup;
|
12
|
12
|
import android.widget.Button;
|
13
|
13
|
import android.widget.TextView;
|
14
|
14
|
import android.widget.Toast;
|
|
15
|
+
|
15
|
16
|
import androidx.annotation.Nullable;
|
16
|
17
|
import androidx.appcompat.app.AlertDialog;
|
17
|
18
|
import androidx.fragment.app.Fragment;
|
18
|
19
|
|
19
|
|
-import com.google.android.gms.tasks.OnSuccessListener;
|
20
|
|
-import com.google.firebase.iid.FirebaseInstanceId;
|
21
|
|
-import com.google.firebase.iid.InstanceIdResult;
|
22
|
|
-
|
23
|
20
|
import org.researchstack.backbone.StorageAccess;
|
24
|
21
|
import org.researchstack.backbone.answerformat.AnswerFormat;
|
25
|
22
|
import org.researchstack.backbone.answerformat.ChoiceAnswerFormat;
|
|
@@ -36,19 +33,22 @@ import org.researchstack.backbone.ui.ViewTaskActivity;
|
36
|
33
|
import java.util.ArrayList;
|
37
|
34
|
import java.util.List;
|
38
|
35
|
import java.util.Objects;
|
|
36
|
+import java.util.Observable;
|
|
37
|
+import java.util.Observer;
|
39
|
38
|
|
40
|
|
-import uprrp.tania.networking.SendAnswers;
|
41
|
|
-import uprrp.tania.models.AnsweredQuestionModel;
|
|
39
|
+import uprrp.tania.GlobalValues;
|
|
40
|
+import uprrp.tania.R;
|
|
41
|
+import uprrp.tania.URLEventListener;
|
42
|
42
|
import uprrp.tania.models.AnsweredAssessmentModel;
|
43
|
|
-import uprrp.tania.networking.FetchAssessment;
|
44
|
|
-import uprrp.tania.networking.FetchUserStatus;
|
|
43
|
+import uprrp.tania.models.AnsweredQuestionModel;
|
45
|
44
|
import uprrp.tania.models.AssessmentModel;
|
46
|
45
|
import uprrp.tania.models.QuestionModel;
|
47
|
|
-import uprrp.tania.R;
|
48
|
|
-import uprrp.tania.URLEventListener;
|
49
|
46
|
import uprrp.tania.models.UserStatusModel;
|
|
47
|
+import uprrp.tania.networking.FetchAssessment;
|
|
48
|
+import uprrp.tania.networking.FetchUserStatus;
|
|
49
|
+import uprrp.tania.networking.SendAnswers;
|
50
|
50
|
|
51
|
|
-public class AssessmentsFragment extends Fragment {
|
|
51
|
+public class AssessmentsFragment extends Fragment implements Observer {
|
52
|
52
|
|
53
|
53
|
// These variables came from the sample app provided to explain the use of Research Stack
|
54
|
54
|
private static final int REQUEST_SURVEY = 1;
|
|
@@ -57,7 +57,6 @@ public class AssessmentsFragment extends Fragment {
|
57
|
57
|
|
58
|
58
|
// Our variables
|
59
|
59
|
private static final String TAG = "AssessmentsFragment";
|
60
|
|
- private String DEVICE_TOKEN;
|
61
|
60
|
private String ASSESSMENT_ID;
|
62
|
61
|
private View thisFragment;
|
63
|
62
|
|
|
@@ -65,47 +64,40 @@ public class AssessmentsFragment extends Fragment {
|
65
|
64
|
@Override
|
66
|
65
|
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
|
67
|
66
|
|
68
|
|
- // Get reference for this fragment and other components
|
69
|
|
- this.thisFragment = inflater.inflate(R.layout.fragment_assessments, container, false);
|
70
|
|
- final Button surveyButton = thisFragment.findViewById(R.id.surveyButton);
|
71
|
|
- final Button refreshButton = thisFragment.findViewById(R.id.refreshButton);
|
|
67
|
+ // Constructor
|
|
68
|
+ thisFragment = inflater.inflate(R.layout.fragment_assessments, container, false);
|
72
|
69
|
|
73
|
|
- // Change all caps text to normal capitalization
|
74
|
|
- // TODO: this is a workaround I found, any other acceptable solution is welcome
|
75
|
|
- surveyButton.setTransformationMethod(null);
|
76
|
|
- refreshButton.setTransformationMethod(null);
|
|
70
|
+ // Listen for device token changes
|
|
71
|
+ this.startObservingGlobals();
|
77
|
72
|
|
78
|
|
- // Request to Firebase...
|
79
|
|
- // TODO: Should we implement retry logic in onFailureListener?
|
80
|
|
- FirebaseInstanceId.getInstance().getInstanceId().addOnSuccessListener(new OnSuccessListener<InstanceIdResult>() {
|
81
|
|
- @Override
|
82
|
|
- public void onSuccess(InstanceIdResult instanceIdResult) {
|
83
|
|
-
|
84
|
|
- // Get device's token
|
85
|
|
- // IMPORTANT: must come first before calling
|
86
|
|
- // another function that uses the token
|
87
|
|
- DEVICE_TOKEN = instanceIdResult.getToken();
|
88
|
|
-
|
89
|
|
- // Add onClick listener to "Answer Survey" button
|
90
|
|
- surveyButton.setOnClickListener(new View.OnClickListener() {
|
91
|
|
- @Override
|
92
|
|
- public void onClick(View v) {
|
93
|
|
- fetchAssessment();
|
94
|
|
- }
|
95
|
|
- });
|
|
73
|
+ // Disable interaction initially while token is being fetched
|
|
74
|
+ if(GlobalValues.getInstance().getDeviceToken() == null) {
|
|
75
|
+ disableInteractionTemporarily();
|
|
76
|
+ } else {
|
|
77
|
+ enableInteraction();
|
|
78
|
+ }
|
96
|
79
|
|
97
|
|
- // Add onClick listener to "Refresh Status" button
|
98
|
|
- refreshButton.setOnClickListener(new View.OnClickListener() {
|
99
|
|
- @Override
|
100
|
|
- public void onClick(View v) {
|
101
|
|
- fetchUserStatus();
|
102
|
|
- }
|
103
|
|
- });
|
|
80
|
+ // Display user status if available
|
|
81
|
+ UserStatusModel userStatus = GlobalValues.getInstance().getUserStatus();
|
|
82
|
+ if(userStatus != null) {
|
|
83
|
+ positiveUserStatus(userStatus);
|
|
84
|
+ }
|
104
|
85
|
|
105
|
|
- // Fetch user status and assessment, if any
|
|
86
|
+ // Change all caps text to normal capitalization and add onClick listener
|
|
87
|
+ final Button surveyButton = thisFragment.findViewById(R.id.surveyButton);
|
|
88
|
+ final Button refreshButton = thisFragment.findViewById(R.id.refreshButton);
|
|
89
|
+ surveyButton.setTransformationMethod(null); // TODO: this is a workaround I found, any other acceptable solution is welcome
|
|
90
|
+ refreshButton.setTransformationMethod(null); // TODO: this is a workaround I found, any other acceptable solution is welcome
|
|
91
|
+ surveyButton.setOnClickListener(new View.OnClickListener() {
|
|
92
|
+ @Override
|
|
93
|
+ public void onClick(View v) {
|
|
94
|
+ fetchAssessment();
|
|
95
|
+ }
|
|
96
|
+ });
|
|
97
|
+ refreshButton.setOnClickListener(new View.OnClickListener() {
|
|
98
|
+ @Override
|
|
99
|
+ public void onClick(View v) {
|
106
|
100
|
fetchUserStatus();
|
107
|
|
-// fetchAssessment();
|
108
|
|
-
|
109
|
101
|
}
|
110
|
102
|
});
|
111
|
103
|
|
|
@@ -113,61 +105,147 @@ public class AssessmentsFragment extends Fragment {
|
113
|
105
|
|
114
|
106
|
}
|
115
|
107
|
|
116
|
|
- private void fetchUserStatus() {
|
117
|
|
-
|
118
|
|
- // Get text fields and initialize other stuff
|
119
|
|
- final TextView statusTextView = this.thisFragment.findViewById(R.id.statusTextView);
|
120
|
|
- final TextView nextSurveyTextView = this.thisFragment.findViewById(R.id.nextSurveyTextView);
|
121
|
|
- final Button surveyButton = this.thisFragment.findViewById(R.id.surveyButton);
|
122
|
|
- final Button refreshButton = this.thisFragment.findViewById(R.id.refreshButton);
|
|
108
|
+ private void disableInteractionTemporarily() {
|
|
109
|
+ final Button surveyButton = thisFragment.findViewById(R.id.surveyButton);
|
|
110
|
+ final Button refreshButton = thisFragment.findViewById(R.id.refreshButton);
|
|
111
|
+ final TextView statusTextView = thisFragment.findViewById(R.id.statusTextView);
|
|
112
|
+ final TextView nextSurveyTextView = thisFragment.findViewById(R.id.nextSurveyTextView);
|
123
|
113
|
|
124
|
|
- // Change UI to indicate loading is happening
|
|
114
|
+ surveyButton.setEnabled(false);
|
|
115
|
+ refreshButton.setEnabled(false);
|
125
|
116
|
statusTextView.setText(R.string.loadingText);
|
126
|
|
- nextSurveyTextView.setVisibility(View.GONE);
|
|
117
|
+ nextSurveyTextView.setVisibility(View.INVISIBLE);
|
|
118
|
+ }
|
127
|
119
|
|
128
|
|
- // Define task
|
129
|
|
- FetchUserStatus userStatusTask = new FetchUserStatus(new URLEventListener() {
|
|
120
|
+ private void disableInteraction() {
|
|
121
|
+ final Button surveyButton = thisFragment.findViewById(R.id.surveyButton);
|
|
122
|
+ final Button refreshButton = thisFragment.findViewById(R.id.refreshButton);
|
|
123
|
+ final TextView statusTextView = thisFragment.findViewById(R.id.statusTextView);
|
|
124
|
+ final TextView nextSurveyTextView = thisFragment.findViewById(R.id.nextSurveyTextView);
|
130
|
125
|
|
131
|
|
- @Override
|
132
|
|
- public void onSuccess(UserStatusModel userStatus) {
|
133
|
|
- if(userStatus.isEnrolled()) {
|
|
126
|
+ surveyButton.setEnabled(false);
|
|
127
|
+ refreshButton.setEnabled(false);
|
|
128
|
+ statusTextView.setText(R.string.tokenErrorText);
|
|
129
|
+ nextSurveyTextView.setVisibility(View.INVISIBLE);
|
|
130
|
+ }
|
134
|
131
|
|
135
|
|
- // Change next survey date text (as well as status text)
|
136
|
|
- statusTextView.setText(userStatus.toString());
|
137
|
|
- nextSurveyTextView.setText(userStatus.getTimeToNext());
|
138
|
|
- nextSurveyTextView.setVisibility(View.VISIBLE);
|
|
132
|
+ private void enableInteraction() {
|
|
133
|
+ final Button surveyButton = thisFragment.findViewById(R.id.surveyButton);
|
|
134
|
+ final Button refreshButton = thisFragment.findViewById(R.id.refreshButton);
|
139
|
135
|
|
140
|
|
- // Hide refresh button (it only refreshes user status, anyways so...)
|
141
|
|
- refreshButton.setVisibility(View.GONE);
|
|
136
|
+ surveyButton.setEnabled(true);
|
|
137
|
+ refreshButton.setEnabled(true);
|
|
138
|
+ if(GlobalValues.getInstance().getUserStatus() == null) {
|
|
139
|
+ fetchUserStatus(); // refresh user status
|
|
140
|
+ }
|
|
141
|
+ }
|
142
|
142
|
|
143
|
|
- // Toggle "Answer" button visibility depending on survey availability
|
144
|
|
- if(userStatus.surveyAvailable()) {
|
145
|
|
- surveyButton.setVisibility(View.VISIBLE);
|
146
|
|
- } else {
|
147
|
|
- surveyButton.setVisibility(View.GONE);
|
148
|
|
- }
|
|
143
|
+ // TAKEN FROM https://stackoverflow.com/questions/21886768/is-there-any-method-i-can-listen-for-changes-to-global-variable-to-trigger-an-ev
|
|
144
|
+ private void startObservingGlobals() {
|
|
145
|
+ GlobalValues.getInstance().addObserver(this);
|
|
146
|
+ }
|
149
|
147
|
|
150
|
|
- } else {
|
151
|
|
- // Prompt user to refresh status if user doesn't have an experience
|
152
|
|
-// statusTextView.setText("You are not enrolled in any experience.\nIf you think this is a mistake, contact your supervisors."); // for debugging/testing
|
153
|
|
- statusTextView.setText(userStatus.toString());
|
154
|
|
- nextSurveyTextView.setVisibility(View.GONE);
|
155
|
|
- surveyButton.setVisibility(View.GONE);
|
156
|
|
- refreshButton.setVisibility(View.VISIBLE);
|
|
148
|
+ // TAKEN FROM https://stackoverflow.com/questions/21886768/is-there-any-method-i-can-listen-for-changes-to-global-variable-to-trigger-an-ev
|
|
149
|
+ @Override
|
|
150
|
+ public void update(Observable observable, Object o) {
|
|
151
|
+ if(observable instanceof GlobalValues) {
|
|
152
|
+ if(o instanceof GlobalValues.ValueKey) {
|
|
153
|
+ switch(((GlobalValues.ValueKey) o).getKey()) {
|
|
154
|
+ case DEVICE_TOKEN:
|
|
155
|
+ if(GlobalValues.getInstance().getDeviceToken() == null) {
|
|
156
|
+ disableInteraction();
|
|
157
|
+ } else {
|
|
158
|
+ enableInteraction();
|
|
159
|
+ }
|
|
160
|
+ break;
|
|
161
|
+ case USER_STATUS:
|
|
162
|
+ UserStatusModel userStatus = GlobalValues.getInstance().getUserStatus();
|
|
163
|
+ if(userStatus == null) {
|
|
164
|
+ negativeUserStatus();
|
|
165
|
+ } else {
|
|
166
|
+ positiveUserStatus(userStatus);
|
|
167
|
+ }
|
|
168
|
+ break;
|
157
|
169
|
}
|
158
|
170
|
}
|
|
171
|
+ }
|
|
172
|
+ }
|
|
173
|
+
|
|
174
|
+ private void negativeUserStatus() {
|
|
175
|
+ Toast.makeText(getContext(), "Can't verify identity!", Toast.LENGTH_LONG).show();
|
|
176
|
+
|
|
177
|
+ final TextView statusTextView = thisFragment.findViewById(R.id.statusTextView);
|
|
178
|
+ final TextView nextSurveyTextView = thisFragment.findViewById(R.id.nextSurveyTextView);
|
|
179
|
+ final Button surveyButton = thisFragment.findViewById(R.id.surveyButton);
|
|
180
|
+ final Button refreshButton = thisFragment.findViewById(R.id.refreshButton);
|
|
181
|
+
|
|
182
|
+ statusTextView.setText(R.string.userStatusErrorText);
|
|
183
|
+ nextSurveyTextView.setVisibility(View.INVISIBLE);
|
|
184
|
+ surveyButton.setVisibility(View.INVISIBLE);
|
|
185
|
+ surveyButton.setEnabled(false);
|
|
186
|
+ refreshButton.setVisibility(View.VISIBLE);
|
|
187
|
+ }
|
|
188
|
+
|
|
189
|
+ private void positiveUserStatus(UserStatusModel userStatus) {
|
|
190
|
+
|
|
191
|
+ final TextView statusTextView = thisFragment.findViewById(R.id.statusTextView);
|
|
192
|
+ final TextView nextSurveyTextView = thisFragment.findViewById(R.id.nextSurveyTextView);
|
|
193
|
+ final Button surveyButton = thisFragment.findViewById(R.id.surveyButton);
|
|
194
|
+ final Button refreshButton = thisFragment.findViewById(R.id.refreshButton);
|
|
195
|
+
|
|
196
|
+ statusTextView.setText(userStatus.toString());
|
|
197
|
+
|
|
198
|
+ if(userStatus.isEnrolled()) {
|
159
|
199
|
|
|
200
|
+ nextSurveyTextView.setText(userStatus.getTimeToNext());
|
|
201
|
+ nextSurveyTextView.setVisibility(View.VISIBLE);
|
|
202
|
+
|
|
203
|
+ if(userStatus.surveyAvailable()) {
|
|
204
|
+ refreshButton.setVisibility(View.INVISIBLE);
|
|
205
|
+ refreshButton.setEnabled(false);
|
|
206
|
+ surveyButton.setVisibility(View.VISIBLE);
|
|
207
|
+ surveyButton.setEnabled(true);
|
|
208
|
+ } else {
|
|
209
|
+ surveyButton.setVisibility(View.INVISIBLE);
|
|
210
|
+ surveyButton.setEnabled(false);
|
|
211
|
+ refreshButton.setVisibility(View.VISIBLE);
|
|
212
|
+ refreshButton.setEnabled(true);
|
|
213
|
+ }
|
|
214
|
+
|
|
215
|
+ } else {
|
|
216
|
+
|
|
217
|
+ nextSurveyTextView.setText("");
|
|
218
|
+ nextSurveyTextView.setVisibility(View.INVISIBLE);
|
|
219
|
+
|
|
220
|
+ surveyButton.setVisibility(View.INVISIBLE);
|
|
221
|
+ surveyButton.setEnabled(false);
|
|
222
|
+ refreshButton.setVisibility(View.VISIBLE);
|
|
223
|
+ refreshButton.setEnabled(true);
|
|
224
|
+
|
|
225
|
+ }
|
|
226
|
+
|
|
227
|
+ }
|
|
228
|
+
|
|
229
|
+ private void fetchUserStatus() {
|
|
230
|
+
|
|
231
|
+ disableInteractionTemporarily();
|
|
232
|
+
|
|
233
|
+ // Define task
|
|
234
|
+ FetchUserStatus userStatusTask = new FetchUserStatus(new URLEventListener() {
|
|
235
|
+ @Override
|
|
236
|
+ public void onSuccess(UserStatusModel userStatus) {
|
|
237
|
+ GlobalValues.getInstance().setUserStatus(userStatus);
|
|
238
|
+ enableInteraction();
|
|
239
|
+ }
|
160
|
240
|
@Override
|
161
|
241
|
public void onFailure(Exception e) {
|
162
|
|
- statusTextView.setText(R.string.userStatusErrorText);
|
163
|
|
- Toast.makeText(getContext(), "Can't verify identity!", Toast.LENGTH_LONG).show();
|
164
|
|
- Log.e("ERROR WHILE FETCHING USER STATUS", e.toString());
|
|
242
|
+ GlobalValues.getInstance().setUserStatus(null);
|
|
243
|
+ Log.e(TAG, "Error while fetching user status: " + e.toString());
|
165
|
244
|
}
|
166
|
|
-
|
167
|
245
|
});
|
168
|
246
|
|
169
|
247
|
// Start task
|
170
|
|
- userStatusTask.execute(this.DEVICE_TOKEN);
|
|
248
|
+ userStatusTask.execute(GlobalValues.getInstance().getDeviceToken());
|
171
|
249
|
|
172
|
250
|
}
|
173
|
251
|
|
|
@@ -204,7 +282,7 @@ public class AssessmentsFragment extends Fragment {
|
204
|
282
|
});
|
205
|
283
|
|
206
|
284
|
// Start task
|
207
|
|
- assessmentTask.execute(this.DEVICE_TOKEN);
|
|
285
|
+ assessmentTask.execute(GlobalValues.getInstance().getDeviceToken());
|
208
|
286
|
|
209
|
287
|
}
|
210
|
288
|
|
|
@@ -259,7 +337,7 @@ public class AssessmentsFragment extends Fragment {
|
259
|
337
|
|
260
|
338
|
@Override
|
261
|
339
|
public void onFailure(Exception e) {
|
262
|
|
- Log.e("ERROR WHILE SENDING ANSWERS", e.toString());
|
|
340
|
+ Log.e(TAG, "Error whilte sending answers: " + e.toString());
|
263
|
341
|
e.printStackTrace();
|
264
|
342
|
progressDialog.dismiss();
|
265
|
343
|
promptRetrySend(answeredAssessment);
|
|
@@ -311,7 +389,7 @@ public class AssessmentsFragment extends Fragment {
|
311
|
389
|
}
|
312
|
390
|
|
313
|
391
|
// Return answered assessment
|
314
|
|
- return new AnsweredAssessmentModel(this.ASSESSMENT_ID, this.DEVICE_TOKEN, answeredQuestions);
|
|
392
|
+ return new AnsweredAssessmentModel(this.ASSESSMENT_ID, GlobalValues.getInstance().getDeviceToken(), answeredQuestions);
|
315
|
393
|
|
316
|
394
|
}
|
317
|
395
|
|
|
@@ -322,7 +400,7 @@ public class AssessmentsFragment extends Fragment {
|
322
|
400
|
|
323
|
401
|
// Create instruction screen (add it to total steps)
|
324
|
402
|
InstructionStep instructionStep = new InstructionStep(INSTRUCTION,
|
325
|
|
- getString(R.string.app_name),
|
|
403
|
+ getString(R.string.appName),
|
326
|
404
|
assessment.getDescription());
|
327
|
405
|
instructionStep.setStepTitle(R.string.surveyToolbarText);
|
328
|
406
|
steps.add(0, instructionStep);
|