use of com.instructure.canvasapi2.utils.LinkHeaders in project instructure-android by instructure.
the class QuizStartFragment method setupCallbacks.
private void setupCallbacks() {
webViewClientCallback = new CanvasWebView.CanvasWebViewClientCallback() {
@Override
public void openMediaFromWebView(String mime, String url, String filename) {
openMedia(mime, url, filename);
}
@Override
public void onPageFinishedCallback(WebView webView, String url) {
}
@Override
public void onPageStartedCallback(WebView webView, String url) {
}
@Override
public boolean canRouteInternallyDelegate(String url) {
return RouterUtils.canRouteInternally(null, url, ApiPrefs.getDomain(), false);
}
@Override
public void routeInternallyCallback(String url) {
RouterUtils.canRouteInternally(getActivity(), url, ApiPrefs.getDomain(), true);
}
};
embeddedWebViewCallback = new CanvasWebView.CanvasEmbeddedWebViewCallback() {
@Override
public void launchInternalWebViewFragment(String url) {
InternalWebviewFragment.Companion.loadInternalWebView(getActivity(), getNavigation(), InternalWebviewFragment.Companion.createBundle(course, url, false));
}
@Override
public boolean shouldLaunchInternalWebViewFragment(String url) {
return true;
}
};
quizSubmissionTimeCanvasCallback = new StatusCallback<QuizSubmissionTime>() {
@Override
public void onResponse(@NonNull Response<QuizSubmissionTime> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (type == ApiType.CACHE)
return;
QuizStartFragment.this.quizSubmissionTime = quizSubmissionTime;
QuizManager.getQuizSubmissions(course, quiz.getId(), true, quizSubmissionResponseCanvasCallback);
}
};
quizSubmissionResponseCanvasCallback = new StatusCallback<QuizSubmissionResponse>() {
@Override
public void onResponse(@NonNull Response<QuizSubmissionResponse> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (type == ApiType.CACHE)
return;
final QuizSubmissionResponse quizSubmissionResponse = response.body();
// since this is a student app, make sure they only have their own submissions (if they're siteadmin it'll be different)
final ArrayList<QuizSubmission> submissions = new ArrayList<>();
final User user = ApiPrefs.getUser();
if (user != null) {
for (QuizSubmission submission : quizSubmissionResponse.getQuizSubmissions()) {
if (submission.getUserId() == user.getId()) {
submissions.add(submission);
}
}
}
quizSubmissionResponse.setQuizSubmissions(submissions);
if (quizSubmissionResponse.getQuizSubmissions() == null || quizSubmissionResponse.getQuizSubmissions().size() == 0) {
// No quiz submissions, let the user start the quiz.
// They haven't turned it in yet, so don't show the turned-in view
quizTurnedInContainer.setVisibility(View.GONE);
shouldStartQuiz = true;
next.setVisibility(View.VISIBLE);
next.setEnabled(true);
} else {
// We should have at least 1 submission
quizSubmission = quizSubmissionResponse.getQuizSubmissions().get(quizSubmissionResponse.getQuizSubmissions().size() - 1);
next.setEnabled(true);
final boolean hasUnlimitedAttempts = quiz.getAllowedAttempts() == -1;
// Teacher can manually unlock a quiz for an individual student
final boolean teacherUnlockedQuizAttempts = quizSubmission.isManuallyUnlocked();
final boolean hasMoreAttemptsLeft = quizSubmission.getAttemptsLeft() > 0;
final boolean canTakeQuizAgain = hasUnlimitedAttempts | teacherUnlockedQuizAttempts | hasMoreAttemptsLeft;
if (quiz.getHideResults() == Quiz.HIDE_RESULTS_TYPE.ALWAYS && !canTakeQuizAgain) {
// Don't let the user see the questions if they've exceeded their attempts
next.setVisibility(View.GONE);
} else if (quiz.getHideResults() == Quiz.HIDE_RESULTS_TYPE.AFTER_LAST_ATTEMPT && !canTakeQuizAgain) {
// They can only see the results after their last attempt, and that hasn't happened yet
next.setVisibility(View.GONE);
}
// -1 allowed attempts == unlimited
if (quizSubmission.getFinishedAt() != null && !canTakeQuizAgain) {
// They've finished the quiz and they can't take it anymore; let them see results
next.setVisibility(View.VISIBLE);
next.setText(getString(R.string.viewQuestions));
shouldLetAnswer = false;
} else {
// They are allowed to take the quiz...
next.setVisibility(View.VISIBLE);
if (quizSubmission.getFinishedAt() != null) {
shouldStartQuiz = true;
next.setText(getString(R.string.takeQuizAgain));
} else {
// Let the user resume their quiz
next.setText(getString(R.string.resumeQuiz));
}
}
if (quizSubmission.getFinishedAt() != null) {
quizTurnedIn.setText(getString(R.string.turnedIn));
quizTurnedInDetails.setText(DateHelper.getDateTimeString(getActivity(), quizSubmission.getFinishedAt()));
// The user has turned in the quiz, let them see the results
viewResults.setVisibility(View.VISIBLE);
} else {
quizTurnedInContainer.setVisibility(View.GONE);
}
// Weird hack where if the time expires and the user hasn't submitted it doesn't let you start the quiz
if (quizSubmission.getWorkflowState() == QuizSubmission.WORKFLOW_STATE.UNTAKEN && (quizSubmission.getEndAt() != null && (quizSubmissionTime != null && quizSubmissionTime.getTimeLeft() > 0))) {
next.setEnabled(false);
// submit the quiz for them
QuizManager.submitQuiz(course, quizSubmission, true, new StatusCallback<QuizSubmissionResponse>() {
@Override
public void onResponse(@NonNull Response<QuizSubmissionResponse> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (type == ApiType.CACHE)
return;
// the user has turned in the quiz, let them see the results
viewResults.setVisibility(View.VISIBLE);
next.setEnabled(true);
shouldStartQuiz = true;
next.setText(getString(R.string.takeQuizAgain));
QuizSubmissionResponse quizResponse = response.body();
// Since this is a student app, make sure they only have their own submissions (if they're siteadmin it'll be different)
final ArrayList<QuizSubmission> submissions = new ArrayList<>();
final User user = ApiPrefs.getUser();
if (user != null) {
for (QuizSubmission submission : quizResponse.getQuizSubmissions()) {
if (submission.getUserId() == user.getId()) {
submissions.add(submission);
}
}
}
quizResponse.setQuizSubmissions(submissions);
if (quizResponse.getQuizSubmissions() != null && quizResponse.getQuizSubmissions().size() > 0) {
quizSubmission = quizResponse.getQuizSubmissions().get(quizResponse.getQuizSubmissions().size() - 1);
}
}
});
}
// If the user can only see results once and they have seen it, don't let them view the questions
if (quiz.isOneTimeResults() && quizSubmission.hasSeenResults()) {
next.setVisibility(View.GONE);
}
if (quiz.isLockedForUser()) {
shouldStartQuiz = false;
next.setText(getString(R.string.assignmentLocked));
}
}
populateQuizInfo();
canvasLoading.setVisibility(View.GONE);
}
@Override
public void onFail(@Nullable Call<QuizSubmissionResponse> call, @NonNull Throwable error, @Nullable Response response) {
canvasLoading.setVisibility(View.GONE);
// on quizzes.
if (response != null && response.code() == 401) {
populateQuizInfo();
// there is a not authorized error, so don't let them start the quiz
next.setVisibility(View.GONE);
}
}
};
quizStartResponseCallback = new StatusCallback<QuizSubmissionResponse>() {
@Override
public void onResponse(@NonNull Response<QuizSubmissionResponse> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (response.code() == 200 && type == ApiType.API) {
// We want to show the quiz here, but we need to get the quizSubmissionId first so our
// api call for the QuizQuestionsFragment knows which questions to get
StatusCallback<QuizSubmissionResponse> quizSubmissionResponseCallback = new StatusCallback<QuizSubmissionResponse>() {
@Override
public void onResponse(@NonNull Response<QuizSubmissionResponse> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
QuizSubmissionResponse quizSubmissionResponse = response.body();
if (quizSubmissionResponse != null && quizSubmissionResponse.getQuizSubmissions() != null && quizSubmissionResponse.getQuizSubmissions().size() > 0) {
quizSubmission = quizSubmissionResponse.getQuizSubmissions().get(quizSubmissionResponse.getQuizSubmissions().size() - 1);
if (quizSubmission != null) {
showQuiz();
} else {
getLockedMessage();
}
}
}
};
QuizManager.getFirstPageQuizSubmissions(course, quiz.getId(), false, quizSubmissionResponseCallback);
}
}
@Override
public void onFail(@Nullable Call<QuizSubmissionResponse> call, @NonNull Throwable error, @Nullable Response response) {
if (response != null && response.code() == 403) {
// Forbidden
// Check to see if it's because of IP restriction or bad access code or either
getLockedMessage();
}
}
};
quizStartSessionCallback = new StatusCallback<ResponseBody>() {
};
}
use of com.instructure.canvasapi2.utils.LinkHeaders in project instructure-android by instructure.
the class SubmissionDetailsFragment method setupCallbacks.
// /////////////////////////////////////////////////////////////////////////
// CallBack
// /////////////////////////////////////////////////////////////////////////
public void setupCallbacks() {
notoriousConfigCallback = new StatusCallback<NotoriousConfig>() {
@Override
public void onResponse(@NonNull Response<NotoriousConfig> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (!apiCheck()) {
return;
}
NotoriousConfig notoriousConfig = response.body();
if (notoriousConfig.isEnabled()) {
mediaComment.setEnabled(true);
}
}
};
// We use a NoNetworkErrorDelegate because sometimes old submissions are deleted.
// We don't want to display unnecessary croutons.
canvasCallbackSubmission = new StatusCallback<Submission>() {
@Override
public void onResponse(@NonNull Response<Submission> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (!apiCheck()) {
return;
}
if (response.body() != null) {
populateAdapter(response.body());
}
}
};
canvasCallbackMessage = new StatusCallback<Submission>() {
@Override
public void onResponse(@NonNull Response<Submission> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (!apiCheck()) {
return;
}
// See if it was successful.
Submission submission = response.body();
if (submission != null) {
SubmissionComment comment = submission.getSubmissionComments().get(submission.getSubmissionComments().size() - 1);
// Our list is a list of Submission, so add the comment to a SubmissionGrade object
Submission newSub = new Submission();
ArrayList<SubmissionComment> comments = new ArrayList<>();
comments.add(comment);
newSub.setSubmittedAt(comment.getCreatedAt());
newSub.setSubmissionComments(comments);
adapter.subList.add(0, newSub);
message.setText("");
} else {
showToast(R.string.errorPostingComment);
}
adapter.notifyDataSetChanged();
// Close the keyboard
InputMethodManager imm = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(message.getWindowToken(), 0);
// Enable the send message button again
submitComment.setVisibility(View.VISIBLE);
sendingProgressBar.setVisibility(View.GONE);
// Clear the attachments list
attachmentsList.clear();
attachmentIds.clear();
attachments.clear();
refreshAttachments();
}
@Override
public void onFail(@Nullable Call<Submission> call, @NonNull Throwable error, @Nullable Response response) {
// Enable the send message button again if there was an Error
submitComment.setVisibility(View.VISIBLE);
sendingProgressBar.setVisibility(View.GONE);
// Clear the attachments list
attachmentsList.clear();
attachmentIds.clear();
attachments.clear();
refreshAttachments();
}
};
canvasCallbackLTITool = new StatusCallback<LTITool>() {
@Override
public void onResponse(@NonNull Response<LTITool> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (!apiCheck()) {
return;
}
LTITool ltiTool = response.body();
String url = ltiTool.getUrl();
// Append platform for quizzes 2 lti tool
Uri uri = Uri.parse(url).buildUpon().appendQueryParameter("platform", "android").build();
// Do NOT authenticate or the LTI tool won't load.
InternalWebviewFragment.Companion.loadInternalWebView(getActivity(), ((Navigation) getActivity()), InternalWebviewFragment.Companion.createBundle(getCanvasContext(), uri.toString(), ltiTool.getName(), false, false, true, assignment.getUrl()));
}
@Override
public void onFail(@Nullable Call<LTITool> call, @NonNull Throwable error, @Nullable Response response) {
// If it wasn't a network Error, then the LTI tool must be expired or invalid.
if (APIHelper.hasNetworkConnection() && (response == null || (response != null && response.code() != 504))) {
showToast(R.string.invalidExternal);
}
}
};
canvasCallbackAssignment = new StatusCallback<Assignment>() {
@Override
public void onResponse(@NonNull Response<Assignment> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (!apiCheck()) {
return;
}
Assignment newAssignment = response.body();
String authenticationURL;
if (newAssignment == null) {
authenticationURL = null;
} else {
authenticationURL = newAssignment.getUrl();
}
// Now get the LTITool
// This API call handles url being null
SubmissionManager.getLtiFromAuthenticationUrl(authenticationURL, canvasCallbackLTITool, true);
}
};
}
use of com.instructure.canvasapi2.utils.LinkHeaders in project instructure-android by instructure.
the class AddSubmissionFragment method setUpCallback.
// /////////////////////////////////////////////////////////////////////////
// CallBack
// /////////////////////////////////////////////////////////////////////////
public void setUpCallback() {
canvasCallbackSubmission = new StatusCallback<Submission>() {
@Override
public void onResponse(@NonNull Response<Submission> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (!apiCheck()) {
return;
}
Submission result = response.body();
if (result.getBody() != null || result.getUrl() != null) {
Toast.makeText(getActivity(), R.string.successPostingSubmission, Toast.LENGTH_LONG).show();
// clear text fields because they are saved
textSubmission.setText("");
urlSubmission.setText("");
// Send broadcast so list is updated.
EventBus.getDefault().post(new FileUploadEvent(new FileUploadNotification(null, new ArrayList<Attachment>())));
Navigation navigation = getNavigation();
if (navigation != null)
navigation.popCurrentFragment();
} else {
Toast.makeText(getActivity(), R.string.errorPostingSubmission, Toast.LENGTH_LONG).show();
}
}
};
mLTIToolCallback = new StatusCallback<List<LTITool>>() {
@Override
public void onResponse(@NonNull Response<List<LTITool>> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
for (LTITool ltiTool : response.body()) {
final String url = ltiTool.getUrl();
if (url != null && url.contains("instructuremedia.com/lti/launch")) {
mArcUpload.setVisibility(View.VISIBLE);
mArcLTITool = ltiTool;
break;
}
}
// check to see if we should automatically show the file upload dialog
showFileUploadDialog();
}
@Override
public void onFail(@Nullable Call<List<LTITool>> call, @NonNull Throwable error, @Nullable Response response) {
// we don't want to show it if this failed due to there being no cache
if (response != null && response.code() != 504) {
showFileUploadDialog();
}
}
};
}
use of com.instructure.canvasapi2.utils.LinkHeaders in project instructure-android by instructure.
the class ModuleListRecyclerAdapter method getModuleItemsCallback.
private ModuleItemCallback getModuleItemsCallback(final ModuleObject moduleObject, final boolean isNotifyGroupChange) {
if (mModuleItemCallbacks.containsKey(moduleObject.getId())) {
return mModuleItemCallbacks.get(moduleObject.getId());
} else {
ModuleItemCallback moduleItemCallback = new ModuleItemCallback(moduleObject) {
private int checkMasteryPaths(int position, ModuleItem item) {
if (item.getMasteryPaths() != null && item.getMasteryPaths().isLocked()) {
// add another module item that says it's locked
ModuleItem masteryPathsLocked = new ModuleItem();
// set an id so that if there is more than one path we'll display all of them. otherwise addOrUpdateItem will overwrite it
masteryPathsLocked.setId(UUID.randomUUID().getLeastSignificantBits());
masteryPathsLocked.setTitle(String.format(Locale.getDefault(), getContext().getString(R.string.locked_mastery_paths), item.getTitle()));
masteryPathsLocked.setType(ModuleItem.TYPE.Locked.toString());
masteryPathsLocked.setCompletionRequirement(null);
masteryPathsLocked.setPosition(position++);
addOrUpdateItem(this.getModuleObject(), masteryPathsLocked);
} else if (item.getMasteryPaths() != null && !item.getMasteryPaths().isLocked() && item.getMasteryPaths().getSelectedSetId() == 0) {
// add another module item that says select to choose assignment group
// We only want to do this when we have a mastery paths object, it's unlocked, and the user hasn't already selected a set
ModuleItem masteryPathsSelect = new ModuleItem();
// set an id so that if there is more than one path we'll display all of them. otherwise addOrUpdateItem will overwrite it
masteryPathsSelect.setId(UUID.randomUUID().getLeastSignificantBits());
masteryPathsSelect.setTitle(getContext().getString(R.string.choose_assignment_group));
masteryPathsSelect.setType(ModuleItem.TYPE.ChooseAssignmentGroup.toString());
masteryPathsSelect.setCompletionRequirement(null);
masteryPathsSelect.setPosition(position++);
// sort the mastery paths by position
ArrayList<AssignmentSet> assignmentSets = new ArrayList<>();
assignmentSets.addAll(Arrays.asList(item.getMasteryPaths().getAssignmentSets()));
Collections.sort(assignmentSets, new Comparator<AssignmentSet>() {
@Override
public int compare(AssignmentSet lh, AssignmentSet rh) {
if (lh != null && rh != null) {
if (lh.getPosition() < rh.getPosition()) {
return -1;
} else if (lh.getPosition() > rh.getPosition()) {
return 1;
}
}
return 0;
}
});
AssignmentSet[] set = new AssignmentSet[assignmentSets.size()];
assignmentSets.toArray(set);
item.getMasteryPaths().setAssignmentSets(set);
masteryPathsSelect.setMasteryPathsItemId(item.getId());
masteryPathsSelect.setMasteryPaths(item.getMasteryPaths());
addOrUpdateItem(this.getModuleObject(), masteryPathsSelect);
}
return position;
}
@Override
public void onResponse(@NonNull Response<List<ModuleItem>> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
List<ModuleItem> moduleItems = response.body();
if (type == ApiType.API) {
int position = (moduleItems.size() > 0 && moduleItems.get(0) != null) ? moduleItems.get(0).getPosition() - 1 : 0;
for (ModuleItem item : moduleItems) {
item.setPosition(position++);
addOrUpdateItem(this.getModuleObject(), item);
position = checkMasteryPaths(position, item);
}
String nextItemsURL = linkHeaders.nextUrl;
if (nextItemsURL != null) {
ModuleManager.getNextPageModuleItems(nextItemsURL, this, true);
}
this.setIsFromNetwork(true);
expandGroup(this.getModuleObject(), isNotifyGroupChange);
} else if (type == ApiType.CACHE) {
int position = (moduleItems.size() > 0 && moduleItems.get(0) != null) ? moduleItems.get(0).getPosition() - 1 : 0;
for (ModuleItem item : moduleItems) {
item.setPosition(position++);
addOrUpdateItem(this.getModuleObject(), item);
}
String nextItemsURL = linkHeaders.nextUrl;
if (nextItemsURL != null) {
ModuleManager.getNextPageModuleItems(nextItemsURL, this, true);
}
// Wait for the network to expand when there are no items
if (moduleItems.size() > 0) {
expandGroup(this.getModuleObject(), isNotifyGroupChange);
}
}
}
@Override
public void onFail(@Nullable Call<List<ModuleItem>> call, @NonNull Throwable error, @Nullable Response response) {
// Only expand if there was no cache result and no network. No connection empty cell will be displayed
if (response != null && response.code() == 504 && APIHelper.isCachedResponse(response) && getContext() != null && !Utils.isNetworkAvailable(getContext())) {
expandGroup(this.getModuleObject(), isNotifyGroupChange);
}
}
};
mModuleItemCallbacks.put(moduleObject.getId(), moduleItemCallback);
return moduleItemCallback;
}
}
use of com.instructure.canvasapi2.utils.LinkHeaders in project instructure-android by instructure.
the class QuizSubmissionQuestionListRecyclerAdapter method addMultipleDropdown.
private void addMultipleDropdown(final QuizSubmissionQuestion baseItem, QuizMultipleDropdownViewHolder holder, int position, int courseColor) {
addAnsweredQuestion(baseItem);
QuizMultipleDropdownBinder.bind(holder, baseItem, courseColor, position, shouldLetAnswer, getContext(), embeddedWebViewCallback, webViewClientCallback, new QuizPostMultipleDropdown() {
@Override
public void postMultipleDropdown(final long questionId, HashMap<String, Long> answers) {
QuizManager.postQuizQuestionMultipleDropdown(quizSubmission, questionId, answers, true, new StatusCallback<QuizSubmissionQuestionResponse>() {
@Override
public void onResponse(@NonNull Response<QuizSubmissionQuestionResponse> response, @NonNull LinkHeaders linkHeaders, @NonNull ApiType type) {
if (type == ApiType.CACHE)
return;
QuizSubmissionQuestionResponse quizSubmissionQuestionResponse = response.body();
if (quizSubmissionQuestionResponse.getQuizSubmissionQuestions() != null) {
for (QuizSubmissionQuestion question : quizSubmissionQuestionResponse.getQuizSubmissionQuestions()) {
if (baseItem.getId() == question.getId()) {
baseItem.setAnswer(question.getAnswer());
}
}
// make sure each answer has a match
int numAnswers = 0;
// API returns a LinkedTreeMap
for (String map : ((LinkedTreeMap<String, String>) baseItem.getAnswer()).values()) {
if (map != null && !map.equals("null")) {
numAnswers++;
}
}
if (numAnswers == ((LinkedTreeMap<String, String>) baseItem.getAnswer()).size()) {
addAnsweredQuestion(questionId);
} else {
removeAnsweredQuestion(questionId);
}
}
}
});
}
}, flagStateCallback);
}
Aggregations