From fe2cc77c48f4226ab80aa77c2e7b3ac679cbc169 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 27 Jan 2017 18:27:44 +0300 Subject: [PATCH 01/38] get table quiz attempt.dataset fields --- .../java/org/stepic/droid/model/Dataset.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/stepic/droid/model/Dataset.java b/app/src/main/java/org/stepic/droid/model/Dataset.java index 91e358ec76..a88dc83da1 100644 --- a/app/src/main/java/org/stepic/droid/model/Dataset.java +++ b/app/src/main/java/org/stepic/droid/model/Dataset.java @@ -10,7 +10,11 @@ public class Dataset { private String someStringValueFromServer; private List pairs; private Boolean is_html_enabled; - List components; + private List components; + private List rows; + private List columns; + private String description; + private boolean is_checkbox; public Dataset() { } @@ -44,4 +48,20 @@ public Boolean getIs_html_enabled() { public List getFillBlankComponents() { return components; } + + public String getDescriptionTableQuiz() { + return description; + } + + public boolean isTableCheckbox() { + return is_checkbox; + } + + public List getTableRows() { + return rows; + } + + public List getTableColumns() { + return columns; + } } From d3b4fa237932d5d6f51198990c8ee21104e566d4 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 27 Jan 2017 19:08:42 +0300 Subject: [PATCH 02/38] add fields for table quiz to reply --- app/src/main/java/org/stepic/droid/model/Reply.java | 13 ++++++++----- .../org/stepic/droid/model/TableChoiceAnswer.kt | 7 +++++++ 2 files changed, 15 insertions(+), 5 deletions(-) create mode 100644 app/src/main/java/org/stepic/droid/model/TableChoiceAnswer.kt diff --git a/app/src/main/java/org/stepic/droid/model/Reply.java b/app/src/main/java/org/stepic/droid/model/Reply.java index e7578c616b..bda575ef06 100644 --- a/app/src/main/java/org/stepic/droid/model/Reply.java +++ b/app/src/main/java/org/stepic/droid/model/Reply.java @@ -3,7 +3,7 @@ import java.util.List; public class Reply { - private final List choices; + private final List choices; private final String text; private final List attachments; private final String formula; @@ -14,8 +14,7 @@ public class Reply { private final List blanks; public static class Builder { - - private List choices; + private List choices; private String text; private List attachments; private String formula; @@ -28,7 +27,7 @@ public static class Builder { public Builder() { } - public Builder setChoices(List choices) { + public Builder setChoices(List choices) { this.choices = choices; return this; } @@ -100,7 +99,7 @@ public String getText() { } public List getChoices() { - return choices; + return (List) choices; } public String getFormula() { @@ -126,4 +125,8 @@ public String getCode() { public List getBlanks() { return blanks; } + + public List getTableChoices() { + return (List) choices; + } } diff --git a/app/src/main/java/org/stepic/droid/model/TableChoiceAnswer.kt b/app/src/main/java/org/stepic/droid/model/TableChoiceAnswer.kt new file mode 100644 index 0000000000..abbf2537c3 --- /dev/null +++ b/app/src/main/java/org/stepic/droid/model/TableChoiceAnswer.kt @@ -0,0 +1,7 @@ +package org.stepic.droid.model + +data class TableChoiceAnswer(val name_row: String, val columns: List) { + companion object { + data class Cell(val name: String, val answer: Boolean) + } +} From fed0f4382da322366dc45191d7072b8e01d49dbb Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 30 Jan 2017 18:37:36 +0300 Subject: [PATCH 03/38] make base view for Table Quiz with plain text --- .../droid/ui/adapters/TableQuizAdapter.java | 170 ++++++++++++++++++ .../droid/ui/fragments/TableStepFragment.java | 108 +++++++++++ .../util/resolvers/StepTypeResolverImpl.java | 3 + .../layout/view_table_quiz_checkbox_cell.xml | 9 + .../res/layout/view_table_quiz_layout.xml | 9 + .../view_table_quiz_radio_button_cell.xml | 7 + .../res/layout/view_table_quiz_text_cell.xml | 8 + 7 files changed, 314 insertions(+) create mode 100644 app/src/main/java/org/stepic/droid/ui/adapters/TableQuizAdapter.java create mode 100644 app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java create mode 100644 app/src/main/res/layout/view_table_quiz_checkbox_cell.xml create mode 100644 app/src/main/res/layout/view_table_quiz_layout.xml create mode 100644 app/src/main/res/layout/view_table_quiz_radio_button_cell.xml create mode 100644 app/src/main/res/layout/view_table_quiz_text_cell.xml diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableQuizAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableQuizAdapter.java new file mode 100644 index 0000000000..6fc2ab3c16 --- /dev/null +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableQuizAdapter.java @@ -0,0 +1,170 @@ +package org.stepic.droid.ui.adapters; + +import android.support.v7.widget.AppCompatCheckBox; +import android.support.v7.widget.AppCompatRadioButton; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; + +import org.jetbrains.annotations.NotNull; +import org.stepic.droid.R; +import org.stepic.droid.model.TableChoiceAnswer; + +import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +public class TableQuizAdapter extends RecyclerView.Adapter { + + private static final int DESCRIPTION_TYPE = 0; + private static final int CHECKBOX_TYPE = 1; + private static final int RADIO_BUTTON_TYPE = 2; + private static final int ROW_HEADER_TYPE = 3; + private static final int COLUMN_HEADER_TYPE = 4; + + + private final List columns; + private final List rows; + private final String description; + private final boolean isCheckbox; + private final List answers; + + @Override + public int getItemViewType(int position) { + if (position == 0) { + return DESCRIPTION_TYPE; + } else if (position <= rows.size()) { + return ROW_HEADER_TYPE; + } else if (position % (rows.size() + 1) == 0) { + return COLUMN_HEADER_TYPE; + } else if (isCheckbox) { + return CHECKBOX_TYPE; + } else { + return RADIO_BUTTON_TYPE; + } + } + + public TableQuizAdapter(List rows, List columns, String description, boolean isCheckbox, List answers) { + this.columns = columns; + this.rows = rows; + this.description = description; + this.isCheckbox = isCheckbox; + this.answers = answers; + } + + + @Override + public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { + if (viewType == RADIO_BUTTON_TYPE) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_table_quiz_radio_button_cell, parent, false); + return new RadioButtonCellViewHolder(v); + } else if (viewType == CHECKBOX_TYPE) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_table_quiz_checkbox_cell, parent, false); + return new CheckboxCellViewHolder(v); + } else if (viewType == DESCRIPTION_TYPE || viewType == ROW_HEADER_TYPE || viewType == COLUMN_HEADER_TYPE) { + View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_table_quiz_text_cell, parent, false); + return new DescriptionViewHolder(v); + } else { + throw new IllegalStateException("viewType with index " + viewType + " is not supported in table quiz"); + } + } + + @Override + public void onBindViewHolder(GenericViewHolder holder, int position) { + int itemViewType = getItemViewType(position); + if (itemViewType == DESCRIPTION_TYPE) { + holder.setData(description); + } else if (itemViewType == ROW_HEADER_TYPE) { + String headerText = rows.get(position - 1); + holder.setData(headerText); + } else if (itemViewType == COLUMN_HEADER_TYPE) { + int columnPosition = position / (rows.size() + 1) - 1; // -1 is description cell at top left cell + String headerText = columns.get(columnPosition); + holder.setData(headerText); + } else { + holder.setData(false); + } + } + + @Override + public int getItemCount() { + return rows.size() + columns.size() + 1 + rows.size() * columns.size(); //1 – description top left cell. + } + + static abstract class GenericViewHolder extends RecyclerView.ViewHolder { + + public GenericViewHolder(View itemView) { + super(itemView); + ButterKnife.bind(this, itemView); + } + + public abstract void setData(@NotNull String text); + + public abstract void setData(@NotNull Boolean needCheckModel); + } + + + static class DescriptionViewHolder extends GenericViewHolder { + + @BindView(R.id.cell_text) + TextView textView; + + public DescriptionViewHolder(View itemView) { + super(itemView); + } + + @Override + public void setData(@NotNull String text) { + textView.setText(text); + } + + @Override + public void setData(@NotNull Boolean needCheck) { + throw new IllegalStateException("description view can't be without text, check position"); + } + + } + + static class CheckboxCellViewHolder extends GenericViewHolder { + + @BindView(R.id.checkbox_cell) + AppCompatCheckBox checkBox; + + public CheckboxCellViewHolder(View itemView) { + super(itemView); + } + + @Override + public void setData(@NotNull String text) { + throw new IllegalStateException("checkbox view can't be without need checked"); + } + + @Override + public void setData(@NotNull Boolean needCheck) { + checkBox.setChecked(needCheck); + } + } + + static class RadioButtonCellViewHolder extends GenericViewHolder { + + @BindView(R.id.radio_button_cell) + AppCompatRadioButton radioButton; + + public RadioButtonCellViewHolder(View itemView) { + super(itemView); + } + + @Override + public void setData(@NotNull String text) { + throw new IllegalStateException("radio button view can't be without need checked"); + } + + @Override + public void setData(@NotNull Boolean needCheck) { + radioButton.setChecked(needCheck); + } + } +} diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java b/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java new file mode 100644 index 0000000000..2a488309e5 --- /dev/null +++ b/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java @@ -0,0 +1,108 @@ +package org.stepic.droid.ui.fragments; + +import android.content.Context; +import android.os.Bundle; +import android.support.annotation.Nullable; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; + +import com.squareup.otto.Subscribe; + +import org.stepic.droid.R; +import org.stepic.droid.events.InternetIsEnabledEvent; +import org.stepic.droid.events.comments.NewCommentWasAddedOrUpdateEvent; +import org.stepic.droid.events.steps.StepWasUpdatedEvent; +import org.stepic.droid.model.Attempt; +import org.stepic.droid.model.Dataset; +import org.stepic.droid.model.Reply; +import org.stepic.droid.model.TableChoiceAnswer; +import org.stepic.droid.ui.adapters.TableQuizAdapter; +import org.stepic.droid.util.DpPixelsHelper; + +import java.util.ArrayList; +import java.util.List; + +import butterknife.ButterKnife; + +public class TableStepFragment extends StepAttemptFragment { + + public static TableStepFragment newInstance() { + return new TableStepFragment(); + } + + private RecyclerView recyclerContainer; + + @Nullable + GridLayoutManager gridLayoutManager; + + + @Override + public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { + super.onViewCreated(view, savedInstanceState); + View tableQuizView = ((LayoutInflater) this.getActivity().getSystemService(Context.LAYOUT_INFLATER_SERVICE)).inflate(R.layout.view_table_quiz_layout, attemptContainer, false); + int dp8inPx = (int) DpPixelsHelper.convertDpToPixel(8f); + attemptContainer.setPadding(0, dp8inPx, 0, dp8inPx); + recyclerContainer = ButterKnife.findById(tableQuizView, R.id.recycler); + recyclerContainer.setNestedScrollingEnabled(false); + attemptContainer.addView(tableQuizView); + } + + @Override + protected void showAttempt(Attempt attempt) { + Dataset dataset = attempt.getDataset(); + List rows = dataset.getTableRows(); + List columns = dataset.getTableColumns(); + String description = dataset.getDescriptionTableQuiz(); + boolean isCheckbox = dataset.isTableCheckbox(); + + gridLayoutManager = new GridLayoutManager(getContext(), rows.size() + 1, GridLayoutManager.HORIZONTAL, false); + RecyclerView.Adapter adapter = new TableQuizAdapter(rows, columns, description, isCheckbox, new ArrayList()); + recyclerContainer.setLayoutManager(gridLayoutManager); + recyclerContainer.setAdapter(adapter); + } + + @Override + protected Reply generateReply() { + //todo get from user answer (some list) + + //stub: + List choiceAnswerList = new ArrayList<>(); + List cellsInFirstRow = new ArrayList<>(); + cellsInFirstRow.add(new TableChoiceAnswer.Companion.Cell("One", true)); + TableChoiceAnswer tableChoiceAnswer = new TableChoiceAnswer("Name of row", cellsInFirstRow); + choiceAnswerList.add(tableChoiceAnswer); + + return new Reply.Builder() + .setChoices(choiceAnswerList) + .build(); + } + + @Override + protected void blockUIBeforeSubmit(boolean needBlock) { + //todo block elements in list + } + + @Override + protected void onRestoreSubmission() { + //todo notify quiz changed + } + + @Subscribe + @Override + public void onInternetEnabled(InternetIsEnabledEvent enabledEvent) { + super.onInternetEnabled(enabledEvent); + } + + @Subscribe + public void onNewCommentWasAdded(NewCommentWasAddedOrUpdateEvent event) { + super.onNewCommentWasAdded(event); + + } + + @Subscribe + public void onStepWasUpdated(StepWasUpdatedEvent event) { + super.onStepWasUpdated(event); + } +} diff --git a/app/src/main/java/org/stepic/droid/util/resolvers/StepTypeResolverImpl.java b/app/src/main/java/org/stepic/droid/util/resolvers/StepTypeResolverImpl.java index 7a2eb9abe2..1e79b275e9 100644 --- a/app/src/main/java/org/stepic/droid/util/resolvers/StepTypeResolverImpl.java +++ b/app/src/main/java/org/stepic/droid/util/resolvers/StepTypeResolverImpl.java @@ -12,6 +12,7 @@ import org.stepic.droid.base.StepBaseFragment; import org.stepic.droid.model.Step; import org.stepic.droid.ui.fragments.FillBlanksFragment; +import org.stepic.droid.ui.fragments.TableStepFragment; import org.stepic.droid.util.AppConstants; import org.stepic.droid.ui.fragments.ChoiceStepFragment; import org.stepic.droid.ui.fragments.FreeResponseStepFragment; @@ -184,6 +185,8 @@ public StepBaseFragment getFragment(Step step) { return new MatchingStepFragment(); case AppConstants.TYPE_FILL_BLANKS: return new FillBlanksFragment(); + case AppConstants.TYPE_TABLE: + return TableStepFragment.newInstance(); default: return new NotSupportedYetStepFragment(); } diff --git a/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml b/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml new file mode 100644 index 0000000000..db2393cad0 --- /dev/null +++ b/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_table_quiz_layout.xml b/app/src/main/res/layout/view_table_quiz_layout.xml new file mode 100644 index 0000000000..45f86ac7ef --- /dev/null +++ b/app/src/main/res/layout/view_table_quiz_layout.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml b/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml new file mode 100644 index 0000000000..0b0d1ddca5 --- /dev/null +++ b/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml @@ -0,0 +1,7 @@ + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_table_quiz_text_cell.xml b/app/src/main/res/layout/view_table_quiz_text_cell.xml new file mode 100644 index 0000000000..8bfd46a66c --- /dev/null +++ b/app/src/main/res/layout/view_table_quiz_text_cell.xml @@ -0,0 +1,8 @@ + + + + \ No newline at end of file From 518de6e50502c44620164bf5573300a46ff34fdb Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 30 Jan 2017 19:05:12 +0300 Subject: [PATCH 04/38] generate blank answer list --- .../droid/ui/fragments/TableStepFragment.java | 20 ++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java b/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java index 2a488309e5..580dc47bed 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java +++ b/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java @@ -33,6 +33,7 @@ public static TableStepFragment newInstance() { } private RecyclerView recyclerContainer; + private List answerList; @Nullable GridLayoutManager gridLayoutManager; @@ -57,12 +58,29 @@ protected void showAttempt(Attempt attempt) { String description = dataset.getDescriptionTableQuiz(); boolean isCheckbox = dataset.isTableCheckbox(); + answerList = initAnswerListFromAttempt(rows, columns); + gridLayoutManager = new GridLayoutManager(getContext(), rows.size() + 1, GridLayoutManager.HORIZONTAL, false); - RecyclerView.Adapter adapter = new TableQuizAdapter(rows, columns, description, isCheckbox, new ArrayList()); + RecyclerView.Adapter adapter = new TableQuizAdapter(rows, columns, description, isCheckbox, answerList); recyclerContainer.setLayoutManager(gridLayoutManager); recyclerContainer.setAdapter(adapter); } + private ArrayList initAnswerListFromAttempt(List rows, List columns) { + // may be we should do it on background thread, but then we should rewrite logic of parent class, and do same actions for each quiz on background thread + ArrayList result = new ArrayList<>(rows.size()); + for (String nameRow : rows) { + List oneRowAnswer = new ArrayList<>(columns.size()); + //we should create new objects for each try –> it is generated in for cycle (but Strings is same objects) + for (String nameColumn : columns) { + oneRowAnswer.add(new TableChoiceAnswer.Companion.Cell(nameColumn, false)); + } + result.add(new TableChoiceAnswer(nameRow, oneRowAnswer)); + } + + return result; + } + @Override protected Reply generateReply() { //todo get from user answer (some list) From 23b91fde863f1b8796510cf16c248f08b4cc88b8 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 30 Jan 2017 19:07:58 +0300 Subject: [PATCH 05/38] implement onRestoreSubmission --- .../droid/ui/fragments/TableStepFragment.java | 26 ++++++++++--------- 1 file changed, 14 insertions(+), 12 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java b/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java index 580dc47bed..dfd72e2ed2 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java +++ b/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java @@ -38,6 +38,8 @@ public static TableStepFragment newInstance() { @Nullable GridLayoutManager gridLayoutManager; + RecyclerView.Adapter adapter; + @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { @@ -61,7 +63,7 @@ protected void showAttempt(Attempt attempt) { answerList = initAnswerListFromAttempt(rows, columns); gridLayoutManager = new GridLayoutManager(getContext(), rows.size() + 1, GridLayoutManager.HORIZONTAL, false); - RecyclerView.Adapter adapter = new TableQuizAdapter(rows, columns, description, isCheckbox, answerList); + adapter = new TableQuizAdapter(rows, columns, description, isCheckbox, answerList); recyclerContainer.setLayoutManager(gridLayoutManager); recyclerContainer.setAdapter(adapter); } @@ -83,17 +85,8 @@ private ArrayList initAnswerListFromAttempt(List rows @Override protected Reply generateReply() { - //todo get from user answer (some list) - - //stub: - List choiceAnswerList = new ArrayList<>(); - List cellsInFirstRow = new ArrayList<>(); - cellsInFirstRow.add(new TableChoiceAnswer.Companion.Cell("One", true)); - TableChoiceAnswer tableChoiceAnswer = new TableChoiceAnswer("Name of row", cellsInFirstRow); - choiceAnswerList.add(tableChoiceAnswer); - return new Reply.Builder() - .setChoices(choiceAnswerList) + .setChoices(answerList) .build(); } @@ -104,7 +97,16 @@ protected void blockUIBeforeSubmit(boolean needBlock) { @Override protected void onRestoreSubmission() { - //todo notify quiz changed + Reply reply = submission.getReply(); + if (reply == null) return; + + List choices = reply.getTableChoices(); + if (choices == null) return; + + answerList.clear(); + answerList.addAll(choices); + + adapter.notifyDataSetChanged(); } @Subscribe From 22f265249bf309b4174ab3b5902a488347183bfd Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 30 Jan 2017 21:20:46 +0300 Subject: [PATCH 06/38] make Reply custom serializer and deserializer for sending and getting them (and restore submission too) --- .../deserializers/ReplyDeserializer.java | 58 ++++++++++++ .../java/org/stepic/droid/model/Reply.java | 23 ++++- .../org/stepic/droid/model/ReplyWrapper.java | 14 +++ .../org/stepic/droid/model/Submission.java | 6 +- .../stepic/droid/model/TableChoiceAnswer.kt | 2 +- .../droid/serializers/ReplySerializer.java | 28 ++++++ ...izAdapter.java => TableChoiceAdapter.java} | 91 ++++++++++++++----- ...ment.java => TableChoiceStepFragment.java} | 12 +-- .../CheckedChangeListenerWithPosition.java | 7 ++ .../util/resolvers/StepTypeResolverImpl.java | 4 +- .../org/stepic/droid/web/RetrofitRESTApi.java | 5 + 11 files changed, 210 insertions(+), 40 deletions(-) create mode 100644 app/src/main/java/org/stepic/droid/deserializers/ReplyDeserializer.java create mode 100644 app/src/main/java/org/stepic/droid/model/ReplyWrapper.java create mode 100644 app/src/main/java/org/stepic/droid/serializers/ReplySerializer.java rename app/src/main/java/org/stepic/droid/ui/adapters/{TableQuizAdapter.java => TableChoiceAdapter.java} (56%) rename app/src/main/java/org/stepic/droid/ui/fragments/{TableStepFragment.java => TableChoiceStepFragment.java} (92%) create mode 100644 app/src/main/java/org/stepic/droid/ui/listeners/CheckedChangeListenerWithPosition.java diff --git a/app/src/main/java/org/stepic/droid/deserializers/ReplyDeserializer.java b/app/src/main/java/org/stepic/droid/deserializers/ReplyDeserializer.java new file mode 100644 index 0000000000..56af6686b3 --- /dev/null +++ b/app/src/main/java/org/stepic/droid/deserializers/ReplyDeserializer.java @@ -0,0 +1,58 @@ +package org.stepic.droid.deserializers; + + +import android.support.annotation.NonNull; + +import com.google.gson.JsonArray; +import com.google.gson.JsonDeserializationContext; +import com.google.gson.JsonDeserializer; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParseException; + +import org.stepic.droid.model.Reply; +import org.stepic.droid.model.ReplyWrapper; +import org.stepic.droid.model.TableChoiceAnswer; + +import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; + +public class ReplyDeserializer implements JsonDeserializer { + + + @Override + public ReplyWrapper deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { + try { + JsonObject reply = json.getAsJsonObject(); + if (reply.has("choices")) { + JsonArray choiceElements = reply.get("choices").getAsJsonArray(); + int size = choiceElements.size(); + List tableChoiceAnswerList = new ArrayList<>(); + if (size != 0) { + for (int i = 0; i < size; i++) { + JsonElement tableChoiceElement = choiceElements.get(i); + TableChoiceAnswer tableChoiceAnswer = context.deserialize(tableChoiceElement, TableChoiceAnswer.class); + tableChoiceAnswerList.add(tableChoiceAnswer); + } + } + json.getAsJsonObject().remove("choices"); + Reply originReply = context.deserialize(json, Reply.class); + originReply.setTableChoices(tableChoiceAnswerList); + return new ReplyWrapper(originReply); + } else { + return deserializeAsReply(json, context); + } + + } catch (Exception exception) { + return deserializeAsReply(json, context); + } + + } + + // if we do not find table choices -> deserialize as Reply + @NonNull + private ReplyWrapper deserializeAsReply(JsonElement json, JsonDeserializationContext context) { + return new ReplyWrapper((Reply) context.deserialize(json, Reply.class)); + } +} \ No newline at end of file diff --git a/app/src/main/java/org/stepic/droid/model/Reply.java b/app/src/main/java/org/stepic/droid/model/Reply.java index bda575ef06..f9749f1d2e 100644 --- a/app/src/main/java/org/stepic/droid/model/Reply.java +++ b/app/src/main/java/org/stepic/droid/model/Reply.java @@ -3,7 +3,7 @@ import java.util.List; public class Reply { - private final List choices; + private final List choices; private final String text; private final List attachments; private final String formula; @@ -13,8 +13,10 @@ public class Reply { private final String code; private final List blanks; + private List tableChoices; //this is not serialize by default, because field 'choices' is already created by different type + public static class Builder { - private List choices; + private List choices; private String text; private List attachments; private String formula; @@ -24,10 +26,18 @@ public static class Builder { private String code; private List blanks; + + public List tableChoices; + public Builder() { } - public Builder setChoices(List choices) { + public Builder setTableChoices(List tableChoices) { + this.tableChoices = tableChoices; + return this; + } + + public Builder setChoices(List choices) { this.choices = choices; return this; } @@ -88,6 +98,7 @@ private Reply(Builder builder) { language = builder.language; code = builder.code; blanks = builder.blanks; + tableChoices = builder.tableChoices; } public String getNumber() { @@ -127,6 +138,10 @@ public List getBlanks() { } public List getTableChoices() { - return (List) choices; + return tableChoices; + } + + public void setTableChoices(List tableChoices) { + this.tableChoices = tableChoices; } } diff --git a/app/src/main/java/org/stepic/droid/model/ReplyWrapper.java b/app/src/main/java/org/stepic/droid/model/ReplyWrapper.java new file mode 100644 index 0000000000..4171a5da8d --- /dev/null +++ b/app/src/main/java/org/stepic/droid/model/ReplyWrapper.java @@ -0,0 +1,14 @@ +package org.stepic.droid.model; + +public class ReplyWrapper { + private final Reply reply; + + public ReplyWrapper(Reply reply) { + this.reply = reply; + } + + public Reply getReply() { + return reply; + } + +} diff --git a/app/src/main/java/org/stepic/droid/model/Submission.java b/app/src/main/java/org/stepic/droid/model/Submission.java index 90f73002fd..e22155b7a7 100644 --- a/app/src/main/java/org/stepic/droid/model/Submission.java +++ b/app/src/main/java/org/stepic/droid/model/Submission.java @@ -39,13 +39,13 @@ public String getScope() { private String score; private String hint; private String time; - private Reply reply; + private ReplyWrapper reply; private long attempt; private String session; private String eta; public Submission(Reply reply, long attempt) { - this.reply = reply; + this.reply = new ReplyWrapper(reply); this.attempt = attempt; } @@ -76,7 +76,7 @@ public String getTime() { } public Reply getReply() { - return reply; + return reply.getReply(); } public long getAttempt() { diff --git a/app/src/main/java/org/stepic/droid/model/TableChoiceAnswer.kt b/app/src/main/java/org/stepic/droid/model/TableChoiceAnswer.kt index abbf2537c3..f840978e2d 100644 --- a/app/src/main/java/org/stepic/droid/model/TableChoiceAnswer.kt +++ b/app/src/main/java/org/stepic/droid/model/TableChoiceAnswer.kt @@ -2,6 +2,6 @@ package org.stepic.droid.model data class TableChoiceAnswer(val name_row: String, val columns: List) { companion object { - data class Cell(val name: String, val answer: Boolean) + data class Cell(val name: String, var answer: Boolean) } } diff --git a/app/src/main/java/org/stepic/droid/serializers/ReplySerializer.java b/app/src/main/java/org/stepic/droid/serializers/ReplySerializer.java new file mode 100644 index 0000000000..a8d4500b8d --- /dev/null +++ b/app/src/main/java/org/stepic/droid/serializers/ReplySerializer.java @@ -0,0 +1,28 @@ +package org.stepic.droid.serializers; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonSerializationContext; +import com.google.gson.JsonSerializer; + +import org.stepic.droid.model.Reply; +import org.stepic.droid.model.ReplyWrapper; + +import java.lang.reflect.Type; + +public class ReplySerializer implements JsonSerializer { + @Override + public JsonElement serialize(ReplyWrapper src, Type typeOfSrc, JsonSerializationContext context) { + Reply reply = src.getReply(); + if (reply.getTableChoices() == null) { + return context.serialize(reply); + } else { + JsonElement tableChoicesJsonElement = context.serialize(reply.getTableChoices(), reply.getTableChoices().getClass()); + reply.setTableChoices(null); + JsonElement replyJsonElement = context.serialize(reply); + JsonObject replyJsonObject = replyJsonElement.getAsJsonObject(); + replyJsonObject.add("choices", tableChoicesJsonElement); + return replyJsonObject; + } + } +} diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableQuizAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java similarity index 56% rename from app/src/main/java/org/stepic/droid/ui/adapters/TableQuizAdapter.java rename to app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index 6fc2ab3c16..cf776a6ed0 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableQuizAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -6,18 +6,20 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.CompoundButton; import android.widget.TextView; import org.jetbrains.annotations.NotNull; import org.stepic.droid.R; import org.stepic.droid.model.TableChoiceAnswer; +import org.stepic.droid.ui.listeners.CheckedChangeListenerWithPosition; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; -public class TableQuizAdapter extends RecyclerView.Adapter { +public class TableChoiceAdapter extends RecyclerView.Adapter implements CheckedChangeListenerWithPosition { private static final int DESCRIPTION_TYPE = 0; private static final int CHECKBOX_TYPE = 1; @@ -47,12 +49,13 @@ public int getItemViewType(int position) { } } - public TableQuizAdapter(List rows, List columns, String description, boolean isCheckbox, List answers) { + public TableChoiceAdapter(List rows, List columns, String description, boolean isCheckbox, List answers) { this.columns = columns; this.rows = rows; this.description = description; this.isCheckbox = isCheckbox; this.answers = answers; + int i = 0; } @@ -60,10 +63,10 @@ public TableQuizAdapter(List rows, List columns, String descript public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { if (viewType == RADIO_BUTTON_TYPE) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_table_quiz_radio_button_cell, parent, false); - return new RadioButtonCellViewHolder(v); + return new RadioButtonCellViewHolder(v, this); } else if (viewType == CHECKBOX_TYPE) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_table_quiz_checkbox_cell, parent, false); - return new CheckboxCellViewHolder(v); + return new CheckboxCellViewHolder(v, this); } else if (viewType == DESCRIPTION_TYPE || viewType == ROW_HEADER_TYPE || viewType == COLUMN_HEADER_TYPE) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_table_quiz_text_cell, parent, false); return new DescriptionViewHolder(v); @@ -81,19 +84,43 @@ public void onBindViewHolder(GenericViewHolder holder, int position) { String headerText = rows.get(position - 1); holder.setData(headerText); } else if (itemViewType == COLUMN_HEADER_TYPE) { - int columnPosition = position / (rows.size() + 1) - 1; // -1 is description cell at top left cell + int columnPosition = getColumnPosition(position); // -1 is description cell at top left cell String headerText = columns.get(columnPosition); holder.setData(headerText); } else { - holder.setData(false); + List oneRowAnswers = getOneRowAnswersFromPosition(position); + int columnPosition = getColumnPosition(position); + TableChoiceAnswer.Companion.Cell cell = oneRowAnswers.get(columnPosition); + holder.setData(cell.getAnswer()); } } + private int getColumnPosition(int position) { + return position / (rows.size() + 1) - 1; + } + + private List getOneRowAnswersFromPosition(int position) { + int rowPosition = (position - 1) % (rows.size() + 1); + TableChoiceAnswer tableChoiceAnswer = answers.get(rowPosition); + return tableChoiceAnswer.getColumns(); + } + @Override public int getItemCount() { return rows.size() + columns.size() + 1 + rows.size() * columns.size(); //1 – description top left cell. } + + @Override + public void onCheckedChanged(CompoundButton view, boolean isChecked, int position) { + List oneRowAnswers = getOneRowAnswersFromPosition(position); + int columnPosition = getColumnPosition(position); + TableChoiceAnswer.Companion.Cell cell = oneRowAnswers.get(columnPosition); + cell.setAnswer(isChecked); + + // TODO: 30.01.17 add if radio button + } + static abstract class GenericViewHolder extends RecyclerView.ViewHolder { public GenericViewHolder(View itemView) { @@ -128,43 +155,59 @@ public void setData(@NotNull Boolean needCheck) { } - static class CheckboxCellViewHolder extends GenericViewHolder { - - @BindView(R.id.checkbox_cell) - AppCompatCheckBox checkBox; - public CheckboxCellViewHolder(View itemView) { + static abstract class CompoundButtonViewHolder extends GenericViewHolder { + public CompoundButtonViewHolder(View itemView, final CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { super(itemView); + getCheckableView().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + checkedChangeListenerWithPosition.onCheckedChanged(buttonView, isChecked, getAdapterPosition()); + } + }); } @Override - public void setData(@NotNull String text) { - throw new IllegalStateException("checkbox view can't be without need checked"); + public final void setData(@NotNull String text) { + throw new IllegalStateException("text is not allowed in table view quiz"); } @Override - public void setData(@NotNull Boolean needCheck) { - checkBox.setChecked(needCheck); + public final void setData(@NotNull Boolean needCheckModel) { + getCheckableView().setChecked(needCheckModel); } + + abstract CompoundButton getCheckableView(); } - static class RadioButtonCellViewHolder extends GenericViewHolder { + static class CheckboxCellViewHolder extends CompoundButtonViewHolder { - @BindView(R.id.radio_button_cell) - AppCompatRadioButton radioButton; + @BindView(R.id.checkbox_cell) + AppCompatCheckBox checkBox; - public RadioButtonCellViewHolder(View itemView) { - super(itemView); + public CheckboxCellViewHolder(View itemView, CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { + super(itemView, checkedChangeListenerWithPosition); } @Override - public void setData(@NotNull String text) { - throw new IllegalStateException("radio button view can't be without need checked"); + CompoundButton getCheckableView() { + return checkBox; + } + } + + static class RadioButtonCellViewHolder extends CompoundButtonViewHolder { + + @BindView(R.id.radio_button_cell) + AppCompatRadioButton radioButton; + + public RadioButtonCellViewHolder(View itemView, final CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { + super(itemView, checkedChangeListenerWithPosition); } @Override - public void setData(@NotNull Boolean needCheck) { - radioButton.setChecked(needCheck); + CompoundButton getCheckableView() { + return radioButton; } } } + diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java b/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java similarity index 92% rename from app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java rename to app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java index dfd72e2ed2..b33432f822 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/TableStepFragment.java +++ b/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java @@ -18,7 +18,7 @@ import org.stepic.droid.model.Dataset; import org.stepic.droid.model.Reply; import org.stepic.droid.model.TableChoiceAnswer; -import org.stepic.droid.ui.adapters.TableQuizAdapter; +import org.stepic.droid.ui.adapters.TableChoiceAdapter; import org.stepic.droid.util.DpPixelsHelper; import java.util.ArrayList; @@ -26,10 +26,10 @@ import butterknife.ButterKnife; -public class TableStepFragment extends StepAttemptFragment { +public class TableChoiceStepFragment extends StepAttemptFragment { - public static TableStepFragment newInstance() { - return new TableStepFragment(); + public static TableChoiceStepFragment newInstance() { + return new TableChoiceStepFragment(); } private RecyclerView recyclerContainer; @@ -63,7 +63,7 @@ protected void showAttempt(Attempt attempt) { answerList = initAnswerListFromAttempt(rows, columns); gridLayoutManager = new GridLayoutManager(getContext(), rows.size() + 1, GridLayoutManager.HORIZONTAL, false); - adapter = new TableQuizAdapter(rows, columns, description, isCheckbox, answerList); + adapter = new TableChoiceAdapter(rows, columns, description, isCheckbox, answerList); recyclerContainer.setLayoutManager(gridLayoutManager); recyclerContainer.setAdapter(adapter); } @@ -86,7 +86,7 @@ private ArrayList initAnswerListFromAttempt(List rows @Override protected Reply generateReply() { return new Reply.Builder() - .setChoices(answerList) + .setTableChoices(answerList) .build(); } diff --git a/app/src/main/java/org/stepic/droid/ui/listeners/CheckedChangeListenerWithPosition.java b/app/src/main/java/org/stepic/droid/ui/listeners/CheckedChangeListenerWithPosition.java new file mode 100644 index 0000000000..078c7f1c19 --- /dev/null +++ b/app/src/main/java/org/stepic/droid/ui/listeners/CheckedChangeListenerWithPosition.java @@ -0,0 +1,7 @@ +package org.stepic.droid.ui.listeners; + +import android.widget.CompoundButton; + +public interface CheckedChangeListenerWithPosition { + void onCheckedChanged(CompoundButton view, boolean isChecked, int position); +} diff --git a/app/src/main/java/org/stepic/droid/util/resolvers/StepTypeResolverImpl.java b/app/src/main/java/org/stepic/droid/util/resolvers/StepTypeResolverImpl.java index 1e79b275e9..0e0b62710b 100644 --- a/app/src/main/java/org/stepic/droid/util/resolvers/StepTypeResolverImpl.java +++ b/app/src/main/java/org/stepic/droid/util/resolvers/StepTypeResolverImpl.java @@ -12,7 +12,7 @@ import org.stepic.droid.base.StepBaseFragment; import org.stepic.droid.model.Step; import org.stepic.droid.ui.fragments.FillBlanksFragment; -import org.stepic.droid.ui.fragments.TableStepFragment; +import org.stepic.droid.ui.fragments.TableChoiceStepFragment; import org.stepic.droid.util.AppConstants; import org.stepic.droid.ui.fragments.ChoiceStepFragment; import org.stepic.droid.ui.fragments.FreeResponseStepFragment; @@ -186,7 +186,7 @@ public StepBaseFragment getFragment(Step step) { case AppConstants.TYPE_FILL_BLANKS: return new FillBlanksFragment(); case AppConstants.TYPE_TABLE: - return TableStepFragment.newInstance(); + return TableChoiceStepFragment.newInstance(); default: return new NotSupportedYetStepFragment(); } diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index a1021c97f7..3bcbaec2a5 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -31,18 +31,21 @@ import org.stepic.droid.configuration.IConfig; import org.stepic.droid.core.ScreenManager; import org.stepic.droid.deserializers.DatasetDeserializer; +import org.stepic.droid.deserializers.ReplyDeserializer; import org.stepic.droid.model.Course; import org.stepic.droid.model.DatasetWrapper; import org.stepic.droid.model.EnrollmentWrapper; import org.stepic.droid.model.Profile; import org.stepic.droid.model.RegistrationUser; import org.stepic.droid.model.Reply; +import org.stepic.droid.model.ReplyWrapper; import org.stepic.droid.model.comments.Comment; import org.stepic.droid.model.comments.Vote; import org.stepic.droid.model.comments.VoteValue; import org.stepic.droid.notifications.model.Notification; import org.stepic.droid.preferences.SharedPreferenceHelper; import org.stepic.droid.preferences.UserPreferences; +import org.stepic.droid.serializers.ReplySerializer; import org.stepic.droid.social.ISocialType; import org.stepic.droid.social.SocialManager; import org.stepic.droid.store.operations.DatabaseFacade; @@ -240,6 +243,8 @@ public Response intercept(Chain chain) throws IOException { private Converter.Factory generateGsonFactory() { Gson gson = new GsonBuilder() .registerTypeAdapter(DatasetWrapper.class, new DatasetDeserializer()) + .registerTypeAdapter(ReplyWrapper.class, new ReplyDeserializer()) + .registerTypeAdapter(ReplyWrapper.class, new ReplySerializer()) .serializeNulls() .create(); return GsonConverterFactory.create(gson); From 8caf3d2ae6cae8101d0d4fbb1dc8238ac01c1494 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Tue, 31 Jan 2017 15:36:17 +0300 Subject: [PATCH 07/38] Allow only one choice for radiobuttons in tables --- .../droid/ui/adapters/TableChoiceAdapter.java | 34 +++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index cf776a6ed0..3d88c29b62 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -14,6 +14,7 @@ import org.stepic.droid.model.TableChoiceAnswer; import org.stepic.droid.ui.listeners.CheckedChangeListenerWithPosition; +import java.util.ArrayList; import java.util.List; import butterknife.BindView; @@ -115,10 +116,37 @@ public int getItemCount() { public void onCheckedChanged(CompoundButton view, boolean isChecked, int position) { List oneRowAnswers = getOneRowAnswersFromPosition(position); int columnPosition = getColumnPosition(position); + + int multiplier = rows.size() + 1; + int remainder = position % multiplier; + + + List changed = new ArrayList<>(); + if (!isCheckbox && isChecked) { + //radio button, check something -> uncheck others + int i = 1; + for (TableChoiceAnswer.Companion.Cell eachCellInRow : oneRowAnswers) { + if (eachCellInRow.getAnswer()) { + //if something is checked + int currentAdapterPosition = multiplier * i + remainder; + eachCellInRow.setAnswer(false); + if (currentAdapterPosition != position) { + changed.add(currentAdapterPosition); + } + } + i++; + } + } + + // change checked state TableChoiceAnswer.Companion.Cell cell = oneRowAnswers.get(columnPosition); cell.setAnswer(isChecked); - // TODO: 30.01.17 add if radio button + if (!changed.isEmpty()) { + for (Integer changedPosition : changed) { + notifyItemChanged(changedPosition); // In the perfect world there is only one for radiobutton + } + } } static abstract class GenericViewHolder extends RecyclerView.ViewHolder { @@ -162,7 +190,9 @@ public CompoundButtonViewHolder(View itemView, final CheckedChangeListenerWithPo getCheckableView().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { - checkedChangeListenerWithPosition.onCheckedChanged(buttonView, isChecked, getAdapterPosition()); + if (buttonView.isPressed()) { + checkedChangeListenerWithPosition.onCheckedChanged(buttonView, isChecked, getAdapterPosition()); + } } }); } From e1cc00f731c718906664e52e3ae460b0b58f56e1 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Tue, 31 Jan 2017 17:16:08 +0300 Subject: [PATCH 08/38] add latex view, check view is centered now --- .../droid/ui/adapters/TableChoiceAdapter.java | 86 +++++++++++++++++-- .../droid/ui/custom/ProgressLatexView.java | 4 + .../ui/fragments/TableChoiceStepFragment.java | 3 +- .../layout/view_table_quiz_checkbox_cell.xml | 15 +++- .../res/layout/view_table_quiz_layout.xml | 3 +- .../view_table_quiz_radio_button_cell.xml | 17 +++- .../res/layout/view_table_quiz_text_cell.xml | 19 +++- 7 files changed, 129 insertions(+), 18 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index 3d88c29b62..ff3b93f460 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -1,17 +1,22 @@ package org.stepic.droid.ui.adapters; +import android.app.Activity; +import android.graphics.Point; import android.support.v7.widget.AppCompatCheckBox; import android.support.v7.widget.AppCompatRadioButton; import android.support.v7.widget.RecyclerView; +import android.view.Display; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import android.view.ViewTreeObserver; import android.widget.CompoundButton; -import android.widget.TextView; import org.jetbrains.annotations.NotNull; import org.stepic.droid.R; import org.stepic.droid.model.TableChoiceAnswer; +import org.stepic.droid.ui.custom.ProgressLatexView; import org.stepic.droid.ui.listeners.CheckedChangeListenerWithPosition; import java.util.ArrayList; @@ -34,6 +39,18 @@ public class TableChoiceAdapter extends RecyclerView.Adapter answers; + private final int deviceHeightPx; + private final int doublePadding; + private final int minUXTouchableSize; + + @Override + public void onAttachedToRecyclerView(RecyclerView recyclerView) { + super.onAttachedToRecyclerView(recyclerView); + RecyclerView.RecycledViewPool recycledViewPool = recyclerView.getRecycledViewPool(); +// recycledViewPool.setMaxRecycledViews(DESCRIPTION_TYPE, 100); +// recycledViewPool.setMaxRecycledViews(ROW_HEADER_TYPE, 100); +// recycledViewPool.setMaxRecycledViews(COLUMN_HEADER_TYPE, 100); + } @Override public int getItemViewType(int position) { @@ -50,13 +67,22 @@ public int getItemViewType(int position) { } } - public TableChoiceAdapter(List rows, List columns, String description, boolean isCheckbox, List answers) { + public TableChoiceAdapter(Activity context, List rows, List columns, String description, boolean isCheckbox, List answers) { this.columns = columns; this.rows = rows; this.description = description; this.isCheckbox = isCheckbox; this.answers = answers; int i = 0; + + Display display = context.getWindowManager().getDefaultDisplay(); + Point size = new Point(); + display.getSize(size); + deviceHeightPx = size.y; + + doublePadding = (int) context.getResources().getDimension(R.dimen.half_padding) * 2; + + minUXTouchableSize = (int) context.getResources().getDimension(R.dimen.min_ux_touchable_size); } @@ -70,7 +96,41 @@ public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new CheckboxCellViewHolder(v, this); } else if (viewType == DESCRIPTION_TYPE || viewType == ROW_HEADER_TYPE || viewType == COLUMN_HEADER_TYPE) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_table_quiz_text_cell, parent, false); - return new DescriptionViewHolder(v); + final DescriptionViewHolder optionViewHolder = new DescriptionViewHolder(v); + + + //for height: + optionViewHolder.container.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + int localHeight = optionViewHolder.textView.getMeasuredHeight() + doublePadding; +// Timber.d("localHeight = %s, of view = %s", localHeight, optionViewHolder.container); +// if (localHeight > doublePadding && localHeight < deviceHeightPx) { +// optionViewHolder.container.getLayoutParams().height = Math.max(localHeight, minUXTouchableSize); +// optionViewHolder.container.getViewTreeObserver().removeOnPreDrawListener(this); +// } + + return true; + } + }); +// + //for width + optionViewHolder.container.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + @Override + public boolean onPreDraw() { + int localWidth = optionViewHolder.textView.getMeasuredWidth() + doublePadding; +// Timber.d("localWidth = %s, of view = %s", localWidth, optionViewHolder.container); +// if (localWidth >= 394) { +// optionViewHolder.container.getLayoutParams().width = Math.max(localWidth, minUXTouchableSize); +// optionViewHolder.container.getViewTreeObserver().removeOnPreDrawListener(this); +// } + + return true; + } + }); + + + return optionViewHolder; } else { throw new IllegalStateException("viewType with index " + viewType + " is not supported in table quiz"); } @@ -164,8 +224,11 @@ public GenericViewHolder(View itemView) { static class DescriptionViewHolder extends GenericViewHolder { + @BindView(R.id.container) + View container; + @BindView(R.id.cell_text) - TextView textView; + ProgressLatexView textView; public DescriptionViewHolder(View itemView) { super(itemView); @@ -173,7 +236,7 @@ public DescriptionViewHolder(View itemView) { @Override public void setData(@NotNull String text) { - textView.setText(text); + textView.setAnyText(text); } @Override @@ -185,6 +248,10 @@ public void setData(@NotNull Boolean needCheck) { static abstract class CompoundButtonViewHolder extends GenericViewHolder { + + @BindView(R.id.container) + ViewGroup container; + public CompoundButtonViewHolder(View itemView, final CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { super(itemView); getCheckableView().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @@ -195,6 +262,15 @@ public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { } } }); + + container.setOnTouchListener(new View.OnTouchListener() { + @Override + public boolean onTouch(View v, MotionEvent event) { + return getCheckableView().dispatchTouchEvent(event); + } + }); + + } @Override diff --git a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java index 9a9085299e..ecd473dae6 100644 --- a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java +++ b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java @@ -122,6 +122,10 @@ public void writeToParcel(Parcel dest, int flags) { } + public int getMeasuredWidthOfInnerLayout() { + return optionText.getMeasuredWidth(); + } + public int getMeasuredHeightOfInnerLayout() { return optionText.getMeasuredHeight(); } diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java b/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java index b33432f822..5b04b1d22c 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java +++ b/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java @@ -49,6 +49,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { attemptContainer.setPadding(0, dp8inPx, 0, dp8inPx); recyclerContainer = ButterKnife.findById(tableQuizView, R.id.recycler); recyclerContainer.setNestedScrollingEnabled(false); +// recyclerContainer.addItemDecoration(new SimpleDividerItemDecoration(getContext())); attemptContainer.addView(tableQuizView); } @@ -63,7 +64,7 @@ protected void showAttempt(Attempt attempt) { answerList = initAnswerListFromAttempt(rows, columns); gridLayoutManager = new GridLayoutManager(getContext(), rows.size() + 1, GridLayoutManager.HORIZONTAL, false); - adapter = new TableChoiceAdapter(rows, columns, description, isCheckbox, answerList); + adapter = new TableChoiceAdapter(getActivity(), rows, columns, description, isCheckbox, answerList); recyclerContainer.setLayoutManager(gridLayoutManager); recyclerContainer.setAdapter(adapter); } diff --git a/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml b/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml index db2393cad0..193d0daa7c 100644 --- a/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml +++ b/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml @@ -1,9 +1,18 @@ - - \ No newline at end of file + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_table_quiz_layout.xml b/app/src/main/res/layout/view_table_quiz_layout.xml index 45f86ac7ef..f4711b4406 100644 --- a/app/src/main/res/layout/view_table_quiz_layout.xml +++ b/app/src/main/res/layout/view_table_quiz_layout.xml @@ -1,8 +1,9 @@ - - \ No newline at end of file + android:layout_height="wrap_content" + android:background="@color/stepic_orange_carrot" + android:minHeight="@dimen/min_ux_touchable_size" + android:minWidth="@dimen/min_ux_touchable_size"> + + + \ No newline at end of file diff --git a/app/src/main/res/layout/view_table_quiz_text_cell.xml b/app/src/main/res/layout/view_table_quiz_text_cell.xml index 8bfd46a66c..6eb1e18a32 100644 --- a/app/src/main/res/layout/view_table_quiz_text_cell.xml +++ b/app/src/main/res/layout/view_table_quiz_text_cell.xml @@ -1,8 +1,19 @@ - + android:layout_height="wrap_content" + android:background="@color/stepic_orange_carrot" + android:minHeight="@dimen/min_ux_touchable_size"> - \ No newline at end of file + + + + + \ No newline at end of file From 190642d11e8bb3db528fab798012fff25ae8ecec Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Thu, 2 Feb 2017 20:18:56 +0300 Subject: [PATCH 09/38] ok, but lagged latex --- .../droid/ui/adapters/TableChoiceAdapter.java | 32 +++++-------------- .../droid/ui/custom/ProgressLatexView.java | 4 +++ 2 files changed, 12 insertions(+), 24 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index ff3b93f460..089e047046 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -24,6 +24,7 @@ import butterknife.BindView; import butterknife.ButterKnife; +import timber.log.Timber; public class TableChoiceAdapter extends RecyclerView.Adapter implements CheckedChangeListenerWithPosition { @@ -42,6 +43,7 @@ public class TableChoiceAdapter extends RecyclerView.Adapter rows, List colu doublePadding = (int) context.getResources().getDimension(R.dimen.half_padding) * 2; + singlePadding = (int) context.getResources().getDimension(R.dimen.half_padding); + minUXTouchableSize = (int) context.getResources().getDimension(R.dimen.min_ux_touchable_size); } @@ -99,37 +103,17 @@ public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final DescriptionViewHolder optionViewHolder = new DescriptionViewHolder(v); - //for height: - optionViewHolder.container.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - int localHeight = optionViewHolder.textView.getMeasuredHeight() + doublePadding; -// Timber.d("localHeight = %s, of view = %s", localHeight, optionViewHolder.container); -// if (localHeight > doublePadding && localHeight < deviceHeightPx) { -// optionViewHolder.container.getLayoutParams().height = Math.max(localHeight, minUXTouchableSize); -// optionViewHolder.container.getViewTreeObserver().removeOnPreDrawListener(this); -// } - - return true; - } - }); -// - //for width +// for height: optionViewHolder.container.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - int localWidth = optionViewHolder.textView.getMeasuredWidth() + doublePadding; -// Timber.d("localWidth = %s, of view = %s", localWidth, optionViewHolder.container); -// if (localWidth >= 394) { -// optionViewHolder.container.getLayoutParams().width = Math.max(localWidth, minUXTouchableSize); -// optionViewHolder.container.getViewTreeObserver().removeOnPreDrawListener(this); -// } - + int localHeight = optionViewHolder.textView.getMeasuredHeightOfInnerLayout(); + int localWidth = optionViewHolder.textView.getMeasuredWidthOfInnerLayout(); + Timber.d("localHeight = %s, localWidth = %s, text on view = %s", localHeight, localWidth, optionViewHolder.textView.getBeforeText()); return true; } }); - return optionViewHolder; } else { throw new IllegalStateException("viewType with index " + viewType + " is not supported in table quiz"); diff --git a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java index ecd473dae6..c2f9b25731 100644 --- a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java +++ b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java @@ -130,4 +130,8 @@ public int getMeasuredHeightOfInnerLayout() { return optionText.getMeasuredHeight(); } + public String getBeforeText() { + return beforeText; + } + } From 2f92e03a71c7ddc1445da952eed94a44ef171a9f Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 3 Feb 2017 11:18:37 +0300 Subject: [PATCH 10/38] latex container is not jump out of the cell --- .../droid/ui/adapters/TableChoiceAdapter.java | 15 +++++++++++++-- .../stepic/droid/ui/custom/ProgressLatexView.java | 11 +++++++++++ .../main/res/layout/view_table_quiz_text_cell.xml | 6 ++---- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index 089e047046..6424ab0cb9 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -105,11 +105,22 @@ public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { // for height: optionViewHolder.container.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + int useOnlyIt = 0; @Override public boolean onPreDraw() { +// if (useOnlyIt>0){ +// optionViewHolder.container.getLayoutParams().height = useOnlyIt; +// return true; +// } + int localHeight = optionViewHolder.textView.getMeasuredHeightOfInnerLayout(); - int localWidth = optionViewHolder.textView.getMeasuredWidthOfInnerLayout(); - Timber.d("localHeight = %s, localWidth = %s, text on view = %s", localHeight, localWidth, optionViewHolder.textView.getBeforeText()); +// int localWidth = optionViewHolder.textView.getMeasuredWidthOfInnerLayout(); + Timber.d("localHeight = %s, localWidth = %s, text on view = %s", localHeight, 1, optionViewHolder.textView.getBeforeText()); + if (localHeight > 0 && localHeight < deviceHeightPx) { + useOnlyIt = Math.max(localHeight, minUXTouchableSize); + optionViewHolder.container.getLayoutParams().height = useOnlyIt; + optionViewHolder.container.getViewTreeObserver().removeOnPreDrawListener(this); + } return true; } }); diff --git a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java index c2f9b25731..91578dcb5e 100644 --- a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java +++ b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java @@ -13,6 +13,9 @@ import android.widget.ProgressBar; import org.stepic.droid.R; +import org.stepic.droid.util.ColorUtil; + +import timber.log.Timber; public class ProgressLatexView extends FrameLayout { @@ -54,6 +57,8 @@ public void onPageFinished(WebView view, String url) { } }; optionText.getWebView().setWebViewClient(client); + + optionText.setBackgroundColor(ColorUtil.INSTANCE.getColorArgb(R.color.stepic_blue_ribbon, context)); } public void setPlainOrLaTeXText(String text) { @@ -130,6 +135,12 @@ public int getMeasuredHeightOfInnerLayout() { return optionText.getMeasuredHeight(); } + public int getHeightOfInnerLayout() { + int height = optionText.getHeight(); + Timber.d("height of latexframe layout is %s", height); + return height; + } + public String getBeforeText() { return beforeText; } diff --git a/app/src/main/res/layout/view_table_quiz_text_cell.xml b/app/src/main/res/layout/view_table_quiz_text_cell.xml index 6eb1e18a32..0e8a2f7fc3 100644 --- a/app/src/main/res/layout/view_table_quiz_text_cell.xml +++ b/app/src/main/res/layout/view_table_quiz_text_cell.xml @@ -4,16 +4,14 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:background="@color/stepic_orange_carrot" - android:minHeight="@dimen/min_ux_touchable_size"> + android:background="@color/stepic_orange_carrot"> + android:padding="@dimen/half_padding"> \ No newline at end of file From d6c000fc34c8895562e30a41687df00882349a08 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 3 Feb 2017 20:01:47 +0300 Subject: [PATCH 11/38] make LaTeX table with fix row height (it is good for much cases, but is not working on long formulas). Tag Beta is needed --- .../droid/ui/adapters/TableChoiceAdapter.java | 34 +++++++------------ .../layout/view_table_quiz_checkbox_cell.xml | 7 ++-- .../res/layout/view_table_quiz_layout.xml | 4 +-- .../view_table_quiz_radio_button_cell.xml | 3 +- .../res/layout/view_table_quiz_text_cell.xml | 20 ++++------- app/src/main/res/values/dimens.xml | 2 ++ 6 files changed, 25 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index 6424ab0cb9..563bf8663d 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -24,7 +24,6 @@ import butterknife.BindView; import butterknife.ButterKnife; -import timber.log.Timber; public class TableChoiceAdapter extends RecyclerView.Adapter implements CheckedChangeListenerWithPosition { @@ -40,10 +39,11 @@ public class TableChoiceAdapter extends RecyclerView.Adapter answers; - private final int deviceHeightPx; + // private final int deviceHeightPx; private final int doublePadding; private final int minUXTouchableSize; private final int singlePadding; + private final int deviceWidthPx75Percent; @Override public void onAttachedToRecyclerView(RecyclerView recyclerView) { @@ -80,7 +80,7 @@ public TableChoiceAdapter(Activity context, List rows, List colu Display display = context.getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); - deviceHeightPx = size.y; + deviceWidthPx75Percent = (int) (size.x * 0.75); doublePadding = (int) context.getResources().getDimension(R.dimen.half_padding) * 2; @@ -103,23 +103,13 @@ public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { final DescriptionViewHolder optionViewHolder = new DescriptionViewHolder(v); -// for height: - optionViewHolder.container.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - int useOnlyIt = 0; + optionViewHolder.latexView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { -// if (useOnlyIt>0){ -// optionViewHolder.container.getLayoutParams().height = useOnlyIt; -// return true; -// } - - int localHeight = optionViewHolder.textView.getMeasuredHeightOfInnerLayout(); -// int localWidth = optionViewHolder.textView.getMeasuredWidthOfInnerLayout(); - Timber.d("localHeight = %s, localWidth = %s, text on view = %s", localHeight, 1, optionViewHolder.textView.getBeforeText()); - if (localHeight > 0 && localHeight < deviceHeightPx) { - useOnlyIt = Math.max(localHeight, minUXTouchableSize); - optionViewHolder.container.getLayoutParams().height = useOnlyIt; - optionViewHolder.container.getViewTreeObserver().removeOnPreDrawListener(this); + int localWidth = optionViewHolder.latexView.getMeasuredWidthOfInnerLayout() + doublePadding; + if (localWidth > deviceWidthPx75Percent) { + optionViewHolder.latexView.getLayoutParams().width = Math.min(Math.max(localWidth, minUXTouchableSize), deviceWidthPx75Percent); + optionViewHolder.latexView.getViewTreeObserver().removeOnPreDrawListener(this); } return true; } @@ -219,11 +209,11 @@ public GenericViewHolder(View itemView) { static class DescriptionViewHolder extends GenericViewHolder { - @BindView(R.id.container) - View container; +// @BindView(R.id.container) +// View container; @BindView(R.id.cell_text) - ProgressLatexView textView; + ProgressLatexView latexView; public DescriptionViewHolder(View itemView) { super(itemView); @@ -231,7 +221,7 @@ public DescriptionViewHolder(View itemView) { @Override public void setData(@NotNull String text) { - textView.setAnyText(text); + latexView.setAnyText(text); } @Override diff --git a/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml b/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml index 193d0daa7c..19733fbbee 100644 --- a/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml +++ b/app/src/main/res/layout/view_table_quiz_checkbox_cell.xml @@ -3,16 +3,13 @@ android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" - android:layout_height="wrap_content" - android:descendantFocusability="afterDescendants" + android:layout_height="@dimen/table_cell_fixed_height" android:background="@color/stepic_orange_carrot" - android:minHeight="@dimen/min_ux_touchable_size" android:minWidth="@dimen/min_ux_touchable_size"> + android:layout_gravity="center"> \ No newline at end of file diff --git a/app/src/main/res/layout/view_table_quiz_layout.xml b/app/src/main/res/layout/view_table_quiz_layout.xml index f4711b4406..943eb468b1 100644 --- a/app/src/main/res/layout/view_table_quiz_layout.xml +++ b/app/src/main/res/layout/view_table_quiz_layout.xml @@ -1,10 +1,10 @@ \ No newline at end of file diff --git a/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml b/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml index bd3db129b9..d20cd75efd 100644 --- a/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml +++ b/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml @@ -3,9 +3,8 @@ android:id="@+id/container" xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" - android:layout_height="wrap_content" + android:layout_height="@dimen/table_cell_fixed_height" android:background="@color/stepic_orange_carrot" - android:minHeight="@dimen/min_ux_touchable_size" android:minWidth="@dimen/min_ux_touchable_size"> - - - - - - - \ No newline at end of file + android:layout_height="@dimen/table_cell_fixed_height" + android:background="@color/stepic_orange_carrot" + android:padding="@dimen/half_padding"> + \ No newline at end of file diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml index 97f802735e..0279391b23 100644 --- a/app/src/main/res/values/dimens.xml +++ b/app/src/main/res/values/dimens.xml @@ -71,4 +71,6 @@ 16sp 24dp 12dp + 96dp + From dc51e4e325deb958cd68f9952cc0e98559147bce Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 3 Feb 2017 20:41:33 +0300 Subject: [PATCH 12/38] clean up code of table quiz --- .../droid/ui/adapters/TableChoiceAdapter.java | 40 +++++-------------- .../droid/ui/custom/ProgressLatexView.java | 15 ------- 2 files changed, 11 insertions(+), 44 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index 563bf8663d..f9b0372b66 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -39,21 +39,10 @@ public class TableChoiceAdapter extends RecyclerView.Adapter answers; - // private final int deviceHeightPx; private final int doublePadding; private final int minUXTouchableSize; - private final int singlePadding; private final int deviceWidthPx75Percent; - @Override - public void onAttachedToRecyclerView(RecyclerView recyclerView) { - super.onAttachedToRecyclerView(recyclerView); - RecyclerView.RecycledViewPool recycledViewPool = recyclerView.getRecycledViewPool(); -// recycledViewPool.setMaxRecycledViews(DESCRIPTION_TYPE, 100); -// recycledViewPool.setMaxRecycledViews(ROW_HEADER_TYPE, 100); -// recycledViewPool.setMaxRecycledViews(COLUMN_HEADER_TYPE, 100); - } - @Override public int getItemViewType(int position) { if (position == 0) { @@ -75,7 +64,6 @@ public TableChoiceAdapter(Activity context, List rows, List colu this.description = description; this.isCheckbox = isCheckbox; this.answers = answers; - int i = 0; Display display = context.getWindowManager().getDefaultDisplay(); Point size = new Point(); @@ -84,8 +72,6 @@ public TableChoiceAdapter(Activity context, List rows, List colu doublePadding = (int) context.getResources().getDimension(R.dimen.half_padding) * 2; - singlePadding = (int) context.getResources().getDimension(R.dimen.half_padding); - minUXTouchableSize = (int) context.getResources().getDimension(R.dimen.min_ux_touchable_size); } @@ -100,22 +86,21 @@ public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new CheckboxCellViewHolder(v, this); } else if (viewType == DESCRIPTION_TYPE || viewType == ROW_HEADER_TYPE || viewType == COLUMN_HEADER_TYPE) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_table_quiz_text_cell, parent, false); - final DescriptionViewHolder optionViewHolder = new DescriptionViewHolder(v); - + final DescriptionViewHolder descriptionViewHolder = new DescriptionViewHolder(v); - optionViewHolder.latexView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { + descriptionViewHolder.latexView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { @Override public boolean onPreDraw() { - int localWidth = optionViewHolder.latexView.getMeasuredWidthOfInnerLayout() + doublePadding; + int localWidth = descriptionViewHolder.latexView.getMeasuredWidthOfInnerLayout() + doublePadding; if (localWidth > deviceWidthPx75Percent) { - optionViewHolder.latexView.getLayoutParams().width = Math.min(Math.max(localWidth, minUXTouchableSize), deviceWidthPx75Percent); - optionViewHolder.latexView.getViewTreeObserver().removeOnPreDrawListener(this); + descriptionViewHolder.latexView.getLayoutParams().width = Math.min(Math.max(localWidth, minUXTouchableSize), deviceWidthPx75Percent); + descriptionViewHolder.latexView.getViewTreeObserver().removeOnPreDrawListener(this); } return true; } }); - return optionViewHolder; + return descriptionViewHolder; } else { throw new IllegalStateException("viewType with index " + viewType + " is not supported in table quiz"); } @@ -196,7 +181,7 @@ public void onCheckedChanged(CompoundButton view, boolean isChecked, int positio static abstract class GenericViewHolder extends RecyclerView.ViewHolder { - public GenericViewHolder(View itemView) { + GenericViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); } @@ -209,13 +194,10 @@ public GenericViewHolder(View itemView) { static class DescriptionViewHolder extends GenericViewHolder { -// @BindView(R.id.container) -// View container; - @BindView(R.id.cell_text) ProgressLatexView latexView; - public DescriptionViewHolder(View itemView) { + DescriptionViewHolder(View itemView) { super(itemView); } @@ -237,7 +219,7 @@ static abstract class CompoundButtonViewHolder extends GenericViewHolder { @BindView(R.id.container) ViewGroup container; - public CompoundButtonViewHolder(View itemView, final CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { + CompoundButtonViewHolder(View itemView, final CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { super(itemView); getCheckableView().setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { @Override @@ -276,7 +258,7 @@ static class CheckboxCellViewHolder extends CompoundButtonViewHolder { @BindView(R.id.checkbox_cell) AppCompatCheckBox checkBox; - public CheckboxCellViewHolder(View itemView, CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { + CheckboxCellViewHolder(View itemView, CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { super(itemView, checkedChangeListenerWithPosition); } @@ -291,7 +273,7 @@ static class RadioButtonCellViewHolder extends CompoundButtonViewHolder { @BindView(R.id.radio_button_cell) AppCompatRadioButton radioButton; - public RadioButtonCellViewHolder(View itemView, final CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { + RadioButtonCellViewHolder(View itemView, final CheckedChangeListenerWithPosition checkedChangeListenerWithPosition) { super(itemView, checkedChangeListenerWithPosition); } diff --git a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java index 91578dcb5e..ecd473dae6 100644 --- a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java +++ b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java @@ -13,9 +13,6 @@ import android.widget.ProgressBar; import org.stepic.droid.R; -import org.stepic.droid.util.ColorUtil; - -import timber.log.Timber; public class ProgressLatexView extends FrameLayout { @@ -57,8 +54,6 @@ public void onPageFinished(WebView view, String url) { } }; optionText.getWebView().setWebViewClient(client); - - optionText.setBackgroundColor(ColorUtil.INSTANCE.getColorArgb(R.color.stepic_blue_ribbon, context)); } public void setPlainOrLaTeXText(String text) { @@ -135,14 +130,4 @@ public int getMeasuredHeightOfInnerLayout() { return optionText.getMeasuredHeight(); } - public int getHeightOfInnerLayout() { - int height = optionText.getHeight(); - Timber.d("height of latexframe layout is %s", height); - return height; - } - - public String getBeforeText() { - return beforeText; - } - } From a0ae61b6b0a8c51ac1fa0d9aa44999d6e01d7332 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 3 Feb 2017 21:36:22 +0300 Subject: [PATCH 13/38] block ui after submit an unblock on retry for table quiz --- .../droid/ui/adapters/TableChoiceAdapter.java | 24 +++++++++++++++++++ .../ui/fragments/TableChoiceStepFragment.java | 6 +++-- .../layout/view_table_quiz_checkbox_cell.xml | 1 - .../res/layout/view_table_quiz_layout.xml | 1 - .../view_table_quiz_radio_button_cell.xml | 1 - 5 files changed, 28 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index f9b0372b66..2a40d39304 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -42,6 +42,7 @@ public class TableChoiceAdapter extends RecyclerView.Adapter \ No newline at end of file diff --git a/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml b/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml index d20cd75efd..aae2c102e1 100644 --- a/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml +++ b/app/src/main/res/layout/view_table_quiz_radio_button_cell.xml @@ -4,7 +4,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="@dimen/table_cell_fixed_height" - android:background="@color/stepic_orange_carrot" android:minWidth="@dimen/min_ux_touchable_size"> Date: Fri, 3 Feb 2017 22:01:48 +0300 Subject: [PATCH 14/38] fix bug in blocking (wrong update range) --- .../java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index 2a40d39304..96ecd2db08 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -185,7 +185,7 @@ public void setAllItemsEnabled(boolean isAllEnabled) { this.isAllEnabled = isAllEnabled; int i = rows.size() + 2; // the first option cell element while (i < getItemCount()) { - notifyItemRangeChanged(i, i + rows.size() - 1); + notifyItemRangeChanged(i, rows.size()); i += rows.size() + 1; } } From 1a529765df9c50291e25017f29b4b651316f9e1b Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 3 Feb 2017 22:04:33 +0300 Subject: [PATCH 15/38] add decorator for table quiz (lines between cells) --- .../stepic/droid/ui/fragments/TableChoiceStepFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java b/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java index af229ef085..fab571a273 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java +++ b/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java @@ -19,6 +19,7 @@ import org.stepic.droid.model.Reply; import org.stepic.droid.model.TableChoiceAnswer; import org.stepic.droid.ui.adapters.TableChoiceAdapter; +import org.stepic.droid.ui.util.SimpleDividerItemDecoration; import org.stepic.droid.util.DpPixelsHelper; import java.util.ArrayList; @@ -40,7 +41,6 @@ public static TableChoiceStepFragment newInstance() { TableChoiceAdapter adapter; - @Override public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); @@ -49,7 +49,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { attemptContainer.setPadding(0, dp8inPx, 0, dp8inPx); recyclerContainer = ButterKnife.findById(tableQuizView, R.id.recycler); recyclerContainer.setNestedScrollingEnabled(false); -// recyclerContainer.addItemDecoration(new SimpleDividerItemDecoration(getContext())); + recyclerContainer.addItemDecoration(new SimpleDividerItemDecoration(getContext())); attemptContainer.addView(tableQuizView); } From 05886883a9d1667613aa1ac061e1e2d7944187c2 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Thu, 9 Feb 2017 13:51:30 +0300 Subject: [PATCH 16/38] add color to text cells at table quiz --- app/src/main/res/layout/view_table_quiz_text_cell.xml | 2 +- app/src/main/res/values/colors.xml | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/res/layout/view_table_quiz_text_cell.xml b/app/src/main/res/layout/view_table_quiz_text_cell.xml index fdf86e174b..d4ac453f86 100644 --- a/app/src/main/res/layout/view_table_quiz_text_cell.xml +++ b/app/src/main/res/layout/view_table_quiz_text_cell.xml @@ -4,6 +4,6 @@ xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="wrap_content" android:layout_height="@dimen/table_cell_fixed_height" - android:background="@color/stepic_orange_carrot" + android:background="@color/table_header" android:padding="@dimen/half_padding"> \ No newline at end of file diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index fbf12fa53e..92e096e5d9 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -15,6 +15,7 @@ @color/white #eeeeee #EDEDED + #80F0F0F0 #66CC66 From 2d1c6a6c94a8e38ac9004fd5d134936154c7856b Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Thu, 9 Feb 2017 14:10:39 +0300 Subject: [PATCH 17/38] make divider for table choice greater --- .../decorators/GridDividerItemDecoration.java | 46 +++++++++++++++++++ .../ui/fragments/TableChoiceStepFragment.java | 4 +- 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/org/stepic/droid/ui/decorators/GridDividerItemDecoration.java diff --git a/app/src/main/java/org/stepic/droid/ui/decorators/GridDividerItemDecoration.java b/app/src/main/java/org/stepic/droid/ui/decorators/GridDividerItemDecoration.java new file mode 100644 index 0000000000..29ec44dd02 --- /dev/null +++ b/app/src/main/java/org/stepic/droid/ui/decorators/GridDividerItemDecoration.java @@ -0,0 +1,46 @@ +package org.stepic.droid.ui.decorators; + + +import android.content.Context; +import android.graphics.Canvas; +import android.graphics.drawable.Drawable; +import android.support.v4.content.ContextCompat; +import android.support.v7.widget.RecyclerView; +import android.view.View; + +import org.stepic.droid.R; + +public class GridDividerItemDecoration extends RecyclerView.ItemDecoration { + private Drawable horizontalDivider; + private Drawable verticalDivider; + + public GridDividerItemDecoration(Context context) { + horizontalDivider = ContextCompat.getDrawable(context, R.drawable.list_divider_h); + verticalDivider = ContextCompat.getDrawable(context, R.drawable.list_divider_w); + } + + @Override + public void onDrawOver(Canvas c, RecyclerView parent, RecyclerView.State state) { + + int childCount = parent.getChildCount(); + for (int i = 0; i < childCount; i++) { + View child = parent.getChildAt(i); + + RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams(); + + int bottom = child.getBottom() + params.bottomMargin; + int top = bottom - horizontalDivider.getIntrinsicHeight(); + int left = child.getLeft(); + int right = child.getRight(); + + horizontalDivider.setBounds(left, top, right, bottom); + horizontalDivider.draw(c); + + int leftVertical = Math.max(0, right - verticalDivider.getIntrinsicWidth()); + int topVertical = child.getTop(); + + verticalDivider.setBounds(leftVertical, topVertical, right, bottom); + verticalDivider.draw(c); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java b/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java index fab571a273..f528635b7a 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java +++ b/app/src/main/java/org/stepic/droid/ui/fragments/TableChoiceStepFragment.java @@ -19,7 +19,7 @@ import org.stepic.droid.model.Reply; import org.stepic.droid.model.TableChoiceAnswer; import org.stepic.droid.ui.adapters.TableChoiceAdapter; -import org.stepic.droid.ui.util.SimpleDividerItemDecoration; +import org.stepic.droid.ui.decorators.GridDividerItemDecoration; import org.stepic.droid.util.DpPixelsHelper; import java.util.ArrayList; @@ -49,7 +49,7 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { attemptContainer.setPadding(0, dp8inPx, 0, dp8inPx); recyclerContainer = ButterKnife.findById(tableQuizView, R.id.recycler); recyclerContainer.setNestedScrollingEnabled(false); - recyclerContainer.addItemDecoration(new SimpleDividerItemDecoration(getContext())); + recyclerContainer.addItemDecoration(new GridDividerItemDecoration(getContext())); attemptContainer.addView(tableQuizView); } From b2877d97ff907c7b515f936f65183ca79f9735e4 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Thu, 9 Feb 2017 14:46:26 +0300 Subject: [PATCH 18/38] make colorized rows (even and odd) --- .../droid/ui/adapters/TableChoiceAdapter.java | 44 +++++++++++++++++-- app/src/main/res/values/colors.xml | 3 +- 2 files changed, 42 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index 96ecd2db08..15911ffe36 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -2,6 +2,7 @@ import android.app.Activity; import android.graphics.Point; +import android.support.annotation.ColorInt; import android.support.v7.widget.AppCompatCheckBox; import android.support.v7.widget.AppCompatRadioButton; import android.support.v7.widget.RecyclerView; @@ -22,6 +23,7 @@ import java.util.ArrayList; import java.util.List; +import butterknife.BindColor; import butterknife.BindView; import butterknife.ButterKnife; @@ -112,18 +114,22 @@ public void onBindViewHolder(GenericViewHolder holder, int position) { int itemViewType = getItemViewType(position); if (itemViewType == DESCRIPTION_TYPE) { holder.setData(description); + // Description is always default (not even or odd) } else if (itemViewType == ROW_HEADER_TYPE) { String headerText = rows.get(position - 1); holder.setData(headerText); + holder.fillAsEven(isPositionEven(position)); } else if (itemViewType == COLUMN_HEADER_TYPE) { int columnPosition = getColumnPosition(position); // -1 is description cell at top left cell String headerText = columns.get(columnPosition); holder.setData(headerText); + //Column header is always default. (not even or odd) } else { List oneRowAnswers = getOneRowAnswersFromPosition(position); int columnPosition = getColumnPosition(position); TableChoiceAnswer.Companion.Cell cell = oneRowAnswers.get(columnPosition); holder.setData(cell.getAnswer()); + holder.fillAsEven(isPositionEven(position)); } holder.makeEnabled(isAllEnabled); } @@ -143,7 +149,6 @@ public int getItemCount() { return rows.size() + columns.size() + 1 + rows.size() * columns.size(); //1 – description top left cell. } - @Override public void onCheckedChanged(CompoundButton view, boolean isChecked, int position) { List oneRowAnswers = getOneRowAnswersFromPosition(position); @@ -190,8 +195,30 @@ public void setAllItemsEnabled(boolean isAllEnabled) { } } + /** + * 0 is header row (even) + * 1 is the next row (odd) + * 2 is the next (even) + * etc + * + * @param position of the element + * @return true if position exists in even row, false otherwise + */ + private boolean isPositionEven(int position) { + int rowPosition = position % (rows.size() + 1); + return rowPosition % 2 == 0; + } + static abstract class GenericViewHolder extends RecyclerView.ViewHolder { + @ColorInt + @BindColor(R.color.table_even_row) + protected int backgroundColorForEven; + + @ColorInt + @BindColor(R.color.white) + protected int backgroundColorForNotEven; + GenericViewHolder(View itemView) { super(itemView); ButterKnife.bind(this, itemView); @@ -202,6 +229,8 @@ static abstract class GenericViewHolder extends RecyclerView.ViewHolder { public abstract void setData(@NotNull Boolean needCheckModel); public abstract void makeEnabled(boolean isAllEnabled); + + public abstract void fillAsEven(boolean positionEven); } @@ -229,6 +258,11 @@ public void makeEnabled(boolean isAllEnabled) { //do nothing, it is not interactable by user } + @Override + public void fillAsEven(boolean positionEven) { + latexView.setBackgroundColor(positionEven ? backgroundColorForEven : backgroundColorForNotEven); + } + } @@ -254,8 +288,6 @@ public boolean onTouch(View v, MotionEvent event) { return getCheckableView().dispatchTouchEvent(event); } }); - - } @Override @@ -274,6 +306,11 @@ public void makeEnabled(boolean isEnabled) { getCheckableView().setClickable(isEnabled); } + @Override + public void fillAsEven(boolean positionEven) { + container.setBackgroundColor(positionEven ? backgroundColorForEven : backgroundColorForNotEven); + } + abstract CompoundButton getCheckableView(); } @@ -307,4 +344,3 @@ CompoundButton getCheckableView() { } } } - diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 92e096e5d9..851b0ec7c7 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -15,7 +15,8 @@ @color/white #eeeeee #EDEDED - #80F0F0F0 + #F0F0F0 + #F6F9FC #66CC66 From b3b68c0bb3bfe9393c6074d2a0eb60127ae45105 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Thu, 9 Feb 2017 15:11:05 +0300 Subject: [PATCH 19/38] add beta label for table quiz --- .../res/layout/view_table_quiz_layout.xml | 23 ++++++++++++++----- app/src/main/res/values-ru/strings.xml | 1 + app/src/main/res/values/strings.xml | 1 + 3 files changed, 19 insertions(+), 6 deletions(-) diff --git a/app/src/main/res/layout/view_table_quiz_layout.xml b/app/src/main/res/layout/view_table_quiz_layout.xml index 45f86ac7ef..46c06de155 100644 --- a/app/src/main/res/layout/view_table_quiz_layout.xml +++ b/app/src/main/res/layout/view_table_quiz_layout.xml @@ -1,9 +1,20 @@ - \ No newline at end of file + android:layout_height="wrap_content" + android:orientation="vertical"> + + + + \ No newline at end of file diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index 1d63b6242a..da6108e7c6 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -341,4 +341,5 @@ Нажать и перетащить ]]> Введите текст + Табличная задача β \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 41f5664ea0..dcec2d256d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -340,4 +340,5 @@ drag and drop ]]> Type text + Table problem β From d0d880050ec48b243884b27c04a7f4fb40c137e5 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 10 Feb 2017 15:57:10 +0300 Subject: [PATCH 20/38] add commented return statement for determining of refreshing token (debug purpose) --- app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java | 1 + 1 file changed, 1 insertion(+) diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index d2ccb1b96d..52291acf36 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -749,6 +749,7 @@ private String getAuthHeaderValueForLogged() { private boolean isNeededUpdate(AuthenticationStepicResponse response) { if (response == null) return false; +// return true; long timestampStored = sharedPreference.getAccessTokenTimestamp(); if (timestampStored == -1) return true; From 6bd72c7d03d2a49f8760a956475ea9261bd1661d Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 10 Feb 2017 17:15:20 +0300 Subject: [PATCH 21/38] disable transition from launch to main screen with Back button --- .../ui/activities/LaunchActivity.java | 4 +--- .../stepic/droid/core/ScreenManagerImpl.java | 4 ++-- .../org/stepic/droid/util/AppConstants.java | 2 ++ app/src/sb/AndroidManifest.xml | Bin 1348 -> 1304 bytes app/src/sb/assets/configs/config.json | Bin 1097 -> 1315 bytes .../droid/ui/activities/LaunchActivity.java | Bin 2755 -> 2917 bytes 6 files changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/classic/java/org.stepic.droid/ui/activities/LaunchActivity.java b/app/src/classic/java/org.stepic.droid/ui/activities/LaunchActivity.java index 398c77e695..cc425bf07d 100644 --- a/app/src/classic/java/org.stepic.droid/ui/activities/LaunchActivity.java +++ b/app/src/classic/java/org.stepic.droid/ui/activities/LaunchActivity.java @@ -53,8 +53,6 @@ public class LaunchActivity extends BackToExitActivityBase { - public final static String FROM_MAIN_FEED_FLAG = "from_main_feed"; - @BindView(R.id.sign_up_btn_activity_launch) View signUpButton; @@ -328,7 +326,7 @@ public void onBackPressed() { boolean fromMainFeed; int index = 0; try { - fromMainFeed = getIntent().getExtras().getBoolean(FROM_MAIN_FEED_FLAG); + fromMainFeed = getIntent().getExtras().getBoolean(AppConstants.FROM_MAIN_FEED_FLAG); index = getIntent().getExtras().getInt(MainFeedActivity.KEY_CURRENT_INDEX); } catch (Exception ex) { fromMainFeed = false; diff --git a/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java b/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java index 7e47beff8d..d6ad25d946 100644 --- a/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java +++ b/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java @@ -108,10 +108,10 @@ public void showLaunchScreen(Activity activity, boolean fromMainFeed, int index) analytic.reportEvent(Analytic.Screens.SHOW_LAUNCH); Intent launchIntent = new Intent(activity, LaunchActivity.class); if (fromMainFeed) { - launchIntent.putExtra(LaunchActivity.FROM_MAIN_FEED_FLAG, true); + launchIntent.putExtra(AppConstants.FROM_MAIN_FEED_FLAG, true); launchIntent.putExtra(MainFeedActivity.KEY_CURRENT_INDEX, index); } - launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK); + launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); activity.startActivity(launchIntent); } diff --git a/app/src/main/java/org/stepic/droid/util/AppConstants.java b/app/src/main/java/org/stepic/droid/util/AppConstants.java index 677a7b13d8..56896f209b 100644 --- a/app/src/main/java/org/stepic/droid/util/AppConstants.java +++ b/app/src/main/java/org/stepic/droid/util/AppConstants.java @@ -97,4 +97,6 @@ public class AppConstants { public static final String cookieHeaderName = "Cookie"; public static final String refererHeaderName = "Referer"; public static final String csrfTokenHeaderName = "X-CSRFToken"; + + public final static String FROM_MAIN_FEED_FLAG = "from_main_feed"; } diff --git a/app/src/sb/AndroidManifest.xml b/app/src/sb/AndroidManifest.xml index e75321341f8c4a5b7bcbea074e97e2f8c38fa738..0fcb8808d0b06c264326bd74395e586bd88659bf 100644 GIT binary patch literal 1304 zcmV+z1?TzzM@dveQdv+`0P7!zrn`!5MNS?#z!uh>($Y~TB~LCV3|+e0Wi|(4qO38A zpi`L3=>sUya39Bf8_nUuXYk4jwCPX;%e!S$YVHP(!6l?Y1ptZYrOMd1w(9eF!FT7* zNXY-u`-0iJ&*!@IEiTblc5RPAqIg_U4X;SqH7LTp)2W2(Y!s6;@HW&RBmizSPkvF5 zD`EzW0_+-R!5(<8-w>7IcyHoIV3FE?74Y7Bleu5c1jRY+&GOdsMdXa?eF1+LAeAYL z%VFJ={%^=*FdlV-K3u28kwVk4SLl@SC0zKD>zAli%dQHn9!YrGe0Nc0{wS za-8+TVc~r&af5erd69&Mbya|bwJ{_vwPAS+h+>**IILcj1$`+gF}filz2#NHa4`cNj!p_Gn`rV3gE8k7^?665Q>ihMg7<4^LOCr8Qj|SRY1)Vz8h_VGeo~NCu=7cQW%5 z%7Z8VE6D}%|BFIGA25#XQgzGc22cIm8UIcY}T#DNJ`4_JSBpzhqX9U}hG&!Xbwt+Pg~Zpb-m zJ?L9ioCA}l`Vr^5K-$SDUl#{DM`CeLMu5Tp(Agar12Q~P!~`PGy?_%Oc?qr()B*Uq zU(ebZlXsXOTc4ggsVtM)wzm-J%CqM&*@W9qGN^ZuP$s^!)7*aPFLd?$2zc{({}vi$ z-56S@AQsT^Cweu)>#o+^GT+t$8Vw6-vx4>);C-U~q2eB!AFpUaCJfvMx3ueN(w-v> z>JdGvv(v4{V31!)#yUhA?OTp^Q+oY~Zm*0q)UlNp<}DvYq(*IxWvimnZu^U`LEgPC zm#|Ow&t^@M7RJJOW%u8_`rZwQuxSz(AQEQ{+J4oIFQK=>$aF3`EklHQFNy!`3L*+| zzrqQM?)gW6nWk_RfQJ-7)3QjUioIEVvX47BV$4ZHA3Bi>yx zYI^jOZuCpCRQ#y2G6?5H{OR72eZJtM6mHr0#m#g)A6hsowvaYQ-1kxWyA zr!N2QEV~#Rnl+#Vs$!yT-vT=j#5#T3V(Qu`kc$ipt}jOO3@ID1M1$n~^#~U?T&Uba ONI8P|TeRVYJn(R10(}Dj literal 1348 zcmV-K1-tqHM@dveQdv+`09PVj569J2qG`BZ?~mgAyq%KJw?}XdrDnz&1Y&NN*i6nIC}k;3a3DcPtytbx~ofn&dCN=>U^ia$qyx-l^d4G zNo|Rk+LNdKAVDe_l#uh#4Z{%ddA0tn=YT*hAXC$k;)()v=5}LSU1PisY1pvO4P|F5 zU!LEVPC%5&5I8~V&BC{xy$je)(5T&b=&N8Dd#1i;uZdW0;0&=|p6-WicH1I2$l4JU zmdDg46j&o*n z7&1&04eKCDk=0_cWA$SYgc5~}e*IMxMDP|n(b{KN0c}#MGMpn`?7d(cpRq)XB1>m* zMw?8jEn;XLE>LtzU|YWBy0r25k~W&IP`g1N>Fyz&kq3jV9n-3C0zDa{ zD(l+TX!&S$Nf10n?+m`Tx=|J1SZYGd<%wE3HCL?=kEsc3|6&Z34Lq!Vmy(AwX#PVS zE?FjD%&=MDKN*dC(}7#m)^ z6-&eNZH_59rd@50rM?oQkabj9bci?h(LhZXBvZ_7E;@4z1Ihnc^(JqXvT8mckhPQ1 z$UeMBP64L^^lQ+t2hXvDIBM|X*Nt(!8SaM!iUw=mhu+oy%>M6&bx@QHOd@PQy1Bc_FGv4F41{1pg<{69 z=8HFqHc>Bmq;m4Q{;oR)wL(-?oRV;toJ&;{Y@OV?q0w-oy4J4bF4lWu?03%wbT)$$ z#H$tIY();)FQ-*39srUlk-PVO`^j~8yf%WvNf0i<$vuBb_oj3!T>oSn%xUY1j);Z{ zq{e2A?DrU@4LR9my2wg3KgnyX@ji@R4*1+{n6d92Y3Q{W6dy37D%p&F9aO5J^aDTPBNd8;2yvR5|5kNkF{{NwgmP zZjp9kAFfbIY^@iGm9rA*z-4tz6ZOaLG;w@NHDWtj$e%9?nWt>Q4MV3dlsU9&#wDif zy^pZ$Ym7-VV2_SeePzkHa1I|1*38u3Ve^F@TEJ!)Ujv|Ue0!a!t z1^v~sS2b(e^7u9p-)Exjj-VaZa4dA9vtM|7DPb^z@r^3yu5}j3EsF|og2zW3*jd41 zj>3lSadE`oM@dveQdv+`0E*Z@#8qCr-(n@;@>M~!$CWKlMe(^r2qpPs2P&j%TfV1x zss?PRicc59 zoX*`8NacngJKs$;u3bw{_#hWrL&?1m$%a{;-1S<|Rl6n7OHr{`!A16pifhzHF+%P| zOrWdNcxe*b83=fqx0{BwsO!QiJ5_Vb`ZRF%%8nlSt_Gj1i;rZ8*a}dVy<-Mi|u!a}t48j$OL;K7iuoKxBlk!?O^ievx7YF>ASqJKw&!nNYIG z1vMO!|Jzbb0rn0LS)|i+3VHLax}*>c16LAeZJln>?K0x)R{evN;GIx1ueb6Q$Ojri zb^;mF`+3DTr$(`kC%nE1*1_ZjU8N1@h_noL5_~u+ce*8w8Uot!o4)8@Ny$a>-qMUp z`;b30hzzxg7sG0g&)7&f-YkVuGa-F^4$)?R-U=^5YO!P<8FZu0Pr0;Bf~zhoRNq?@ z4H%+I3vt(m9S`$RLn5VcUfHr>vOfC5yB&Ca+bV>6tUp2Iw;PtgVVaF8o*e=KL6ICR zsR?q3vZe%R}LXz7?#I;hfTt#OeprOEu<_c2nk$E6LI-K= zL>hru_!hbAIfYnjaht#{q*i$wY@?QMa_iNGpdSZyDnVA}{Sug$=DQJZ%_{@(-A1O& zK!e;_;X~;<+U(}RC9lRRfI`;pG)~du58en?NUlKYu(C2mlx)~7nD;4W+mw_mpASf; zVvipHZ{Z04GC2hyIyTh>CIDv9RgR~#9#elTy17#ET5+gg@6lvbOWW~*=`h{i8C8DS z2`{7U^%W#yet7}Be!~cQv=XTRZ6AmW5FsG+EXzS;_7^=*n$o(m8nC)S2UE&phGn2S z+yHeOoDi#`uU0C=Ij^75|^?wfs-OzbVQvBK;UY`+Dd13N; zu%eiMCy7CbbetlDVj`VpUmhmL*Z^Uak;h8foSpva7C@o%eYtLQESv&MxI?JI!)b%?koqJB?QaKa(oY}W z3hz)Zs|!fEkP_5>FPhKS-OaeWz;CzoxJ;c8Ig7Hz3it+WmORY(f|M0)v4H?gx&5-# zrgAZx7O!r((g^jVEc5mpb2NL71J9Sz`DC?+=`aWJBT3rOq|q$GGuausYjN3v;|(WVVy_~Q+^kMCQt^0l&@;Ma_#@nYpBH=mDKF~Z~o zB-maIsrnipn|sI&>ido=waeCD|rhtvQ7 literal 1097 zcmV-P1h)GCM@dveQdv+`0KjNO4b5#G77*?3hU1U0kM|GA(v|nQVC`u?#wE5WOTGtS z;ygPnxRt%lDD7^fqOGujJE(pgPet_PYIPzTgE6%t%q=hIe>Gz(*S?AGQojjN5l-}= z77gF^k0y$Mo`@c!giF>S9vk4Bk$xEbiG7(apUsOz@R(CwCExV?J2oJml!g?8WtC5W zj&Nc+Iy)@ubGoJ-Q`&F9brp;DQa4fF_KjaF;B>ne{~HI<*v2b0xCU(5; zjX*=5m1iwl#rjJt05I)n{Gv zt2kRD;Pd};O67_5ahf<@f*Qnc@U@~p`l{SRjpiMQ97RQ~+1P`>mBTE|nt%LD$TF3= zOeq>4qe767eNC}jMJ{8J0e5pny?=U4Bl*anY*S%;9ZSQxcuy!g0F}nJw5vM}T$ZIu zp}B_IrCkR~CXIaYOg&A|HTN0BUtO$OU^ARS{HCcj!N9alBz$_4cZGwtVBDFr~UZPDJEGXNeQp?styLQfOT`)&m1bWLX+e@MjMj= zt~!3=VmaWg-q(#Qg4fP+=e`FK@=wmPmg588E;7kh*w4I(=mBivE^6u;=XriWf=Qm0 zC||(?gx+vmSgb_{BYwt4K3wd34>cXHFXA(O z7aONq-Z0Cn9&KzP{%VAd4E2`IJ?6*iN(EsBlZ~ zG`E={Bc4>ddnTwU0+eNB0{i)Yyhb*7Vjx@f>p?-Hg|hITf%xVE1^R$Uas>eGkZ*Tc z>~Y{O3BnFKau;)pR8aJ!DiNsh9^_d{jTRUME?jGV-_hAa+$qOpVVImbn*C~<(|k`{ zgDyV4w2Mb}DKHW8i0QF{wio=+#OX#Ge7vinJfCpGI`k>D&9C2UYZm)(MP}i#EPn$O@H)B4AfS zZi6m|N?+JfvEg`uJu|73@xIHkPe89ih|Rg2Yq@CG^oDddRMFC+*Z=}FyjVSkS5JRV zmpV8|YrYCG6!(1pSe0tH-+m98J{{m{H*rls{*rD{n1m3jDYZke=w2E~W;YqW#wXL+ zIH4I#f$3J~NYaBjrtiFk#9Gv%JhWm{vnPu~GOCl=O|P zUQbj~`aesl*;m0dmDXlG1Eh%)uqheiMUJ{&Ut-`(SD?2?wFoWTlxEWO(+Os#_dHrR zL4HCbFhwuBI~e4t8`Od!lH}!e9X4T6ktZxo!P`!V5F>2!%5G9BLx}Z_ zmp+uNN6J!Iw`H!>B?l^Us0z&=%M@iu?CcmnCHP{qL_@yend|Rjq)NpO>Q6KfC1Rp# z7?8QcJY)S=wVz7?y()ZZW`{o(5|w(EZMZCsx5Ia+3)v}t=}oQ_VZC%lPw zt$>P>Tdt9XwaoK(W!)@6VMadQ<$I;j&$*e#5-J>^JBqgKw&?(OzV7?KTpL!)CwS2I zetkof|BA8&So}p*%ZsUyd;arFc2l{t4rw86&W#TN-v}SpdEn(DA7U@X2j{RB`y@iO zPqu)SN{bd;nZ@hfa5)|j<6yJZF|o8qUpArq+2a~k$Ytwl7909ex8s{xtd5rhYnyvh z;FR5#-h=&227iia)3)f`I%$L%0nGmok3_x_2>xkbT&PLaNjN?4_-MdG1WeT|avI&!ZRgxEjn} zWfCXy0tSol`;gjnmE3+1!e8IIW0j@#>0cR}# z3d1SS^r&C=0W4CS6_3!goP|te=k@qqC5c`12L{xqFN^>OMi%2`%O@x|F}K``v4pw~ zR&x%&9Sfbm$ssMUO0nK)A!uy!H9$`%q|Dv2TNtGaxEpa}7HATZ?rBL``);G0j3$YJ z5=z&^Xk^2lvd>5km+G^e!_&BRqJ8s^aqW(uts7TPC=u_KGXiyZLmp~KP(dK8WDJKJ zOpR`n0i5odk|Ex;TTBvB>;K(&VBK|4O4)f-Thl!JHp!%m?1Z-W+ATuksc?cTUfdpP zK3ZyX8C7*K|7ehG7J6Zr(>(;oc0{)cct<75X*A~UJg+Y6+-iIHpS0f@BcX>1gTrW92tyOQN2r&uQ~V#92z z;&Zi%;|Wbytht!N3yh67>a46V!Y;vMuL48!n*ddD_p|e3l_@aksm-KSEs1a!lUi3= z95R#xDx5=@L#lStLPfDetS9)4fxHzqGc!)<&`LjwBaMHyVt(mYE_(cmSe%YTA)F*v zqHT4!T*?@;0OutFePZksWrn`}9a9DBbuNZ{t>F<#1Jk4^AAaH7-GsB@ZB5h#+!X`s z(csX@8SlyVGMPY>G!p^T3rd=Vh*WLDIEr>BgwyWI+s+BJdRv?IV>#*Pg9$k0JM(dK zJSgXw1`2gP=t1%uHKNetdysv^AIXQE+pyU1kQW4*#_0GX_KtBjq(s%oH;j{r>)HIW zZ~Ug06Hpq~qR~(}z!)fvL`K1a&;*FXq-qZNxXv9D=06>`WX1U#ZkkO(K&BJN+FirB zq(`1UXZ{ci8N^TEt10OY6(brdg8L&4!l6_&|BdD zp9O69&v~#`xqa?;r{gX{lukL$8jfd_`O-Z8U>%ZF*@`hcw(0)wFeiApyZhaTqeW%r z@U1$2A6fbnnM3uVeuR{vVbbgxbCVn`7=OJYR144oed7|PQl13R%LCO-=zG?o!(BNm zDHfnHKf=C>=}AaO?VuvqC^J9XKCPBrK8MDkA^WHlz? zH{()3PzseQEDbcSGGe*WE(k!cZD*!*0jW|2<%*bdc}H7$MOo6#K<#S&Xok6(mHA6a zah{8oj?$cF?$!0rjt^#823#=u$+%QZ|5ie30D;^9TG;^GMiJevuT7AI`U_ZV!PzcvL6R3$+)P)rtHgjRlD#x{C5%DW2&1$buy-{wOJZ}yf7=}t zVYp!w!*9dJnRpx&_#%3kMtL&>h?TdM1TC z($J}qyC*ph?qX|+^jZpSEXQvg7=*B)wJsBWL4#~|8A+-zB}$qpll zQ)r{O^NI58CZc$*)_f^gm#9}53o{zYlugm;hRh#$Apc6dE=bG9%w%V!{hNcRPJ4s z)m;HEIQpF-?8nBu{0vbfOfHnEaLQ};AM|&6wL%yXnF*wQNAv_Bkm$6rVyrqC;k&Kv zkrdZ=%P=7U(#xVaD-viJ#hEe$b6W$KUy+4_fP6)reEV;F%+yZ-(-CtJ2r0m7I5)Wd zxF$0IUZ}@egTBm*pXKn}QR#2{1hQed8mxJS6S7A8Fr~fZzjjpc1lvsVY681d$v);R z8L!A|xf@kxpS`U0T}rFnWtUlROVyhS{L~Mw?n58|!t}6Sig}~OHzw{Jf49(YbO)i3 zp)s2}jE0UtFd@z+zl+(b|0x=SQWpqinv|f$BgYXh+_P47-&p}HR^Q(DC=07m0v25>)II970Y?@NLehHa}FlN6HJOHo|Dg;z1v5T zyM7WX_mFfHVdxD#9{*K-o5Y;o)TPNC=>q^9xhS#YkOU!lb`sjV!nZ?;-|!u1Wjgp! zSkvo(0}Ex$G6q19TM@xuao@m-a7sD$b;1R-2c`W(zBU6)e1YkpW_HSjs+G$(^Bjy8 zb0jS(SHZZGJhh;$Tp^X%SKQ}pR`j)e?k4MdxhasG!F?eE?yAM?MUwBs2UUM}{2IHEh{%;(N67M;@|1P8>t` zQi{m!Oz_BC?*@@{CKAy;lFrOS)im1m$?ORIKn=!udJ=_dMOCJMq;s`kAts1|FwNw! z@rNYUsX2%)Yz?W>qL%qa@WSV*KO$#f%!iWq0}aRMcEHzCsBQ0$6$48(YS(+Vxwe0LH&CfHR_V^&;jmG)KR|L^BkEAHecgZ=0yUzxzn z7hGJ~(YL1njP+#Zvz<-;(yyV_-%pFg*h7KvyoH$HoQUiWO{DGL+~W+4Z6BW#!_Uoz zIAyJav#BOhi(*N2(oC+it$=#Xt)iWdSoWKB1H+EW|G5@u~ zh-oi|I*a>kO4nK<9Xn_TdIaSo2?$_3_H9t_KHXrqPw+iyl6aCaR!Z8BlW|u-ksDM`w{qjY)g9m4g?wS)B#oSJ+YVb!r9d9CW^y7sf zuUAQqv@R28EyArrW}^s+yw^UCg|*4EPx?x$iN6-AP~7rm)*^Wj+hrpEeedP!zw=d> zeXWQne=F8ahd!*ALz2sb19xbSqnFR(#BI2$01wkc@_Ga`IFtKpld45130~S&xEi| zxP!q;0KdABN+6HymJ7KeS_Y)v`xp5MV-s-n zVCn7>0eMRsxuRLYIBka2imjdz1W9ryAh+ zNzKq!sObXYGIhf+C|%@2-}n^o*nu=1p2rNz4xh1U zHW%!nJ0lFwPbIjdLQe}hGcju*Ulxm%&vdA=>RHh%l=XsCwF3k@+V>&XWV%XrTroex z@Kn|+3*+2caGW_5K3m&Ju%T00+kZ~86V(>{u`@LEfEDvvG5kZ_ystSe*Z;gp7m*1Q{E);;my4Muz|3u9!?(1^?#kz$etHqN9Crrjxl(ILTqx;-O$#J4*0 zsw4z7ms;Oky!JJWJHqN4H{Zvf4bIKLYs2$zKQFKyR3n>h^(~VBoAhzgcK5EW*3Xfb zd?&`-K*_tTzX}ZH3#tcU<2-+&zHomoL{+4k7=n=sr5=Hmz`>E0v^h1yfuCkfrlf7( zUucD-Q`27mS8{P->6Sj($1bPEpHlO7H(kQhu@v1fvS_zO5iSHURfWk0QjG$jv z0uyUyJZj6*m@A3#OFY;fr8tC{>rM!#YrDL6#no2eF-w8jQlN%ugT2uQgj%pD@)r6$ zlwo9k;N4UxIfCx-bG#dabDo)Wx6V@}aLUmsZwqC@VUJ+)xITKa9Np560uS#G|4c<5 z8n^pNhLdkW{Z#VK>&x8wCysJBzh&@aHP{{^N%QTcSoFfB&DRxOk2eIU{lCgjtP_-S zK~P}KLNoUfzpAfYAk$oB!LSmT7bfFgza92C;v`(j#mFU1asjeW+URy2asUUG^{j=;J4g_ zCo0aAcSDjqD~OCpXQ1;>rvJLtsn&*iBe8M$vafVs6p4dROs%Tm$`Umw;uCwanQP{z JRP3gDjb?gcU`_x4 From aa57463852fb35d73ec699c79e0b4626dd8bf5d6 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 10 Feb 2017 17:23:19 +0300 Subject: [PATCH 22/38] add to config name of fields in cookies, reduce dependency of Api implementation --- app/src/main/assets/configs/config.json | Bin 1299 -> 1374 bytes .../droid/configuration/ConfigRelease.java | 12 ++++++++++++ .../stepic/droid/configuration/IConfig.java | 4 ++++ .../org/stepic/droid/web/RetrofitRESTApi.java | 18 +++--------------- app/src/sb/assets/configs/config.json | Bin 1315 -> 1398 bytes 5 files changed, 19 insertions(+), 15 deletions(-) diff --git a/app/src/main/assets/configs/config.json b/app/src/main/assets/configs/config.json index ece499bc337f6cc9723b2710015459565a5d1380..edb813248e151ae9e953d1e20470ad30a2f31eee 100644 GIT binary patch literal 1374 zcmV-k1)=%?M@dveQdv+`06Tyz0@s9Vds-vOj7LK+RW-dIsEkplVge>M%}$H|hOcWD z&**-G)xM=%PN+n)ayO{$cU3gQ;R0kVlMNt>+7Xz_`0s~P{ZVS1h(e@#RMB)g4m+2U z4lqS!^Se14p@kHtrAgB=)=NCKKo{nyH4tPnAk$Vbl4N#l_xBmIJ= z6FHEg9wCt7N2YoGFL}fD#Fg`wKp^^TDCCML51p%Xg{tJ6pc+Cu;SUjz8V=$)7r_Z9 z2)Qdl^a$Avw+9anN^96*Vl>NYXr?y8d9_kvps2Sx?t0D`l_`^31af>_s|7=W_9LDj# z=}Dy$YefZsGvN`ba z8)}M&Y)AHOP)9sRorPLYFENsg{r>wK&BbS7a2n9E@X5uYJrK(qr2|mkEI=rK6Y(RJ zZwd?35kHp&NWV`I^AAYKm`{!SNNr{M2o82vmhr@hQJg7Suo6?27v!c*+;h;KofvIW z%4D0#Z~}A0O_zVoJAzqQmpX9_zzOUIJMbs0!j0EVlk@#B54&@wo-jYR^J_ztNlL-b&rswo-$r$48>WYP-${5I9l30Y3)PGGZYA9IubEEU2TAFA zHXpaVnxJG+wcG;($Q zx-Mmp`3}}-_?8uwg8TO^iPLG?e#si$?qisJ^cx5vV9Q0UU zb6H0h4>=r}s!-N!LOg$BYr`F5+!ew>-u_N%WgD13X3qv=TTc;|b|8nBU1DS{{FF=2 z-(7Frs)C-0ZUrft*KmsYL>d`iu*(nScV6)K7d?O3wr!cj65a>HTlI-o$?+E>kHzP7 zkUNR8BN5Cm${R(P4MAN5yVe;lM%Uoo93#7Hoe9Kd6YRUM#ZaDd$Rx;n^h$8ek&;`t z>@5vOs>e?iyJY{BiKelaEN6(->i4!3QNhB;zFO;hX0A`a+kWInNeg^4*!ts--4oIR zSrX8jn*NAoWucK~pxtsntNm2nxB?GPp}gvD!LTj!BU48hMq+DE`7X<~UjKH$4nwP- zr0u8Eo@F1182m8|#9*q_;?n$eC+bbdmZQUx>xa=*J3ep5B^N*=BxXx6idcLMa4#+8ed0DQ=>%V=ik=KM!8ZCr}BV g1hka|>%BD{c@vl(+A%Tg6l@jz%atyB*|v>VTn?3=vH$=8 literal 1299 zcmV+u1?>6&M@dveQdv+`0PlRt^HTyVpiSFI#OM4?=QA6vCM=*vw@V^PCR-LwX$7Zt zs-Q!ocg`}elhuk~LYhN^E^TYiJ|VUX#oemWzA3E;KV_cm=vbQ;L9v<%XkC zHErTC1o-hI9x9aQQw1U`s2S1HVfOXW0bXD&(p=HEoc3??*Z2t}UY@Jo19I?m4A3Q` z=1M-16UoP*U-OGiJCTCNwZ-{rZ7Xy;g#!Cqe|jERHDe(LCp<6~ZhjAA&Y<9w2*rF2 zg%tvD1wx>-JE!91IaX~E45x?64F_`&ee}kxB@N~Xukm_y4p-oor(H#0sTtbFu+<+L>?F6- zyuBRHlmktxbDy@Ab1^ATo~lm3q=4OF%fr)IaQ>WmB_HZB(?oXFbSvwEs?dH3$r>8A zJwLgBkaClgZgGve56!+;PMcTVoEE2>ar`Vw=+8)&vhZ+qQ79$Rs&wBujZ3fa?#O7G zcXJ^(6uCL9N)M!O{-P#}%3e>K8?m<9AC8(_k>LQyq^eQkZD+DI1vG;qnoGL$*@!|m zyQ^@GVaUE4+ReVuc;i@Nr5aOC(g38SLtD|`UFjuoZ#B;x-;7v@(ZQSFFf>g4yY1G- zMm_Dt<$DkF6zx!SsL$M_ZGuU6K`>X=&JL@lyUde|s~9K!vHwBa68WIJau(*6U#1Z6 zQ+%A}C!t@xjm^)1-S=SnUV&ZcR@a90?LK$z&$|<8wX3T;>CCbC<`jmX1cXXV;BavzJ>#Z>6Adhdl|qb{H3RW_5H{^tydF(p1J?I=pr? z{r38?L^I1{JLX;ou0~D|Z7?spk{L|E)f#LLO(5AM<-+!-*pDIp++LP?`%>Y*V)N+0Ju!+_x9p zys`rLXdSxR-*<^*4;>IM;F~gFrva^^GIVl}EMMUW!&Q03s#O4A84Onav*|SOmjznx zU`7m40aSl2%RgtfJjR=M4UZX%y!-WFKi0Be;06)ZA^k>|dyxfz2u61*l+i*e!fbZS zLsQpx@&bYJmNfsKHi3+dJ@1;%D!0f{mIkf(;LW3U?`Ujv3%OIad1SRW`FYvY2nDcg zlIr)-Hh#$6UKgG0<7#*AsajW>b&+Rkq|2SI9)N3q!cvx(O-0Mw!{C*-_blCsKO0@{qpD(|sfV5b^{%X*?m)3ox<^t|& z?|Rfy5Akcjp180~*0=1crVQX{?X~^hVK4~s_mvA53nG8;-W9^LA$EByr>IvMH@dwh z&NpAfCsE5mun4MK?=()~bL!@_)_@yX*{bNI*8Q?ANr_4M=tI(ep82J9pCr9l1et_2 J?pJ)~gAb|FlNSI0 diff --git a/app/src/main/java/org/stepic/droid/configuration/ConfigRelease.java b/app/src/main/java/org/stepic/droid/configuration/ConfigRelease.java index 81240c6adb..1553bc89cb 100644 --- a/app/src/main/java/org/stepic/droid/configuration/ConfigRelease.java +++ b/app/src/main/java/org/stepic/droid/configuration/ConfigRelease.java @@ -42,6 +42,8 @@ public class ConfigRelease implements IConfig { private static final java.lang.String TERMS_OF_SERVICE = "TERMS_OF_SERVICE"; private static final java.lang.String PRIVACY_POLICY = "PRIVACY_POLICY"; private static final java.lang.String MIXPANEL_TOKEN = "MIXPANEL_TOKEN"; + private static final java.lang.String CSRF_COOKIE_NAME = "CSRF_COOKIE_NAME"; + private static final java.lang.String SESSION_COOKIE_NAME = "SESSION_COOKIE_NAME"; @Inject @@ -168,6 +170,16 @@ public String getMixpanelToken() { return getString(MIXPANEL_TOKEN, null); } + @Override + public String getCsrfTokenCookieName() { + return getString(CSRF_COOKIE_NAME, null); + } + + @Override + public String getSessionCookieName() { + return getString(SESSION_COOKIE_NAME, null); + } + private String getString(String key) { return getString(key, null); } diff --git a/app/src/main/java/org/stepic/droid/configuration/IConfig.java b/app/src/main/java/org/stepic/droid/configuration/IConfig.java index 0afea24c2c..4f1c243d07 100644 --- a/app/src/main/java/org/stepic/droid/configuration/IConfig.java +++ b/app/src/main/java/org/stepic/droid/configuration/IConfig.java @@ -27,4 +27,8 @@ public interface IConfig { String getTermsOfServiceUrl(); String getMixpanelToken(); + + String getCsrfTokenCookieName (); + + String getSessionCookieName(); } diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index f70174b5d6..6b37e84992 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -29,7 +29,6 @@ import org.stepic.droid.analytic.Analytic; import org.stepic.droid.base.MainApplication; import org.stepic.droid.configuration.IConfig; -import org.stepic.droid.core.ScreenManager; import org.stepic.droid.deserializers.DatasetDeserializer; import org.stepic.droid.model.Course; import org.stepic.droid.model.DatasetWrapper; @@ -45,12 +44,10 @@ import org.stepic.droid.preferences.UserPreferences; import org.stepic.droid.social.ISocialType; import org.stepic.droid.social.SocialManager; -import org.stepic.droid.store.operations.DatabaseFacade; import org.stepic.droid.ui.NotificationCategory; import org.stepic.droid.util.AppConstants; import org.stepic.droid.util.DeviceInfoUtil; import org.stepic.droid.util.RWLocks; -import org.stepic.droid.util.resolvers.text.TextResolver; import org.stepic.droid.web.util.StringConverterFactory; import java.io.IOException; @@ -81,12 +78,6 @@ public class RetrofitRESTApi implements IApi { @Inject SharedPreferenceHelper sharedPreference; - @Inject - ScreenManager screenManager; - - @Inject - DatabaseFacade databaseFacade; - @Inject IConfig config; @@ -96,9 +87,6 @@ public class RetrofitRESTApi implements IApi { @Inject Analytic analytic; - @Inject - TextResolver textResolver; - private StepicRestLoggedService loggedService; private StepicRestOAuthService oAuthService; private StepicEmptyAuthService stepikEmptyAuthService; @@ -563,8 +551,8 @@ public Call sendFeedback(String email, String rawDescription) { .build(); StepikDeskEmptyAuthService tempService = notLogged.create(StepikDeskEmptyAuthService.class); - String subject = MainApplication.getAppContext().getString(R.string.feedback_subject); - String aboutSystem = DeviceInfoUtil.getInfosAboutDevice(MainApplication.getAppContext()); + String subject = context.getString(R.string.feedback_subject); + String aboutSystem = DeviceInfoUtil.getInfosAboutDevice(context); rawDescription = rawDescription + "\n\n" + aboutSystem; return tempService.sendFeedback(subject, email, aboutSystem, rawDescription); } @@ -581,7 +569,7 @@ public Call getDevices() { @Override public Call registerDevice(String token) { - String description = DeviceInfoUtil.getShortInfo(MainApplication.getAppContext()); + String description = DeviceInfoUtil.getShortInfo(context); DeviceRequest deviceRequest = new DeviceRequest(token, description); return loggedService.registerDevice(deviceRequest); } diff --git a/app/src/sb/assets/configs/config.json b/app/src/sb/assets/configs/config.json index 7dd5ae58b7cccada75c4e5933de1f28a990f096d..c8f07365044a982bd716c35da4903776d03e75d6 100644 GIT binary patch literal 1398 zcmV-+1&R6qM@dveQdv+`0A5D5(**&C+h;~wAQr1my1uX>=2OGLgK~)x}XO?Z7pBK9x6^@81-O5;D|*UYGI# z9Cph}h?eU^vq=3d@ZC`PESG>@ii=5!Z>oya@y?uPqu~spCr(e@kx)H?s`oRE-3V=w%Wu8{rBY8adA9p zd&IL%@7Skmt16Rob1shIf1ZaB{65`pk#QMk$nqgKVqW>f1@3?crd~4?#Vr+VDb0O1 zC0A!C0$$BlU)sD*m^(T6?#PH}X*sB4ZCZPz{(U$=DT#42PF&( z3G^b`9C0StBnImj$kJ*+Zt_y)nTNaRxqaGvrC{{)&^d#I5wLcDTPna3(1klpfc9ww z+oDG{6h*pe#2XrJn)971v8rqHCmuj(>pspz!l)*NU~pbnXmxg~r+(a*DR)>eWaqD@2EYAEfvi0q&Ze|dtE55J zvR^a2af7=SBzf=f!1S3pgv$u0j{18{Ywk*1cGq2U6_aT86)ZzhNQg6*(m;)2A`;Fu ze_Xi|G<1+UJe$3BUxWZ9m4h*~=Kv7zB|!${sXcguN|ERPeCJ0?FXr*t+mosZbZ_m# z{bSO-k6?>CI%Ub$n6bBJlpnHVEiyKvq{VeBC;!9P+QD!zTvbII>3wV`=N5k{E|RoN zuRY2`W`W$&P!)V}8%Yr|h~X4h4B1fbwRsLKUei2nRCsVvuCm0MFTMpJ2bstpf;O+v zr1&GSMJxvzlfvIU#Ly6GMm4N}MAa^m;R=N~;Ko;Wu_ki5+RS9R+nzbbh+A-DKvEe= z_`?FbDe{X#2bc2Z@kW5TB_W>j2(gwxh!o&LZq(-);Arvc`D?hv*Scp>!cEak;pa&I EUXIAJ5C8xG literal 1315 zcmV+;1>E`oM@dveQdv+`0E*Z@#8qCr-(n@;@>M~!$CWKlMe(^r2qpPs2P&j%TfV1x zss?PRicc59 zoX*`8NacngJKs$;u3bw{_#hWrL&?1m$%a{;-1S<|Rl6n7OHr{`!A16pifhzHF+%P| zOrWdNcxe*b83=fqx0{BwsO!QiJ5_Vb`ZRF%%8nlSt_Gj1i;rZ8*a}dVy<-Mi|u!a}t48j$OL;K7iuoKxBlk!?O^ievx7YF>ASqJKw&!nNYIG z1vMO!|Jzbb0rn0LS)|i+3VHLax}*>c16LAeZJln>?K0x)R{evN;GIx1ueb6Q$Ojri zb^;mF`+3DTr$(`kC%nE1*1_ZjU8N1@h_noL5_~u+ce*8w8Uot!o4)8@Ny$a>-qMUp z`;b30hzzxg7sG0g&)7&f-YkVuGa-F^4$)?R-U=^5YO!P<8FZu0Pr0;Bf~zhoRNq?@ z4H%+I3vt(m9S`$RLn5VcUfHr>vOfC5yB&Ca+bV>6tUp2Iw;PtgVVaF8o*e=KL6ICR zsR?q3vZe%R}LXz7?#I;hfTt#OeprOEu<_c2nk$E6LI-K= zL>hru_!hbAIfYnjaht#{q*i$wY@?QMa_iNGpdSZyDnVA}{Sug$=DQJZ%_{@(-A1O& zK!e;_;X~;<+U(}RC9lRRfI`;pG)~du58en?NUlKYu(C2mlx)~7nD;4W+mw_mpASf; zVvipHZ{Z04GC2hyIyTh>CIDv9RgR~#9#elTy17#ET5+gg@6lvbOWW~*=`h{i8C8DS z2`{7U^%W#yet7}Be!~cQv=XTRZ6AmW5FsG+EXzS;_7^=*n$o(m8nC)S2UE&phGn2S z+yHeOoDi#`uU0C=Ij^75|^?wfs-OzbVQvBK;UY`+Dd13N; zu%eiMCy7CbbetlDVj`VpUmhmL*Z^Uak;h8foSpva7C@o%eYtLQESv&MxI?JI!)b%?koqJB?QaKa(oY}W z3hz)Zs|!fEkP_5>FPhKS-OaeWz;CzoxJ;c8Ig7Hz3it+WmORY(f|M0)v4H?gx&5-# zrgAZx7O!r((g^jVEc5mpb2NL71J9Sz`DC?+=`aWJBT3rOq|q$GGuausYjN3v;|(WVVy_~Q+^kMCQt^0l&@;Ma_#@nYpBH=mDKF~Z~o zB-maIsrnipn|sI&>ido=waeCD|rhtvQ7 From 88057db426acc68132204b089f671ee89db2c8a9 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Fri, 10 Feb 2017 17:25:17 +0300 Subject: [PATCH 23/38] change constants for cookie name to config fields in Api --- .../main/java/org/stepic/droid/web/RetrofitRESTApi.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index 6b37e84992..fe7c1420c2 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -327,7 +327,7 @@ public Response intercept(Chain chain) throws IOException { private final String tryGetCsrfFromOnePair(String keyValueCookie) { List cookieList = HttpCookie.parse(keyValueCookie); for (HttpCookie item : cookieList) { - if (item.getName() != null && item.getName().equals("csrftoken")) { + if (item.getName() != null && item.getName().equals(config.getCsrfTokenCookieName())) { return item.getValue(); } } @@ -499,16 +499,16 @@ public Response intercept(Chain chain) throws IOException { String csrftoken = null; String sessionId = null; for (HttpCookie item : cookies) { - if (item.getName() != null && item.getName().equals("csrftoken")) { + if (item.getName() != null && item.getName().equals(config.getCsrfTokenCookieName())) { csrftoken = item.getValue(); continue; } - if (item.getName() != null && item.getName().equals("sessionid")) { + if (item.getName() != null && item.getName().equals(config.getSessionCookieName())) { sessionId = item.getValue(); } } - String cookieResult = "csrftoken=" + csrftoken + "; " + "sessionid=" + sessionId; + String cookieResult = config.getCsrfTokenCookieName() + "=" + csrftoken + "; " + config.getSessionCookieName() + "=" + sessionId; if (csrftoken == null) return chain.proceed(newRequest); HttpUrl url = newRequest .httpUrl() From fc1458710e84fd7de8f30265433b7b91dcf25635 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 13 Feb 2017 16:56:23 +0300 Subject: [PATCH 24/38] update retrofit to 2.1 for fix wrong refresh of token --- app/build.gradle | 4 +- .../base/CoursesDatabaseFragmentBase.java | 15 ++-- .../droid/base/FragmentActivityBase.java | 4 + .../stepic/droid/base/StepBaseFragment.java | 13 +-- .../org/stepic/droid/core/CommentManager.kt | 28 +++---- .../stepic/droid/core/LoginManagerImpl.java | 23 +++--- .../droid/core/modules/AppCoreModule.java | 16 ++++ .../core/presenters/CertificatePresenter.kt | 22 ++--- .../core/presenters/CourseFinderPresenter.kt | 13 +-- .../core/presenters/CourseJoinerPresenter.kt | 16 ++-- .../presenters/NotificationListPresenter.kt | 4 +- .../PersistentCourseListPresenter.kt | 4 +- .../core/presenters/SectionsPresenter.kt | 4 +- .../core/presenters/StepAttemptPresenter.kt | 4 +- .../droid/core/presenters/StepsPresenter.kt | 2 +- .../OnResponseLoadingInstructorsEvent.java | 12 +-- .../notifications/StepicInstanceIdService.kt | 2 +- .../InternetConnectionEnabledReceiver.java | 4 +- .../stepic/droid/services/LoadService.java | 10 +-- .../org/stepic/droid/services/ViewPusher.java | 4 +- .../droid/ui/activities/RegisterActivity.java | 21 ++--- .../droid/ui/activities/UnitsActivity.java | 8 +- .../ui/dialogs/DeleteCommentDialogFragment.kt | 16 ++-- .../dialogs/RemindPasswordDialogFragment.java | 12 +-- .../droid/ui/fragments/CommentsFragment.kt | 19 +++-- .../ui/fragments/CourseDetailFragment.java | 14 ++-- .../droid/ui/fragments/NewCommentFragment.kt | 13 +-- .../ui/fragments/TextFeedbackFragment.kt | 12 +-- .../main/java/org/stepic/droid/web/IApi.java | 2 +- .../org/stepic/droid/web/RetrofitRESTApi.java | 82 ++++++++++--------- .../droid/web/StepicEmptyAuthService.java | 12 +-- .../droid/web/StepicRestLoggedService.java | 22 ++--- .../droid/web/StepicRestOAuthService.java | 18 ++-- .../droid/web/StepikDeskEmptyAuthService.java | 8 +- .../web/util/StringConverterFactory.java | 4 +- .../web/util/StringRequestBodyConverter.java | 6 +- 36 files changed, 247 insertions(+), 226 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index 0593e8d368..f0b3cf92d0 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -141,8 +141,8 @@ dependencies { compile 'joda-time:joda-time:2.8' - compile 'com.squareup.retrofit:retrofit:2.0.0-beta2' - compile 'com.squareup.retrofit:converter-gson:2.0.0-beta2' + compile 'com.squareup.retrofit2:retrofit:2.1.0' + compile 'com.squareup.retrofit2:converter-gson:2.1.0' compile 'com.squareup:otto:1.3.8' diff --git a/app/src/main/java/org/stepic/droid/base/CoursesDatabaseFragmentBase.java b/app/src/main/java/org/stepic/droid/base/CoursesDatabaseFragmentBase.java index 499ac23fcc..4f1d3a8a7e 100644 --- a/app/src/main/java/org/stepic/droid/base/CoursesDatabaseFragmentBase.java +++ b/app/src/main/java/org/stepic/droid/base/CoursesDatabaseFragmentBase.java @@ -4,7 +4,6 @@ import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.os.Handler; import android.support.annotation.Nullable; import android.support.v4.app.FragmentActivity; import android.view.ContextMenu; @@ -37,10 +36,9 @@ import javax.inject.Inject; -import retrofit.Call; -import retrofit.Callback; -import retrofit.Response; -import retrofit.Retrofit; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; public abstract class CoursesDatabaseFragmentBase extends CourseListFragmentBase implements FilterForCoursesView, OnBackClickListener { private static final int FILTER_REQUEST_CODE = 776; @@ -182,9 +180,8 @@ private void dropCourse(int position) { Course localRef = course; @Override - public void onResponse(Response response, Retrofit retrofit) { - - new Handler().post(new Runnable() { + public void onResponse(Call call, Response response) { + threadPoolExecutor.execute(new Runnable() { @Override public void run() { databaseFacade.deleteCourse(localRef, Table.enrolled); @@ -201,7 +198,7 @@ public void run() { } @Override - public void onFailure(Throwable t) { + public void onFailure(Call call, Throwable t) { bus.post(new FailDropCourseEvent(getCourseType(), localRef)); } }); diff --git a/app/src/main/java/org/stepic/droid/base/FragmentActivityBase.java b/app/src/main/java/org/stepic/droid/base/FragmentActivityBase.java index 430e07d3f3..6bc6b48d24 100644 --- a/app/src/main/java/org/stepic/droid/base/FragmentActivityBase.java +++ b/app/src/main/java/org/stepic/droid/base/FragmentActivityBase.java @@ -45,6 +45,7 @@ import javax.inject.Inject; import butterknife.Unbinder; +import retrofit2.Retrofit; import uk.co.chrisjenx.calligraphy.CalligraphyContextWrapper; public abstract class FragmentActivityBase extends AppCompatActivity { @@ -54,6 +55,9 @@ public abstract class FragmentActivityBase extends AppCompatActivity { protected Unbinder unbinder; + @Inject + protected Retrofit retrofit; + @Inject protected TextResolver textResolver; diff --git a/app/src/main/java/org/stepic/droid/base/StepBaseFragment.java b/app/src/main/java/org/stepic/droid/base/StepBaseFragment.java index a4157521be..545eb496f4 100644 --- a/app/src/main/java/org/stepic/droid/base/StepBaseFragment.java +++ b/app/src/main/java/org/stepic/droid/base/StepBaseFragment.java @@ -43,9 +43,9 @@ import javax.inject.Inject; import butterknife.BindView; -import retrofit.Callback; -import retrofit.Response; -import retrofit.Retrofit; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; public abstract class StepBaseFragment extends FragmentBase implements RouteStepView, AnonymousView { @@ -236,9 +236,10 @@ public void onNewCommentWasAdded(NewCommentWasAddedOrUpdateEvent event) { long[] arr = new long[]{step.getId()}; shell.getApi().getSteps(arr).enqueue(new Callback() { + @Override - public void onResponse(Response response, Retrofit retrofit) { - if (response.isSuccess()) { + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { StepResponse stepResponse = response.body(); if (stepResponse != null && stepResponse.getSteps() != null && !stepResponse.getSteps().isEmpty()) { final Step stepFromInternet = stepResponse.getSteps().get(0); @@ -258,7 +259,7 @@ public void run() { } @Override - public void onFailure(Throwable t) { + public void onFailure(Call call, Throwable t) { } }); diff --git a/app/src/main/java/org/stepic/droid/core/CommentManager.kt b/app/src/main/java/org/stepic/droid/core/CommentManager.kt index 18f9205453..d30e2b03cc 100644 --- a/app/src/main/java/org/stepic/droid/core/CommentManager.kt +++ b/app/src/main/java/org/stepic/droid/core/CommentManager.kt @@ -12,9 +12,9 @@ import org.stepic.droid.model.comments.Vote import org.stepic.droid.preferences.SharedPreferenceHelper import org.stepic.droid.web.CommentsResponse import org.stepic.droid.web.IApi -import retrofit.Callback -import retrofit.Response -import retrofit.Retrofit +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response import java.util.* import javax.inject.Inject @@ -27,10 +27,10 @@ class CommentManager { lateinit var api: IApi @Inject - lateinit var sharedPrefs : SharedPreferenceHelper + lateinit var sharedPrefs: SharedPreferenceHelper - private var discussionProxy : DiscussionProxy? = null - private val discussionOrderList : MutableList = ArrayList() + private var discussionProxy: DiscussionProxy? = null + private val discussionOrderList: MutableList = ArrayList() private val maxOfParentInQuery = 10 // server supports 20, but we can change it private val maxOfRepliesInQuery = 20 // we can't change it @@ -149,7 +149,7 @@ class CommentManager { } else { //reply childIndex not found parentCommentToSumOfCachedReplies[parentCommentId] = childIndex - for (indexForDelete in childIndex..parentComment.replies.size-1) { + for (indexForDelete in childIndex..parentComment.replies.size - 1) { cachedCommentsSetMap.remove(parentComment.replies[indexForDelete]) } break @@ -162,9 +162,10 @@ class CommentManager { fun loadCommentsByIds(idsForLoading: LongArray, fromReply: Boolean = false) { api.getCommentsByIds(idsForLoading).enqueue(object : Callback { - override fun onResponse(response: Response?, retrofit: Retrofit?) { - if (response != null && response.isSuccess) { + override fun onResponse(call: Call?, response: Response?) { + + if (response != null && response.isSuccessful) { val stepicResponse = response.body() if (stepicResponse != null) { addComments(stepicResponse, fromReply) @@ -176,7 +177,7 @@ class CommentManager { } } - override fun onFailure(t: Throwable?) { + override fun onFailure(call: Call?, t: Throwable?) { bus.post(InternetConnectionProblemInCommentsEvent(discussionProxyId)) } }) @@ -280,10 +281,9 @@ class CommentManager { fun resetAll(dP: DiscussionProxy? = null) { parentIdToPositionInDiscussionMap.clear() - if (dP!=null) { + if (dP != null) { setDiscussionProxy(dP) - } - else{ + } else { setDiscussionProxy(discussionProxy!!) } sumOfCachedParent = 0 @@ -301,7 +301,7 @@ class CommentManager { return cachedCommentsSetMap[commentId] } - fun clearAllLoadings(){ + fun clearAllLoadings() { commentIdIsLoading.clear() repliesIdIsLoading.clear() } diff --git a/app/src/main/java/org/stepic/droid/core/LoginManagerImpl.java b/app/src/main/java/org/stepic/droid/core/LoginManagerImpl.java index 54e89a65be..c002e62002 100644 --- a/app/src/main/java/org/stepic/droid/core/LoginManagerImpl.java +++ b/app/src/main/java/org/stepic/droid/core/LoginManagerImpl.java @@ -19,9 +19,9 @@ import javax.inject.Inject; import javax.inject.Singleton; -import retrofit.Callback; -import retrofit.Response; -import retrofit.Retrofit; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; @Singleton public class LoginManagerImpl implements LoginManager { @@ -47,9 +47,9 @@ public void login(String rawLogin, String rawPassword, final ProgressHandler pro IApi api = shell.getApi(); api.authWithLoginPassword(login, rawPassword).enqueue(new Callback() { @Override - public void onResponse(Response response, Retrofit retrofit) { + public void onResponse(Call call, Response response) { progressHandler.dismiss(); - if (response.isSuccess()) { + if (response.isSuccessful()) { successLogin(response, finisher, null, course); } else { if (response.code() == 429) { @@ -61,7 +61,7 @@ public void onResponse(Response response, Retrofit } @Override - public void onFailure(Throwable t) { + public void onFailure(Call call, Throwable t) { progressHandler.dismiss(); failLogin(t, null); } @@ -74,12 +74,12 @@ public void loginWithCode(String rawCode, final ProgressHandler progressHandler, progressHandler.activate(); shell.getApi().authWithCode(code).enqueue(new Callback() { @Override - public void onResponse(Response response, Retrofit retrofit) { + public void onResponse(Call call, Response response) { handleSuccess(progressHandler, response, finisher, null, course); } @Override - public void onFailure(Throwable t) { + public void onFailure(Call call, Throwable t) { progressHandler.dismiss(); failLogin(t, null); } @@ -88,7 +88,7 @@ public void onFailure(Throwable t) { private void handleSuccess(ProgressHandler progressHandler, Response response, ActivityFinisher finisher, FailLoginSupplementaryHandler failLoginSupplementaryHandler, @Nullable Course course) { progressHandler.dismiss(); - if (response.isSuccess()) { + if (response.isSuccessful()) { successLogin(response, finisher, failLoginSupplementaryHandler, course); } else { if (response.code() == 401) { @@ -104,13 +104,14 @@ public void loginWithNativeProviderCode(String nativeCode, SocialManager.SocialT String code = nativeCode.trim(); progressHandler.activate(); shell.getApi().authWithNativeCode(code, type).enqueue(new Callback() { + @Override - public void onResponse(Response response, Retrofit retrofit) { + public void onResponse(Call call, Response response) { handleSuccess(progressHandler, response, finisher, failLoginSupplementaryHandler, course); } @Override - public void onFailure(Throwable t) { + public void onFailure(Call call, Throwable t) { progressHandler.dismiss(); failLogin(t, failLoginSupplementaryHandler); } diff --git a/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java b/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java index b1465e19d5..df728b32c9 100644 --- a/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java +++ b/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java @@ -62,6 +62,9 @@ import dagger.Module; import dagger.Provides; +import okhttp3.OkHttpClient; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; @Module(includes = {StorageModule.class}) @@ -295,4 +298,17 @@ TextResolver provideTextResolver() { RecyclerView.RecycledViewPool provideRecycledViewPool() { return new RecyclerView.RecycledViewPool(); } + + /** + * this retrofit is only for parsing error body + */ + @Provides + @Singleton + Retrofit provideRetrofit(IConfig config) { + return new Retrofit.Builder() + .baseUrl(config.getBaseUrl()) + .addConverterFactory(GsonConverterFactory.create()) + .client(new OkHttpClient()) + .build(); + } } diff --git a/app/src/main/java/org/stepic/droid/core/presenters/CertificatePresenter.kt b/app/src/main/java/org/stepic/droid/core/presenters/CertificatePresenter.kt index 8c7c4a67e8..aee13861c3 100644 --- a/app/src/main/java/org/stepic/droid/core/presenters/CertificatePresenter.kt +++ b/app/src/main/java/org/stepic/droid/core/presenters/CertificatePresenter.kt @@ -14,10 +14,10 @@ import org.stepic.droid.store.operations.DatabaseFacade import org.stepic.droid.web.CertificateResponse import org.stepic.droid.web.CoursesStepicResponse import org.stepic.droid.web.IApi -import retrofit.Call -import retrofit.Callback -import retrofit.Response -import retrofit.Retrofit +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import retrofit2.Retrofit import java.util.* import java.util.concurrent.ThreadPoolExecutor @@ -72,9 +72,8 @@ class CertificatePresenter(val api: IApi, private fun loadCertificatesSilent() { certificatesCall = api.certificates certificatesCall?.enqueue(object : Callback { - - override fun onResponse(response: Response?, retrofit: Retrofit?) { - if (response?.isSuccess ?: false) { + override fun onResponse(call: Call?, response: Response?) { + if (response?.isSuccessful ?: false) { if (certificateViewItemList == null) { certificateViewItemList = ArrayList() } @@ -100,12 +99,13 @@ class CertificatePresenter(val api: IApi, val baseUrl = config.baseUrl coursesCall = api.getCourses(1, courseIds) coursesCall?.enqueue(object : Callback { - override fun onFailure(t: Throwable?) { + + override fun onFailure(call: Call?, t: Throwable?) { view?.onInternetProblem() } - override fun onResponse(response: Response?, retrofit: Retrofit?) { - if (response?.isSuccess ?: false) { + override fun onResponse(call: Call?, response: Response?) { + if (response?.isSuccessful ?: false) { val localCertificateViewItems: List = response ?.body() ?.courses @@ -146,7 +146,7 @@ class CertificatePresenter(val api: IApi, } } - override fun onFailure(t: Throwable?) { + override fun onFailure(call: Call?, t: Throwable?) { view?.onInternetProblem() } diff --git a/app/src/main/java/org/stepic/droid/core/presenters/CourseFinderPresenter.kt b/app/src/main/java/org/stepic/droid/core/presenters/CourseFinderPresenter.kt index cc03106df5..037f06e8fa 100644 --- a/app/src/main/java/org/stepic/droid/core/presenters/CourseFinderPresenter.kt +++ b/app/src/main/java/org/stepic/droid/core/presenters/CourseFinderPresenter.kt @@ -9,9 +9,9 @@ import org.stepic.droid.store.operations.DatabaseFacade import org.stepic.droid.store.operations.Table import org.stepic.droid.web.CoursesStepicResponse import org.stepic.droid.web.IApi -import retrofit.Callback -import retrofit.Response -import retrofit.Retrofit +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response import java.util.concurrent.ThreadPoolExecutor class CourseFinderPresenter( @@ -34,8 +34,9 @@ class CourseFinderPresenter( } } else { api.getCourse(courseId).enqueue(object : Callback { - override fun onResponse(response: Response, retrofit: Retrofit) { - if (response.isSuccess && !response.body().courses.isEmpty()) { + + override fun onResponse(call: Call?, response: Response?) { + if (response != null && response.isSuccessful && !response.body().courses.isEmpty()) { view?.onCourseFound(CourseFoundEvent(response.body().courses[0])) } else { view?.onCourseUnavailable(CourseUnavailableForUserEvent(courseId)) @@ -43,7 +44,7 @@ class CourseFinderPresenter( } } - override fun onFailure(t: Throwable) { + override fun onFailure(call: Call?, t: Throwable?) { view!!.onInternetFailWhenCourseIsTriedToLoad(CourseCantLoadEvent()) } }) diff --git a/app/src/main/java/org/stepic/droid/core/presenters/CourseJoinerPresenter.kt b/app/src/main/java/org/stepic/droid/core/presenters/CourseJoinerPresenter.kt index af8c27456c..1b46532e71 100644 --- a/app/src/main/java/org/stepic/droid/core/presenters/CourseJoinerPresenter.kt +++ b/app/src/main/java/org/stepic/droid/core/presenters/CourseJoinerPresenter.kt @@ -12,9 +12,9 @@ import org.stepic.droid.preferences.SharedPreferenceHelper import org.stepic.droid.store.operations.DatabaseFacade import org.stepic.droid.store.operations.Table import org.stepic.droid.web.IApi -import retrofit.Callback -import retrofit.Response -import retrofit.Retrofit +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response import java.net.HttpURLConnection import java.util.concurrent.ThreadPoolExecutor @@ -34,11 +34,11 @@ class CourseJoinerPresenter( view?.setEnabledJoinButton(false) api.tryJoinCourse(course).enqueue(object : Callback { - private val localCourseCopy = course - override fun onResponse(response: Response, retrofit: Retrofit) { - if (response.isSuccess) { + private val localCourseCopy = course + override fun onResponse(call: Call?, response: Response?) { + if (response?.isSuccessful ?: false) { localCourseCopy.enrollment = localCourseCopy.courseId.toInt() threadPoolExecutor.execute { @@ -61,11 +61,11 @@ class CourseJoinerPresenter( bus.post(SuccessJoinEvent(localCourseCopy)) //todo remake without bus view?.onSuccessJoin(SuccessJoinEvent(localCourseCopy)) } else { - view?.onFailJoin(FailJoinEvent(response.code())) + view?.onFailJoin(FailJoinEvent(response?.code() ?: 0)) } } - override fun onFailure(t: Throwable) { + override fun onFailure(call: Call?, t: Throwable?) { view?.onFailJoin(FailJoinEvent()) } }) diff --git a/app/src/main/java/org/stepic/droid/core/presenters/NotificationListPresenter.kt b/app/src/main/java/org/stepic/droid/core/presenters/NotificationListPresenter.kt index 4c25da3a2e..c9c436f1ac 100644 --- a/app/src/main/java/org/stepic/droid/core/presenters/NotificationListPresenter.kt +++ b/app/src/main/java/org/stepic/droid/core/presenters/NotificationListPresenter.kt @@ -165,7 +165,7 @@ class NotificationListPresenter( fun markAsRead(id: Long) { threadPoolExecutor.execute { try { - val isSuccess = api.setReadStatusForNotification(id, true).execute().isSuccess + val isSuccess = api.setReadStatusForNotification(id, true).execute().isSuccessful if (isSuccess) { mainHandler.post { bus.post(NotificationCheckedSuccessfullyEvent(id)) @@ -218,7 +218,7 @@ class NotificationListPresenter( threadPoolExecutor.execute { try { val response = api.markAsReadAllType(notificationCategoryLocal).execute() - if (response.isSuccess) { + if (response.isSuccessful) { notificationList.forEach { it.is_unread = false } diff --git a/app/src/main/java/org/stepic/droid/core/presenters/PersistentCourseListPresenter.kt b/app/src/main/java/org/stepic/droid/core/presenters/PersistentCourseListPresenter.kt index d1f56d203b..2f0a781f2a 100644 --- a/app/src/main/java/org/stepic/droid/core/presenters/PersistentCourseListPresenter.kt +++ b/app/src/main/java/org/stepic/droid/core/presenters/PersistentCourseListPresenter.kt @@ -14,7 +14,7 @@ import org.stepic.droid.store.operations.Table import org.stepic.droid.util.RWLocks import org.stepic.droid.web.CoursesStepicResponse import org.stepic.droid.web.IApi -import retrofit.Response +import retrofit2.Response import java.util.* import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.atomic.AtomicBoolean @@ -79,7 +79,7 @@ class PersistentCourseListPresenter( null } - if (response != null && response.isSuccess) { + if (response != null && response.isSuccessful) { val coursesFromInternet = response.body().courses try { diff --git a/app/src/main/java/org/stepic/droid/core/presenters/SectionsPresenter.kt b/app/src/main/java/org/stepic/droid/core/presenters/SectionsPresenter.kt index ed0c6102f8..1a2b13d45a 100644 --- a/app/src/main/java/org/stepic/droid/core/presenters/SectionsPresenter.kt +++ b/app/src/main/java/org/stepic/droid/core/presenters/SectionsPresenter.kt @@ -9,9 +9,9 @@ import org.stepic.droid.model.Progress import org.stepic.droid.model.Section import org.stepic.droid.store.operations.DatabaseFacade import org.stepic.droid.transformers.transformToViewModel +import org.stepic.droid.viewmodel.ProgressViewModel import org.stepic.droid.web.IApi import timber.log.Timber -import org.stepic.droid.viewmodel.ProgressViewModel import java.util.* import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.atomic.AtomicBoolean @@ -79,7 +79,7 @@ class SectionsPresenter(val threadPoolExecutor: ThreadPoolExecutor, //get from Internet try { val response = api.getSections(sectionIds).execute() - if (response.isSuccess || response.body()?.sections?.isNotEmpty() ?: false) { + if (response.isSuccessful || response.body()?.sections?.isNotEmpty() ?: false) { val sections = response.body().sections val cachedSections: Map = databaseFacade .getAllSectionsOfCourse(course) diff --git a/app/src/main/java/org/stepic/droid/core/presenters/StepAttemptPresenter.kt b/app/src/main/java/org/stepic/droid/core/presenters/StepAttemptPresenter.kt index 85ce3242b9..4621df024b 100644 --- a/app/src/main/java/org/stepic/droid/core/presenters/StepAttemptPresenter.kt +++ b/app/src/main/java/org/stepic/droid/core/presenters/StepAttemptPresenter.kt @@ -123,7 +123,7 @@ class StepAttemptPresenter(val mainHandler: IMainHandler, Runnable { try { val submissionsResponse = api.getSubmissions(attemptId).execute() - if (submissionsResponse.isSuccess) { + if (submissionsResponse.isSuccessful) { val submission = submissionsResponse.body().submissions.firstOrNull() // if null -> we do not have submissions for THIS ATTEMPT @@ -209,7 +209,7 @@ class StepAttemptPresenter(val mainHandler: IMainHandler, private fun getExistingAttempts(stepId: Long) { try { val existingAttemptsResponse = api.getExistingAttempts(stepId).execute() - if (existingAttemptsResponse.isSuccess) { + if (existingAttemptsResponse.isSuccessful) { val body = existingAttemptsResponse.body() if (body == null) { createNewAttempt(stepId) diff --git a/app/src/main/java/org/stepic/droid/core/presenters/StepsPresenter.kt b/app/src/main/java/org/stepic/droid/core/presenters/StepsPresenter.kt index 3c334e16a2..d0b36d6d47 100644 --- a/app/src/main/java/org/stepic/droid/core/presenters/StepsPresenter.kt +++ b/app/src/main/java/org/stepic/droid/core/presenters/StepsPresenter.kt @@ -12,7 +12,7 @@ import org.stepic.droid.util.ProgressUtil import org.stepic.droid.web.IApi import org.stepic.droid.web.LessonStepicResponse import org.stepic.droid.web.StepResponse -import retrofit.Response +import retrofit2.Response import java.util.* import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.atomic.AtomicBoolean diff --git a/app/src/main/java/org/stepic/droid/events/instructors/OnResponseLoadingInstructorsEvent.java b/app/src/main/java/org/stepic/droid/events/instructors/OnResponseLoadingInstructorsEvent.java index c008b76577..f20ca663ff 100644 --- a/app/src/main/java/org/stepic/droid/events/instructors/OnResponseLoadingInstructorsEvent.java +++ b/app/src/main/java/org/stepic/droid/events/instructors/OnResponseLoadingInstructorsEvent.java @@ -3,24 +3,18 @@ import org.stepic.droid.model.Course; import org.stepic.droid.web.UserStepicResponse; -import retrofit.Response; -import retrofit.Retrofit; +import retrofit2.Response; public class OnResponseLoadingInstructorsEvent extends InstructorsBaseEvent { private final Response response; - private final Retrofit retrofit; - public OnResponseLoadingInstructorsEvent(Course mCourse, Response response, Retrofit retrofit) { - super(mCourse); + public OnResponseLoadingInstructorsEvent(Course course, Response response) { + super(course); this.response = response; - this.retrofit = retrofit; } public Response getResponse() { return response; } - public Retrofit getRetrofit() { - return retrofit; - } } diff --git a/app/src/main/java/org/stepic/droid/notifications/StepicInstanceIdService.kt b/app/src/main/java/org/stepic/droid/notifications/StepicInstanceIdService.kt index 9adbed50fe..23c059ecaf 100644 --- a/app/src/main/java/org/stepic/droid/notifications/StepicInstanceIdService.kt +++ b/app/src/main/java/org/stepic/droid/notifications/StepicInstanceIdService.kt @@ -24,7 +24,7 @@ class StepicInstanceIdService : FirebaseInstanceIdService() { val authTokenStepik : AuthenticationStepicResponse = sharedPreferences.authResponseFromStore!! //for logged user only work val token = tokenNullable!! val response = api.registerDevice(token).execute() - if (!response.isSuccess && response.code() != 400) { //400 -- device already registered + if (!response.isSuccessful && response.code() != 400) { //400 -- device already registered throw Exception("response was failed. it is ok. code: " + response.code()) } sharedPreferences.setIsGcmTokenOk(true) diff --git a/app/src/main/java/org/stepic/droid/receivers/InternetConnectionEnabledReceiver.java b/app/src/main/java/org/stepic/droid/receivers/InternetConnectionEnabledReceiver.java index e3b00da06c..38a0629ea9 100644 --- a/app/src/main/java/org/stepic/droid/receivers/InternetConnectionEnabledReceiver.java +++ b/app/src/main/java/org/stepic/droid/receivers/InternetConnectionEnabledReceiver.java @@ -82,8 +82,8 @@ public void run() { List list = databaseFacade.getAllInQueue(); for (ViewAssignment item : list) { try { - retrofit.Response response = api.postViewed(item).execute(); - if (response.isSuccess()) { + retrofit2.Response response = api.postViewed(item).execute(); + if (response.isSuccessful()) { databaseFacade.removeFromQueue(item); Step step = databaseFacade.getStepById(item.getStep()); if (step != null) { diff --git a/app/src/main/java/org/stepic/droid/services/LoadService.java b/app/src/main/java/org/stepic/droid/services/LoadService.java index 5d6f79c5fa..0fa140da37 100644 --- a/app/src/main/java/org/stepic/droid/services/LoadService.java +++ b/app/src/main/java/org/stepic/droid/services/LoadService.java @@ -46,7 +46,7 @@ import javax.inject.Inject; -import retrofit.Response; +import retrofit2.Response; public class LoadService extends IntentService { @@ -250,7 +250,7 @@ private void addUnitLesson(Unit unitOut, Lesson lessonOut) { databaseFacade.addProgress(item); } Response response = api.getSteps(lesson.getSteps()).execute(); - if (response.isSuccess()) { + if (response.isSuccessful()) { List steps = response.body().getSteps(); if (steps != null && !steps.isEmpty()) { @@ -313,7 +313,7 @@ private void addSection(Section sectionOut) { int lastExclusive = Math.min(unitIds.length, pointer + AppConstants.DEFAULT_NUMBER_IDS_IN_QUERY); long[] subArrayForLoading = Arrays.copyOfRange(unitIds, pointer, lastExclusive); Response unitResponse = api.getUnits(subArrayForLoading).execute(); - if (!unitResponse.isSuccess()) { + if (!unitResponse.isSuccessful()) { responseIsSuccess = false; } else { units.addAll(unitResponse.body().getUnits()); @@ -340,7 +340,7 @@ private void addSection(Section sectionOut) { int lastExclusive = Math.min(lessonsIds.length, pointer + AppConstants.DEFAULT_NUMBER_IDS_IN_QUERY); long[] subArrayForLoading = Arrays.copyOfRange(lessonsIds, pointer, lastExclusive); Response lessonResponse = api.getLessons(subArrayForLoading).execute(); - if (!lessonResponse.isSuccess()) { + if (!lessonResponse.isSuccessful()) { responseIsSuccess = false; } else { lessons.addAll(lessonResponse.body().getLessons()); @@ -444,7 +444,7 @@ private List fetchProgresses(String[] ids) throws IOException { int lastExclusive = Math.min(ids.length, pointer + AppConstants.DEFAULT_NUMBER_IDS_IN_QUERY); String[] subArrayForLoading = Arrays.copyOfRange(ids, pointer, lastExclusive); Response progressesResponse = api.getProgresses(subArrayForLoading).execute(); - if (!progressesResponse.isSuccess()) { + if (!progressesResponse.isSuccessful()) { responseIsSuccess = false; } else { progresses.addAll(progressesResponse.body().getProgresses()); diff --git a/app/src/main/java/org/stepic/droid/services/ViewPusher.java b/app/src/main/java/org/stepic/droid/services/ViewPusher.java index 8b7d695847..2c093364e6 100644 --- a/app/src/main/java/org/stepic/droid/services/ViewPusher.java +++ b/app/src/main/java/org/stepic/droid/services/ViewPusher.java @@ -26,7 +26,7 @@ import kotlin.Unit; import kotlin.jvm.functions.Function0; -import retrofit.Response; +import retrofit2.Response; public class ViewPusher extends IntentService { @@ -80,7 +80,7 @@ protected void onHandleIntent(Intent intent) { try { Response response = api.postViewed(new ViewAssignment(assignmentId, stepId)).execute(); - if (!response.isSuccess()) { + if (!response.isSuccessful()) { throw new IOException("response is not success"); } } catch (IOException e) { diff --git a/app/src/main/java/org/stepic/droid/ui/activities/RegisterActivity.java b/app/src/main/java/org/stepic/droid/ui/activities/RegisterActivity.java index bfb2c23462..f1e4e6e69a 100644 --- a/app/src/main/java/org/stepic/droid/ui/activities/RegisterActivity.java +++ b/app/src/main/java/org/stepic/droid/ui/activities/RegisterActivity.java @@ -14,7 +14,6 @@ import android.widget.Toast; import com.google.firebase.analytics.FirebaseAnalytics; -import com.squareup.okhttp.ResponseBody; import org.jetbrains.annotations.Nullable; import org.stepic.droid.R; @@ -28,14 +27,15 @@ import java.lang.annotation.Annotation; -import butterknife.BindView; import butterknife.BindString; +import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnFocusChange; -import retrofit.Callback; -import retrofit.Converter; -import retrofit.Response; -import retrofit.Retrofit; +import okhttp3.ResponseBody; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Converter; +import retrofit2.Response; public class RegisterActivity extends FragmentActivityBase { @@ -178,9 +178,9 @@ private void createAccount() { shell.getApi().signUp(firstName, lastName, email, password).enqueue(new Callback() { @Override - public void onResponse(Response response, Retrofit retrofit) { + public void onResponse(Call call, Response response) { ProgressHelper.dismiss(progress); - if (response.isSuccess()) { + if (response.isSuccessful()) { analytic.reportEvent(FirebaseAnalytics.Event.SIGN_UP); loginManager.login(email, password, new ProgressHandler() { @Override @@ -200,8 +200,9 @@ public void onFinish() { } }, getCourseFromExtra()); } else { + response.errorBody(); Converter errorConverter = - retrofit.responseConverter(RegistrationResponse.class, new Annotation[0]); + retrofit.responseBodyConverter(RegistrationResponse.class, new Annotation[0]); RegistrationResponse error = null; try { error = errorConverter.convert(response.errorBody()); @@ -214,7 +215,7 @@ public void onFinish() { } @Override - public void onFailure(Throwable t) { + public void onFailure(Call call, Throwable t) { ProgressHelper.dismiss(progress); Toast.makeText(RegisterActivity.this, R.string.connectionProblems, Toast.LENGTH_SHORT).show(); } diff --git a/app/src/main/java/org/stepic/droid/ui/activities/UnitsActivity.java b/app/src/main/java/org/stepic/droid/ui/activities/UnitsActivity.java index 45d7745299..18565532aa 100644 --- a/app/src/main/java/org/stepic/droid/ui/activities/UnitsActivity.java +++ b/app/src/main/java/org/stepic/droid/ui/activities/UnitsActivity.java @@ -55,7 +55,7 @@ import butterknife.BindView; import butterknife.ButterKnife; import kotlin.jvm.functions.Function0; -import retrofit.Response; +import retrofit2.Response; public class UnitsActivity extends FragmentActivityBase implements SwipeRefreshLayout.OnRefreshListener { @@ -155,7 +155,7 @@ public void run() { int lastExclusive = Math.min(unitIds.length, pointer + AppConstants.DEFAULT_NUMBER_IDS_IN_QUERY); long[] subArrayForLoading = Arrays.copyOfRange(unitIds, pointer, lastExclusive); Response unitResponse = shell.getApi().getUnits(subArrayForLoading).execute(); - if (!unitResponse.isSuccess()) { + if (!unitResponse.isSuccessful()) { responseIsSuccess = false; } else { backgroundUnits.addAll(unitResponse.body().getUnits()); @@ -231,7 +231,7 @@ public void run() { int lastExclusive = Math.min(lessonsIds.length, pointer + AppConstants.DEFAULT_NUMBER_IDS_IN_QUERY); long[] subArrayForLoading = Arrays.copyOfRange(lessonsIds, pointer, lastExclusive); Response lessonsResponse = shell.getApi().getLessons(subArrayForLoading).execute(); - if (!lessonsResponse.isSuccess()) { + if (!lessonsResponse.isSuccessful()) { responseIsSuccess = false; } else { backgroundLessons.addAll(lessonsResponse.body().getLessons()); @@ -294,7 +294,7 @@ public void run() { int lastExclusive = Math.min(progressIds.length, pointer + AppConstants.DEFAULT_NUMBER_IDS_IN_QUERY); String[] subArrayForLoading = Arrays.copyOfRange(progressIds, pointer, lastExclusive); Response progressesResponse = shell.getApi().getProgresses(subArrayForLoading).execute(); - if (!progressesResponse.isSuccess()) { + if (!progressesResponse.isSuccessful()) { responseIsSuccess = false; } else { backgroundProgress.addAll(progressesResponse.body().getProgresses()); diff --git a/app/src/main/java/org/stepic/droid/ui/dialogs/DeleteCommentDialogFragment.kt b/app/src/main/java/org/stepic/droid/ui/dialogs/DeleteCommentDialogFragment.kt index ab27465dd9..cddf4b9484 100644 --- a/app/src/main/java/org/stepic/droid/ui/dialogs/DeleteCommentDialogFragment.kt +++ b/app/src/main/java/org/stepic/droid/ui/dialogs/DeleteCommentDialogFragment.kt @@ -12,12 +12,11 @@ import org.stepic.droid.events.comments.FailDeleteCommentEvent import org.stepic.droid.events.comments.InternetConnectionProblemInCommentsEvent import org.stepic.droid.events.comments.NewCommentWasAddedOrUpdateEvent import org.stepic.droid.util.ProgressHelper -import org.stepic.droid.ui.dialogs.LoadingProgressDialog import org.stepic.droid.web.CommentsResponse import org.stepic.droid.web.IApi -import retrofit.Callback -import retrofit.Response -import retrofit.Retrofit +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response import javax.inject.Inject class DeleteCommentDialogFragment : DialogFragment() { @@ -29,7 +28,7 @@ class DeleteCommentDialogFragment : DialogFragment() { lateinit var bus: Bus; @Inject - lateinit var analytic : Analytic + lateinit var analytic: Analytic companion object { private val COMMENT_ID_KEY = "comment_id_key" @@ -55,9 +54,10 @@ class DeleteCommentDialogFragment : DialogFragment() { ProgressHelper.activate(loadingProgressDialog) analytic.reportEvent(Analytic.Comments.DELETE_COMMENT_CONFIRMATION) api.deleteComment(commentId).enqueue(object : Callback { - override fun onResponse(response: Response?, retrofit: Retrofit?) { + + override fun onResponse(call: Call?, response: Response?) { ProgressHelper.dismiss(loadingProgressDialog) - if (response?.isSuccess ?: false) { + if (response?.isSuccessful ?: false) { val comment = response?.body()?.comments?.firstOrNull() comment?.let { bus.post(NewCommentWasAddedOrUpdateEvent(it.target!!, it)) @@ -67,7 +67,7 @@ class DeleteCommentDialogFragment : DialogFragment() { } } - override fun onFailure(t: Throwable?) { + override fun onFailure(call: Call?, t: Throwable?) { ProgressHelper.dismiss(loadingProgressDialog) bus.post(InternetConnectionProblemInCommentsEvent(null)) } diff --git a/app/src/main/java/org/stepic/droid/ui/dialogs/RemindPasswordDialogFragment.java b/app/src/main/java/org/stepic/droid/ui/dialogs/RemindPasswordDialogFragment.java index 5a6f43f6e5..8962dbd04d 100644 --- a/app/src/main/java/org/stepic/droid/ui/dialogs/RemindPasswordDialogFragment.java +++ b/app/src/main/java/org/stepic/droid/ui/dialogs/RemindPasswordDialogFragment.java @@ -27,9 +27,9 @@ import butterknife.BindString; import butterknife.ButterKnife; -import retrofit.Callback; -import retrofit.Response; -import retrofit.Retrofit; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; public class RemindPasswordDialogFragment extends DialogFragment { @@ -139,9 +139,9 @@ private void sendEmail(final AlertDialog alertDialog) { if (!email.isEmpty()) { api.remindPassword(email).enqueue(new Callback() { @Override - public void onResponse(Response response, Retrofit retrofit) { + public void onResponse(Call call, Response response) { ProgressHelper.dismiss(progressLogin); - com.squareup.okhttp.Response rawResponse = response.raw(); + okhttp3.Response rawResponse = response.raw(); if (rawResponse.priorResponse() != null && rawResponse.priorResponse().code() == 302) { alertDialog.dismiss(); Toast.makeText(getContext(), R.string.email_sent, Toast.LENGTH_SHORT).show(); @@ -159,7 +159,7 @@ public void onResponse(Response response, Retrofit retrofit) { } @Override - public void onFailure(Throwable t) { + public void onFailure(Call call, Throwable t) { ProgressHelper.dismiss(progressLogin); final Context context = getContext(); diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/CommentsFragment.kt b/app/src/main/java/org/stepic/droid/ui/fragments/CommentsFragment.kt index 7f83938c09..84d9738ea9 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/CommentsFragment.kt +++ b/app/src/main/java/org/stepic/droid/ui/fragments/CommentsFragment.kt @@ -38,9 +38,10 @@ import org.stepic.droid.util.StringUtil import org.stepic.droid.util.getFirstAndLastName import org.stepic.droid.web.DiscussionProxyResponse import org.stepic.droid.web.VoteResponse -import retrofit.Callback -import retrofit.Response -import retrofit.Retrofit +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import retrofit2.Retrofit import java.util.* import javax.inject.Inject @@ -339,16 +340,16 @@ class CommentsFragment : FragmentBase(), SwipeRefreshLayout.OnRefreshListener { voteId?.let { val voteObject = Vote(voteId, voteValue) shell.api.makeVote(it, voteValue).enqueue(object : Callback { - override fun onResponse(response: Response?, retrofit: Retrofit?) { + override fun onResponse(call: Call?, response: Response?) { //todo event for update - if (response?.isSuccess ?: false) { + if (response?.isSuccessful ?: false) { bus.post(LikeCommentSuccessEvent(commentId, voteObject)) } else { bus.post(LikeCommentFailEvent()) } } - override fun onFailure(t: Throwable?) { + override fun onFailure(call: Call?, t: Throwable?) { //todo event for fail bus.post(LikeCommentFailEvent()) } @@ -413,8 +414,8 @@ class CommentsFragment : FragmentBase(), SwipeRefreshLayout.OnRefreshListener { private fun loadDiscussionProxyById(id: String = discussionId) { shell.api.getDiscussionProxies(id).enqueue(object : Callback { - override fun onResponse(response: Response?, retrofit: Retrofit?) { - if (response != null && response.isSuccess) { + override fun onResponse(call: Call?, response: Response?) { + if (response != null && response.isSuccessful) { val discussionProxy = response.body().discussionProxies.firstOrNull() if (discussionProxy != null && discussionProxy.discussions.isNotEmpty()) { bus.post(DiscussionProxyLoadedSuccessfullyEvent(discussionProxy)) @@ -426,7 +427,7 @@ class CommentsFragment : FragmentBase(), SwipeRefreshLayout.OnRefreshListener { } } - override fun onFailure(t: Throwable?) { + override fun onFailure(call: Call?, t: Throwable?) { bus.post(InternetConnectionProblemInCommentsEvent(discussionId)) } diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/CourseDetailFragment.java b/app/src/main/java/org/stepic/droid/ui/fragments/CourseDetailFragment.java index 3b31515b14..6b35d97dfd 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/CourseDetailFragment.java +++ b/app/src/main/java/org/stepic/droid/ui/fragments/CourseDetailFragment.java @@ -83,9 +83,9 @@ import butterknife.BindString; import butterknife.BindView; import butterknife.ButterKnife; -import retrofit.Callback; -import retrofit.Response; -import retrofit.Retrofit; +import retrofit2.Call; +import retrofit2.Callback; +import retrofit2.Response; public class CourseDetailFragment extends FragmentBase implements LoadCourseView, CourseJoinView { @@ -417,12 +417,12 @@ private void fetchInstructors() { bus.post(new StartLoadingInstructorsEvent(course)); shell.getApi().getUsers(course.getInstructors()).enqueue(new Callback() { @Override - public void onResponse(Response response, Retrofit retrofit) { - if (response.isSuccess()) { + public void onResponse(Call call, Response response) { + if (response.isSuccessful()) { if (response.body() == null) { bus.post(new FailureLoadInstructorsEvent(course, null)); } else { - bus.post(new OnResponseLoadingInstructorsEvent(course, response, retrofit)); + bus.post(new OnResponseLoadingInstructorsEvent(course, response)); } } else { bus.post(new FailureLoadInstructorsEvent(course, null)); @@ -430,7 +430,7 @@ public void onResponse(Response response, Retrofit retrofit) } @Override - public void onFailure(Throwable t) { + public void onFailure(Call call, Throwable t) { bus.post(new FailureLoadInstructorsEvent(course, t)); } }); diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/NewCommentFragment.kt b/app/src/main/java/org/stepic/droid/ui/fragments/NewCommentFragment.kt index 7640c84cdf..3878f402bf 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/NewCommentFragment.kt +++ b/app/src/main/java/org/stepic/droid/ui/fragments/NewCommentFragment.kt @@ -23,9 +23,10 @@ import org.stepic.droid.ui.util.BackButtonHandler import org.stepic.droid.ui.util.OnBackClickListener import org.stepic.droid.util.ProgressHelper import org.stepic.droid.web.CommentsResponse -import retrofit.Callback -import retrofit.Response -import retrofit.Retrofit +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response +import retrofit2.Retrofit class NewCommentFragment : FragmentBase(), OnBackClickListener { @@ -167,8 +168,8 @@ class NewCommentFragment : FragmentBase(), OnBackClickListener { shell.api.postComment(text, target!!, parent).enqueue(object : Callback { - override fun onResponse(response: Response?, retrofit: Retrofit?) { - if (response?.isSuccess ?: false && response?.body()?.comments != null) { + override fun onResponse(call: Call?, response: Response?) { + if (response?.isSuccessful ?: false && response?.body()?.comments != null) { analytic.reportEvent(Analytic.Comments.COMMENTS_SENT_SUCCESSFULLY) val newComment = response?.body()?.comments?.firstOrNull() bus.post(NewCommentWasAddedOrUpdateEvent(targetId = target!!, newCommentInsertOrUpdate = newComment)) @@ -181,7 +182,7 @@ class NewCommentFragment : FragmentBase(), OnBackClickListener { } } - override fun onFailure(t: Throwable?) { + override fun onFailure(call: Call?, t: Throwable?) { Toast.makeText(MainApplication.getAppContext(), R.string.connectionProblems, Toast.LENGTH_LONG).show() onFinishTryingSending() } diff --git a/app/src/main/java/org/stepic/droid/ui/fragments/TextFeedbackFragment.kt b/app/src/main/java/org/stepic/droid/ui/fragments/TextFeedbackFragment.kt index 0983d9b295..29f2ca0f9a 100644 --- a/app/src/main/java/org/stepic/droid/ui/fragments/TextFeedbackFragment.kt +++ b/app/src/main/java/org/stepic/droid/ui/fragments/TextFeedbackFragment.kt @@ -20,9 +20,9 @@ import org.stepic.droid.events.feedback.FeedbackSentEvent import org.stepic.droid.ui.dialogs.LoadingProgressDialog import org.stepic.droid.util.ProgressHelper import org.stepic.droid.util.ValidatorUtil -import retrofit.Callback -import retrofit.Response -import retrofit.Retrofit +import retrofit2.Call +import retrofit2.Callback +import retrofit2.Response class TextFeedbackFragment : FragmentBase() { @@ -150,9 +150,9 @@ class TextFeedbackFragment : FragmentBase() { ProgressHelper.activate(progressDialog) shell.api.sendFeedback(email, description).enqueue(object : Callback { - override fun onResponse(response: Response?, retrofit: Retrofit?) { + override fun onResponse(call: Call?, response: Response?) { ProgressHelper.dismiss(progressDialog) - if (response?.isSuccess ?: false) { + if (response?.isSuccessful ?: false) { bus.post(FeedbackSentEvent()) } else { @@ -160,7 +160,7 @@ class TextFeedbackFragment : FragmentBase() { } } - override fun onFailure(throwable: Throwable?) { + override fun onFailure(call: Call?, t: Throwable?) { ProgressHelper.dismiss(progressDialog) bus.post(FeedbackInternetProblemsEvent()) } diff --git a/app/src/main/java/org/stepic/droid/web/IApi.java b/app/src/main/java/org/stepic/droid/web/IApi.java index 77c964e872..b43f67bd15 100644 --- a/app/src/main/java/org/stepic/droid/web/IApi.java +++ b/app/src/main/java/org/stepic/droid/web/IApi.java @@ -13,7 +13,7 @@ import java.io.IOException; -import retrofit.Call; +import retrofit2.Call; public interface IApi { diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index 8d6172146f..d26928c320 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -13,13 +13,6 @@ import com.google.firebase.analytics.FirebaseAnalytics; import com.google.gson.Gson; import com.google.gson.GsonBuilder; -import com.squareup.okhttp.Credentials; -import com.squareup.okhttp.Headers; -import com.squareup.okhttp.HttpUrl; -import com.squareup.okhttp.Interceptor; -import com.squareup.okhttp.OkHttpClient; -import com.squareup.okhttp.Request; -import com.squareup.okhttp.Response; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -51,7 +44,6 @@ import org.stepic.droid.util.AppConstants; import org.stepic.droid.util.DeviceInfoUtil; import org.stepic.droid.util.RWLocks; -import org.stepic.droid.web.util.StringConverterFactory; import java.io.IOException; import java.net.HttpCookie; @@ -65,10 +57,17 @@ import javax.inject.Inject; import javax.inject.Singleton; -import retrofit.Call; -import retrofit.Converter; -import retrofit.GsonConverterFactory; -import retrofit.Retrofit; +import okhttp3.Credentials; +import okhttp3.Headers; +import okhttp3.HttpUrl; +import okhttp3.Interceptor; +import okhttp3.OkHttpClient; +import okhttp3.Request; +import okhttp3.Response; +import retrofit2.Call; +import retrofit2.Converter; +import retrofit2.Retrofit; +import retrofit2.converter.gson.GsonConverterFactory; import timber.log.Timber; @Singleton @@ -93,7 +92,6 @@ public class RetrofitRESTApi implements IApi { private StepicRestLoggedService loggedService; private StepicRestOAuthService oAuthService; private StepicEmptyAuthService stepikEmptyAuthService; - private final OkHttpClient okHttpClient = new OkHttpClient(); public RetrofitRESTApi() { @@ -102,12 +100,12 @@ public RetrofitRESTApi() { makeOauthServiceWithNewAuthHeader(sharedPreference.isLastTokenSocial() ? TokenType.social : TokenType.loginPassword); makeLoggedService(); - OkHttpClient okHttpClient = new OkHttpClient(); + OkHttpClient.Builder okHttpClient = new OkHttpClient.Builder(); setTimeout(okHttpClient, TIMEOUT_IN_SECONDS); Retrofit retrofit = new Retrofit.Builder() .baseUrl(config.getBaseUrl()) .addConverterFactory(generateGsonFactory()) - .client(okHttpClient) + .client(okHttpClient.build()) .build(); stepikEmptyAuthService = retrofit.create(StepicEmptyAuthService.class); try { @@ -120,7 +118,7 @@ public RetrofitRESTApi() { } private void makeLoggedService() { - OkHttpClient okHttpClient = new OkHttpClient(); + OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder(); Interceptor interceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { @@ -153,7 +151,7 @@ public Response intercept(Chain chain) throws IOException { .build(); } } else if (isNeededUpdate(response)) { - retrofit.Response authenticationStepicResponse; + retrofit2.Response authenticationStepicResponse; try { authenticationStepicResponse = oAuthService.updateToken(config.getRefreshGrantType(), response.getRefresh_token()).execute(); response = authenticationStepicResponse.body(); @@ -175,7 +173,7 @@ public Response intercept(Chain chain) throws IOException { String extendedMessage = ""; if (authenticationStepicResponse == null) { extendedMessage = "rawResponse was null"; - } else if (authenticationStepicResponse.isSuccess()) { + } else if (authenticationStepicResponse.isSuccessful()) { extendedMessage = "was success " + authenticationStepicResponse.code(); } else { try { @@ -214,8 +212,9 @@ public Response intercept(Chain chain) throws IOException { } }; - okHttpClient.networkInterceptors().add(interceptor); - setTimeout(okHttpClient, TIMEOUT_IN_SECONDS); + okHttpBuilder.addNetworkInterceptor(interceptor); + setTimeout(okHttpBuilder, TIMEOUT_IN_SECONDS); + OkHttpClient okHttpClient = okHttpBuilder.build(); Retrofit retrofit = new Retrofit.Builder() .baseUrl(config.getBaseUrl()) .addConverterFactory(generateGsonFactory()) @@ -235,13 +234,13 @@ public Response intercept(Chain chain) throws IOException { return chain.proceed(newRequest); } }; - OkHttpClient okHttpClient = new OkHttpClient(); - setTimeout(okHttpClient, TIMEOUT_IN_SECONDS); - okHttpClient.networkInterceptors().add(interceptor); + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + setTimeout(builder, TIMEOUT_IN_SECONDS); + builder.addNetworkInterceptor(interceptor); Retrofit notLogged = new Retrofit.Builder() .baseUrl(config.getBaseUrl()) .addConverterFactory(generateGsonFactory()) - .client(okHttpClient) + .client(builder.build()) .build(); oAuthService = notLogged.create(StepicRestOAuthService.class); } @@ -256,9 +255,9 @@ private Converter.Factory generateGsonFactory() { return GsonConverterFactory.create(gson); } - private void setTimeout(OkHttpClient okHttpClient, int seconds) { - okHttpClient.setConnectTimeout(seconds, TimeUnit.SECONDS); - okHttpClient.setReadTimeout(seconds, TimeUnit.SECONDS); + private void setTimeout(OkHttpClient.Builder builder, int seconds) { + builder.connectTimeout(seconds, TimeUnit.SECONDS); + builder.readTimeout(seconds, TimeUnit.SECONDS); } @Override @@ -292,7 +291,7 @@ public Call authWithCode(String code) { public Call signUp(String firstName, String lastName, String email, String password) { analytic.reportEvent(Analytic.Web.TRY_REGISTER); - OkHttpClient okHttpClient = new OkHttpClient(); + Interceptor interceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { @@ -318,11 +317,13 @@ public Response intercept(Chain chain) throws IOException { return chain.proceed(newRequest); } }; - okHttpClient.networkInterceptors().add(interceptor); + OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder(); + okHttpClientBuilder.addNetworkInterceptor(interceptor); + setTimeout(okHttpClientBuilder, TIMEOUT_IN_SECONDS); Retrofit notLogged = new Retrofit.Builder() .baseUrl(config.getBaseUrl()) .addConverterFactory(generateGsonFactory()) - .client(okHttpClient) + .client(okHttpClientBuilder.build()) .build(); StepicRestOAuthService tempService = notLogged.create(StepicRestOAuthService.class); return tempService.createAccount(new UserRegistrationRequest(new RegistrationUser(firstName, lastName, email, password))); @@ -492,7 +493,7 @@ public Call getSubmissionForStep(long stepId) { public Call remindPassword(String email) { String encodedEmail = URLEncoder.encode(email); - OkHttpClient okHttpClient = new OkHttpClient(); + Interceptor interceptor = new Interceptor() { @Override public Response intercept(Chain chain) throws IOException { @@ -516,7 +517,7 @@ public Response intercept(Chain chain) throws IOException { String cookieResult = config.getCsrfTokenCookieName() + "=" + csrftoken + "; " + config.getSessionCookieName() + "=" + sessionId; if (csrftoken == null) return chain.proceed(newRequest); HttpUrl url = newRequest - .httpUrl() + .url() .newBuilder() .addQueryParameter("csrfmiddlewaretoken", csrftoken) .addQueryParameter("csrfmiddlewaretoken", csrftoken) @@ -530,11 +531,13 @@ public Response intercept(Chain chain) throws IOException { return chain.proceed(newRequest); } }; - okHttpClient.networkInterceptors().add(interceptor); + OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder(); + okHttpClientBuilder.addNetworkInterceptor(interceptor); + setTimeout(okHttpClientBuilder, TIMEOUT_IN_SECONDS); Retrofit notLogged = new Retrofit.Builder() .baseUrl(config.getBaseUrl()) .addConverterFactory(generateGsonFactory()) - .client(okHttpClient) + .client(okHttpClientBuilder.build()) .build(); StepicEmptyAuthService tempService = notLogged.create(StepicEmptyAuthService.class); return tempService.remindPassword(encodedEmail); @@ -551,7 +554,7 @@ public Call sendFeedback(String email, String rawDescription) { OkHttpClient okHttpClient = new OkHttpClient(); Retrofit notLogged = new Retrofit.Builder() .baseUrl(config.getZendeskHost()) - .addConverterFactory(StringConverterFactory.create()) + .addConverterFactory(generateGsonFactory()) .client(okHttpClient) .build(); StepikDeskEmptyAuthService tempService = notLogged.create(StepikDeskEmptyAuthService.class); @@ -608,6 +611,7 @@ public UpdateResponse getInfoForUpdating() throws IOException { .url(config.getBaseUrl() + "/" + config.getUpdateEndpoint()) .build(); + OkHttpClient okHttpClient = new OkHttpClient(); String jsonString = okHttpClient.newCall(request).execute().body().string(); Gson gson = new Gson(); @@ -690,8 +694,8 @@ private String getNotificationCategoryString(NotificationCategory notificationCa @Nullable private List getCookiesForBaseUrl() throws IOException { String lang = Locale.getDefault().getLanguage(); - retrofit.Response ob = stepikEmptyAuthService.getStepicForFun(lang).execute(); - Headers headers = ob.headers(); + retrofit2.Response response = stepikEmptyAuthService.getStepicForFun(lang).execute(); + Headers headers = response.headers(); java.net.CookieManager cookieManager = new java.net.CookieManager(); URI myUri; try { @@ -705,9 +709,9 @@ private List getCookiesForBaseUrl() throws IOException { private void updateCookieForBaseUrl() throws IOException { String lang = Locale.getDefault().getLanguage(); - retrofit.Response ob = stepikEmptyAuthService.getStepicForFun(lang).execute(); + retrofit2.Response response = stepikEmptyAuthService.getStepicForFun(lang).execute(); - List setCookieHeaders = ob.headers().values(AppConstants.setCookieHeaderName); + List setCookieHeaders = response.headers().values(AppConstants.setCookieHeaderName); if (!setCookieHeaders.isEmpty()) { for (String value : setCookieHeaders) { if (value != null) { diff --git a/app/src/main/java/org/stepic/droid/web/StepicEmptyAuthService.java b/app/src/main/java/org/stepic/droid/web/StepicEmptyAuthService.java index ec912638ff..5caf18ef94 100644 --- a/app/src/main/java/org/stepic/droid/web/StepicEmptyAuthService.java +++ b/app/src/main/java/org/stepic/droid/web/StepicEmptyAuthService.java @@ -2,12 +2,12 @@ import org.stepic.droid.util.AppConstants; -import retrofit.Call; -import retrofit.http.Field; -import retrofit.http.FormUrlEncoded; -import retrofit.http.GET; -import retrofit.http.Header; -import retrofit.http.POST; +import retrofit2.Call; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.Header; +import retrofit2.http.POST; public interface StepicEmptyAuthService { diff --git a/app/src/main/java/org/stepic/droid/web/StepicRestLoggedService.java b/app/src/main/java/org/stepic/droid/web/StepicRestLoggedService.java index b22ad1f7cc..53ffa3a74e 100644 --- a/app/src/main/java/org/stepic/droid/web/StepicRestLoggedService.java +++ b/app/src/main/java/org/stepic/droid/web/StepicRestLoggedService.java @@ -3,17 +3,17 @@ import org.jetbrains.annotations.Nullable; import org.stepic.droid.model.EnrollmentWrapper; -import retrofit.Call; -import retrofit.http.Body; -import retrofit.http.DELETE; -import retrofit.http.Field; -import retrofit.http.FormUrlEncoded; -import retrofit.http.GET; -import retrofit.http.Headers; -import retrofit.http.POST; -import retrofit.http.PUT; -import retrofit.http.Path; -import retrofit.http.Query; +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.DELETE; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; +import retrofit2.http.GET; +import retrofit2.http.Headers; +import retrofit2.http.POST; +import retrofit2.http.PUT; +import retrofit2.http.Path; +import retrofit2.http.Query; public interface StepicRestLoggedService { @GET("api/sections") diff --git a/app/src/main/java/org/stepic/droid/web/StepicRestOAuthService.java b/app/src/main/java/org/stepic/droid/web/StepicRestOAuthService.java index f259753ebd..ec632cb5ad 100644 --- a/app/src/main/java/org/stepic/droid/web/StepicRestOAuthService.java +++ b/app/src/main/java/org/stepic/droid/web/StepicRestOAuthService.java @@ -1,14 +1,14 @@ package org.stepic.droid.web; -import com.squareup.okhttp.ResponseBody; - -import retrofit.Call; -import retrofit.http.Body; -import retrofit.http.GET; -import retrofit.http.POST; -import retrofit.http.Path; -import retrofit.http.Query; -import retrofit.http.Streaming; +import okhttp3.ResponseBody; + +import retrofit2.Call; +import retrofit2.http.Body; +import retrofit2.http.GET; +import retrofit2.http.POST; +import retrofit2.http.Path; +import retrofit2.http.Query; +import retrofit2.http.Streaming; public interface StepicRestOAuthService { @POST("/oauth2/token/") diff --git a/app/src/main/java/org/stepic/droid/web/StepikDeskEmptyAuthService.java b/app/src/main/java/org/stepic/droid/web/StepikDeskEmptyAuthService.java index 6341f2ffb3..aae3a7b7e9 100644 --- a/app/src/main/java/org/stepic/droid/web/StepikDeskEmptyAuthService.java +++ b/app/src/main/java/org/stepic/droid/web/StepikDeskEmptyAuthService.java @@ -1,9 +1,9 @@ package org.stepic.droid.web; -import retrofit.Call; -import retrofit.http.Multipart; -import retrofit.http.POST; -import retrofit.http.Part; +import retrofit2.Call; +import retrofit2.http.Multipart; +import retrofit2.http.POST; +import retrofit2.http.Part; public interface StepikDeskEmptyAuthService { diff --git a/app/src/main/java/org/stepic/droid/web/util/StringConverterFactory.java b/app/src/main/java/org/stepic/droid/web/util/StringConverterFactory.java index a83216b27f..16b0624e13 100644 --- a/app/src/main/java/org/stepic/droid/web/util/StringConverterFactory.java +++ b/app/src/main/java/org/stepic/droid/web/util/StringConverterFactory.java @@ -1,11 +1,11 @@ package org.stepic.droid.web.util; -import com.squareup.okhttp.RequestBody; +import okhttp3.RequestBody; import java.lang.annotation.Annotation; import java.lang.reflect.Type; -import retrofit.Converter; +import retrofit2.Converter; public class StringConverterFactory extends Converter.Factory { public static StringConverterFactory create() { diff --git a/app/src/main/java/org/stepic/droid/web/util/StringRequestBodyConverter.java b/app/src/main/java/org/stepic/droid/web/util/StringRequestBodyConverter.java index ecae31c9be..40a56cd174 100644 --- a/app/src/main/java/org/stepic/droid/web/util/StringRequestBodyConverter.java +++ b/app/src/main/java/org/stepic/droid/web/util/StringRequestBodyConverter.java @@ -1,11 +1,11 @@ package org.stepic.droid.web.util; -import com.squareup.okhttp.MediaType; -import com.squareup.okhttp.RequestBody; +import okhttp3.MediaType; +import okhttp3.RequestBody; import java.io.IOException; -import retrofit.Converter; +import retrofit2.Converter; public class StringRequestBodyConverter implements Converter { From b69bf20b9e6a2e28925ba517abc81a3f06f91c7c Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 13 Feb 2017 17:28:27 +0300 Subject: [PATCH 25/38] add more smart readerwriter lock for refreshing of token --- .../org/stepic/droid/web/RetrofitRESTApi.java | 95 ++++++++++--------- 1 file changed, 50 insertions(+), 45 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index d26928c320..2b9ddd079f 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -16,8 +16,6 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import org.joda.time.DateTime; -import org.joda.time.DateTimeZone; import org.stepic.droid.R; import org.stepic.droid.analytic.Analytic; import org.stepic.droid.base.MainApplication; @@ -124,7 +122,7 @@ private void makeLoggedService() { public Response intercept(Chain chain) throws IOException { Request newRequest = chain.request(); try { - RWLocks.AuthLock.writeLock().lock(); + RWLocks.AuthLock.readLock().lock(); AuthenticationStepicResponse response = sharedPreference.getAuthResponseFromStore(); String urlForCookies = newRequest.url().toString(); if (response == null) { @@ -151,45 +149,52 @@ public Response intercept(Chain chain) throws IOException { .build(); } } else if (isNeededUpdate(response)) { - retrofit2.Response authenticationStepicResponse; + RWLocks.AuthLock.readLock().unlock(); try { - authenticationStepicResponse = oAuthService.updateToken(config.getRefreshGrantType(), response.getRefresh_token()).execute(); - response = authenticationStepicResponse.body(); - } catch (Exception e) { - analytic.reportError(Analytic.Error.CANT_UPDATE_TOKEN, e); - return chain.proceed(newRequest); - } - if (response == null || !response.isSuccess()) { - //it is worst case: + RWLocks.AuthLock.writeLock().lock(); + retrofit2.Response authenticationStepicResponse; + try { + authenticationStepicResponse = oAuthService.updateToken(config.getRefreshGrantType(), response.getRefresh_token()).execute(); + response = authenticationStepicResponse.body(); + } catch (Exception e) { + analytic.reportError(Analytic.Error.CANT_UPDATE_TOKEN, e); + return chain.proceed(newRequest); + } + if (response == null || !response.isSuccess()) { + //it is worst case: - String message; - if (response == null) { - message = "response was null"; - } else { - message = response.toString(); - } + String message; + if (response == null) { + message = "response was null"; + } else { + message = response.toString(); + } - String extendedMessage = ""; - if (authenticationStepicResponse == null) { - extendedMessage = "rawResponse was null"; - } else if (authenticationStepicResponse.isSuccessful()) { - extendedMessage = "was success " + authenticationStepicResponse.code(); - } else { - try { - extendedMessage = "failed " + authenticationStepicResponse.code() + " " + authenticationStepicResponse.errorBody().string(); - } catch (Exception ex) { - analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_INLINE_GETTING, ex); + String extendedMessage = ""; + if (authenticationStepicResponse == null) { + extendedMessage = "rawResponse was null"; + } else if (authenticationStepicResponse.isSuccessful()) { + extendedMessage = "was success " + authenticationStepicResponse.code(); + } else { + try { + extendedMessage = "failed " + authenticationStepicResponse.code() + " " + authenticationStepicResponse.errorBody().string(); + } catch (Exception ex) { + analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_INLINE_GETTING, ex); + } } + analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_ONLINE_EXTENDED, new FailRefreshException(extendedMessage)); + analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_ONLINE, new FailRefreshException(message)); + analytic.reportEvent(Analytic.Web.UPDATE_TOKEN_FAILED); + return chain.proceed(newRequest); } - analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_ONLINE_EXTENDED, new FailRefreshException(extendedMessage)); - analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_ONLINE, new FailRefreshException(message)); - analytic.reportEvent(Analytic.Web.UPDATE_TOKEN_FAILED); - return chain.proceed(newRequest); - } - //Update is success: - sharedPreference.storeAuthInfo(response); + //Update is success: + sharedPreference.storeAuthInfo(response); + RWLocks.AuthLock.readLock().lock(); + } finally { + RWLocks.AuthLock.writeLock().unlock(); + } } if (response != null) { //it is good way @@ -207,7 +212,7 @@ public Response intercept(Chain chain) throws IOException { } return originalResponse; } finally { - RWLocks.AuthLock.writeLock().unlock(); + RWLocks.AuthLock.readLock().unlock(); } } @@ -741,14 +746,14 @@ private String getAuthHeaderValueForLogged() { private boolean isNeededUpdate(AuthenticationStepicResponse response) { if (response == null) return false; -// return true; - - long timestampStored = sharedPreference.getAccessTokenTimestamp(); - if (timestampStored == -1) return true; - - long nowTemp = DateTime.now(DateTimeZone.UTC).getMillis(); - long delta = nowTemp - timestampStored; - long expiresMillis = (response.getExpires_in() - 50) * 1000; - return delta > expiresMillis;//token expired --> need update + return true; + +// long timestampStored = sharedPreference.getAccessTokenTimestamp(); +// if (timestampStored == -1) return true; +// +// long nowTemp = DateTime.now(DateTimeZone.UTC).getMillis(); +// long delta = nowTemp - timestampStored; +// long expiresMillis = (response.getExpires_in() - 50) * 1000; +// return delta > expiresMillis;//token expired --> need update } } From 6b159c99df33e7b52e6626c3f316a5aa9acc5537 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 13 Feb 2017 17:32:32 +0300 Subject: [PATCH 26/38] add stetho for find issues with API & tune rwl --- app/build.gradle | 3 + .../stepic/droid/base/MainApplication.java | 2 + .../org/stepic/droid/web/RetrofitRESTApi.java | 102 ++++++++++-------- 3 files changed, 61 insertions(+), 46 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index f0b3cf92d0..d5b84eedd8 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -189,6 +189,9 @@ dependencies { } compile 'com.caverock:androidsvg:1.2.1' + + compile 'com.facebook.stetho:stetho:1.4.2' + compile 'com.facebook.stetho:stetho-okhttp3:1.4.2' } repositories { diff --git a/app/src/main/java/org/stepic/droid/base/MainApplication.java b/app/src/main/java/org/stepic/droid/base/MainApplication.java index ff47fde101..5a98b8294b 100644 --- a/app/src/main/java/org/stepic/droid/base/MainApplication.java +++ b/app/src/main/java/org/stepic/droid/base/MainApplication.java @@ -6,6 +6,7 @@ import com.facebook.FacebookSdk; import com.facebook.appevents.AppEventsLogger; +import com.facebook.stetho.Stetho; import com.vk.sdk.VKSdk; import com.yandex.metrica.YandexMetrica; @@ -39,6 +40,7 @@ public void onCreate() { private void init() { // refWatcher = LeakCanary.install(this); application = this; + Stetho.initializeWithDefaults(this); if (BuildConfig.DEBUG) { Timber.plant(new Timber.DebugTree()); diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index 2b9ddd079f..533b72abfd 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -10,6 +10,7 @@ import android.webkit.CookieManager; import android.webkit.CookieSyncManager; +import com.facebook.stetho.okhttp3.StethoInterceptor; import com.google.firebase.analytics.FirebaseAnalytics; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -71,6 +72,7 @@ @Singleton public class RetrofitRESTApi implements IApi { private final int TIMEOUT_IN_SECONDS = 10; + private final StethoInterceptor stethoInterceptor = new StethoInterceptor(); @Inject Context context; @@ -152,47 +154,51 @@ public Response intercept(Chain chain) throws IOException { RWLocks.AuthLock.readLock().unlock(); try { RWLocks.AuthLock.writeLock().lock(); - retrofit2.Response authenticationStepicResponse; - try { - authenticationStepicResponse = oAuthService.updateToken(config.getRefreshGrantType(), response.getRefresh_token()).execute(); - response = authenticationStepicResponse.body(); - } catch (Exception e) { - analytic.reportError(Analytic.Error.CANT_UPDATE_TOKEN, e); - return chain.proceed(newRequest); - } - if (response == null || !response.isSuccess()) { - //it is worst case: + Timber.d("writer 1"); + if (isNeededUpdate(response)) { + retrofit2.Response authenticationStepicResponse; + try { + authenticationStepicResponse = oAuthService.updateToken(config.getRefreshGrantType(), response.getRefresh_token()).execute(); + response = authenticationStepicResponse.body(); + } catch (Exception e) { + analytic.reportError(Analytic.Error.CANT_UPDATE_TOKEN, e); + return chain.proceed(newRequest); + } + if (response == null || !response.isSuccess()) { + //it is worst case: - String message; - if (response == null) { - message = "response was null"; - } else { - message = response.toString(); - } + String message; + if (response == null) { + message = "response was null"; + } else { + message = response.toString(); + } - String extendedMessage = ""; - if (authenticationStepicResponse == null) { - extendedMessage = "rawResponse was null"; - } else if (authenticationStepicResponse.isSuccessful()) { - extendedMessage = "was success " + authenticationStepicResponse.code(); - } else { - try { - extendedMessage = "failed " + authenticationStepicResponse.code() + " " + authenticationStepicResponse.errorBody().string(); - } catch (Exception ex) { - analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_INLINE_GETTING, ex); + String extendedMessage = ""; + if (authenticationStepicResponse == null) { + extendedMessage = "rawResponse was null"; + } else if (authenticationStepicResponse.isSuccessful()) { + extendedMessage = "was success " + authenticationStepicResponse.code(); + } else { + try { + extendedMessage = "failed " + authenticationStepicResponse.code() + " " + authenticationStepicResponse.errorBody().string(); + } catch (Exception ex) { + analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_INLINE_GETTING, ex); + } } + analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_ONLINE_EXTENDED, new FailRefreshException(extendedMessage)); + analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_ONLINE, new FailRefreshException(message)); + analytic.reportEvent(Analytic.Web.UPDATE_TOKEN_FAILED); + return chain.proceed(newRequest); } - analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_ONLINE_EXTENDED, new FailRefreshException(extendedMessage)); - analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_ONLINE, new FailRefreshException(message)); - analytic.reportEvent(Analytic.Web.UPDATE_TOKEN_FAILED); - return chain.proceed(newRequest); - } - //Update is success: - sharedPreference.storeAuthInfo(response); - RWLocks.AuthLock.readLock().lock(); + //Update is success: + sharedPreference.storeAuthInfo(response); + } } finally { + RWLocks.AuthLock.readLock().lock(); + Timber.d("writer 2"); RWLocks.AuthLock.writeLock().unlock(); } } @@ -218,6 +224,7 @@ public Response intercept(Chain chain) throws IOException { } }; okHttpBuilder.addNetworkInterceptor(interceptor); + okHttpBuilder.addNetworkInterceptor(this.stethoInterceptor); setTimeout(okHttpBuilder, TIMEOUT_IN_SECONDS); OkHttpClient okHttpClient = okHttpBuilder.build(); Retrofit retrofit = new Retrofit.Builder() @@ -239,13 +246,14 @@ public Response intercept(Chain chain) throws IOException { return chain.proceed(newRequest); } }; - OkHttpClient.Builder builder = new OkHttpClient.Builder(); - setTimeout(builder, TIMEOUT_IN_SECONDS); - builder.addNetworkInterceptor(interceptor); + OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder(); + setTimeout(okHttpBuilder, TIMEOUT_IN_SECONDS); + okHttpBuilder.addNetworkInterceptor(interceptor); + okHttpBuilder.addNetworkInterceptor(this.stethoInterceptor); Retrofit notLogged = new Retrofit.Builder() .baseUrl(config.getBaseUrl()) .addConverterFactory(generateGsonFactory()) - .client(builder.build()) + .client(okHttpBuilder.build()) .build(); oAuthService = notLogged.create(StepicRestOAuthService.class); } @@ -322,13 +330,14 @@ public Response intercept(Chain chain) throws IOException { return chain.proceed(newRequest); } }; - OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder(); - okHttpClientBuilder.addNetworkInterceptor(interceptor); - setTimeout(okHttpClientBuilder, TIMEOUT_IN_SECONDS); + OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder(); + okHttpBuilder.addNetworkInterceptor(interceptor); + okHttpBuilder.addNetworkInterceptor(this.stethoInterceptor); + setTimeout(okHttpBuilder, TIMEOUT_IN_SECONDS); Retrofit notLogged = new Retrofit.Builder() .baseUrl(config.getBaseUrl()) .addConverterFactory(generateGsonFactory()) - .client(okHttpClientBuilder.build()) + .client(okHttpBuilder.build()) .build(); StepicRestOAuthService tempService = notLogged.create(StepicRestOAuthService.class); return tempService.createAccount(new UserRegistrationRequest(new RegistrationUser(firstName, lastName, email, password))); @@ -536,13 +545,14 @@ public Response intercept(Chain chain) throws IOException { return chain.proceed(newRequest); } }; - OkHttpClient.Builder okHttpClientBuilder = new OkHttpClient.Builder(); - okHttpClientBuilder.addNetworkInterceptor(interceptor); - setTimeout(okHttpClientBuilder, TIMEOUT_IN_SECONDS); + OkHttpClient.Builder okHttpBuilder = new OkHttpClient.Builder(); + okHttpBuilder.addNetworkInterceptor(interceptor); + okHttpBuilder.addNetworkInterceptor(this.stethoInterceptor); + setTimeout(okHttpBuilder, TIMEOUT_IN_SECONDS); Retrofit notLogged = new Retrofit.Builder() .baseUrl(config.getBaseUrl()) .addConverterFactory(generateGsonFactory()) - .client(okHttpClientBuilder.build()) + .client(okHttpBuilder.build()) .build(); StepicEmptyAuthService tempService = notLogged.create(StepicEmptyAuthService.class); return tempService.remindPassword(encodedEmail); From 9711d0800b98ce3f9a30d40e2fbb11b4e2d5f21f Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Tue, 14 Feb 2017 14:48:16 +0300 Subject: [PATCH 27/38] hide parameters of refresh/sign in requests to body --- .../droid/web/StepicRestOAuthService.java | 34 +++++++++++-------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/web/StepicRestOAuthService.java b/app/src/main/java/org/stepic/droid/web/StepicRestOAuthService.java index ec632cb5ad..fbb9754f25 100644 --- a/app/src/main/java/org/stepic/droid/web/StepicRestOAuthService.java +++ b/app/src/main/java/org/stepic/droid/web/StepicRestOAuthService.java @@ -1,37 +1,41 @@ package org.stepic.droid.web; import okhttp3.ResponseBody; - import retrofit2.Call; import retrofit2.http.Body; +import retrofit2.http.Field; +import retrofit2.http.FormUrlEncoded; import retrofit2.http.GET; import retrofit2.http.POST; import retrofit2.http.Path; -import retrofit2.http.Query; import retrofit2.http.Streaming; public interface StepicRestOAuthService { + @FormUrlEncoded @POST("/oauth2/token/") - Call updateToken(@Query("grant_type") String grant_type, - @Query("refresh_token") String refresh_token); + Call updateToken(@Field("grant_type") String grant_type, + @Field("refresh_token") String refresh_token); + @FormUrlEncoded @POST("/oauth2/token/") - Call authWithLoginPassword(@Query("grant_type") String grant_type, - @Query(value = "username", encoded = true) String username, - @Query(value = "password", encoded = true) String password); + Call authWithLoginPassword(@Field("grant_type") String grant_type, + @Field(value = "username", encoded = true) String username, + @Field(value = "password", encoded = true) String password); + @FormUrlEncoded @POST("/oauth2/token/") - Call getTokenByCode(@Query("grant_type") String grant_type, - @Query("code") String code, - @Query("redirect_uri") String redirect_uri); + Call getTokenByCode(@Field("grant_type") String grant_type, + @Field("code") String code, + @Field("redirect_uri") String redirect_uri); + @FormUrlEncoded @POST("/oauth2/social-token/") - Call getTokenByNativeCode(@Query("provider") String providerName, - @Query("code") String providerCode, - @Query("grant_type") String grant_type, - @Query("redirect_uri") String redirect_uri, - @Query("code_type") String accessToken); + Call getTokenByNativeCode(@Field("provider") String providerName, + @Field("code") String providerCode, + @Field("grant_type") String grant_type, + @Field("redirect_uri") String redirect_uri, + @Field("code_type") String accessToken); @POST("/api/users") From 33614b48ad88c222c02fb1d284ce06878a962be2 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Tue, 14 Feb 2017 15:34:00 +0300 Subject: [PATCH 28/38] fix bug, when updater is used old auth data --- .../main/java/org/stepic/droid/web/RetrofitRESTApi.java | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index 533b72abfd..6eaa5a1628 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -151,10 +151,11 @@ public Response intercept(Chain chain) throws IOException { .build(); } } else if (isNeededUpdate(response)) { - RWLocks.AuthLock.readLock().unlock(); try { + RWLocks.AuthLock.readLock().unlock(); RWLocks.AuthLock.writeLock().lock(); Timber.d("writer 1"); + response = sharedPreference.getAuthResponseFromStore(); if (isNeededUpdate(response)) { retrofit2.Response authenticationStepicResponse; try { @@ -755,7 +756,10 @@ private String getAuthHeaderValueForLogged() { } private boolean isNeededUpdate(AuthenticationStepicResponse response) { - if (response == null) return false; + if (response == null) { + Timber.d("Token is null"); + return false; + } return true; // long timestampStored = sharedPreference.getAccessTokenTimestamp(); From 2f09216a2c5e470c945e0280069cc590d35ad2f6 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Tue, 14 Feb 2017 16:24:31 +0300 Subject: [PATCH 29/38] logout user, when 401 is exist while refresh token --- .../org/stepic/droid/analytic/Analytic.java | 1 + .../org/stepic/droid/core/ScreenManager.java | 5 +- .../stepic/droid/core/ScreenManagerImpl.java | 12 +- .../stepic/droid/core/StepikLogoutManager.kt | 42 ++++ .../droid/core/modules/AppCoreModule.java | 7 + .../droid/core/modules/MainFeedModule.java | 11 +- .../presenters/ProfileMainFeedPresenter.kt | 33 +-- .../droid/ui/activities/SplashActivity.java | 14 ++ .../org/stepic/droid/web/RetrofitRESTApi.java | 35 ++- app/src/main/res/values-ru/strings.xml | 206 +++++++++++++----- app/src/main/res/values/strings.xml | 1 + 11 files changed, 266 insertions(+), 101 deletions(-) create mode 100644 app/src/main/java/org/stepic/droid/core/StepikLogoutManager.kt diff --git a/app/src/main/java/org/stepic/droid/analytic/Analytic.java b/app/src/main/java/org/stepic/droid/analytic/Analytic.java index 462daa5133..dd7df8418a 100644 --- a/app/src/main/java/org/stepic/droid/analytic/Analytic.java +++ b/app/src/main/java/org/stepic/droid/analytic/Analytic.java @@ -171,6 +171,7 @@ interface Error { String PENDING_INTENT_WAS_NULL = "pending_intent_null_streaks"; String FAIL_REFRESH_TOKEN_INLINE_GETTING = "fail_refresh_token_online_get"; java.lang.String COOKIE_WAS_EMPTY = "cookie_was_empty"; + String FAIL_LOGOUT_WHEN_REFRESH = "refresh_fail_logout_social"; } interface Web { diff --git a/app/src/main/java/org/stepic/droid/core/ScreenManager.java b/app/src/main/java/org/stepic/droid/core/ScreenManager.java index fd3990b735..8ac6e4abf5 100644 --- a/app/src/main/java/org/stepic/droid/core/ScreenManager.java +++ b/app/src/main/java/org/stepic/droid/core/ScreenManager.java @@ -19,9 +19,10 @@ import org.stepic.droid.web.ViewAssignment; public interface ScreenManager { - void showLaunchScreen(Activity activity); - void showLaunchScreen(Activity activity, boolean fromMainFeed, int indexInMenu); + void showLaunchScreen(Context context); + + void showLaunchScreen(Context context, boolean fromMainFeed, int indexInMenu); void showRegistration(Activity sourceActivity, @Nullable Course course); diff --git a/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java b/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java index d6ad25d946..41e25c081e 100644 --- a/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java +++ b/app/src/main/java/org/stepic/droid/core/ScreenManagerImpl.java @@ -82,8 +82,8 @@ public ScreenManagerImpl(IConfig config, UserPreferences userPreferences, Analyt } @Override - public void showLaunchScreen(Activity activity) { - showLaunchScreen(activity, false, 0); + public void showLaunchScreen(Context context) { + showLaunchScreen(context, false, 0); } @Override @@ -104,15 +104,15 @@ public void openImage(Context context, String path) { } @Override - public void showLaunchScreen(Activity activity, boolean fromMainFeed, int index) { + public void showLaunchScreen(Context context, boolean fromMainFeed, int index) { analytic.reportEvent(Analytic.Screens.SHOW_LAUNCH); - Intent launchIntent = new Intent(activity, LaunchActivity.class); + Intent launchIntent = new Intent(context, LaunchActivity.class); if (fromMainFeed) { launchIntent.putExtra(AppConstants.FROM_MAIN_FEED_FLAG, true); launchIntent.putExtra(MainFeedActivity.KEY_CURRENT_INDEX, index); } - launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); - activity.startActivity(launchIntent); + launchIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK | Intent.FLAG_ACTIVITY_NEW_TASK); //app context -- new task + context.startActivity(launchIntent); } diff --git a/app/src/main/java/org/stepic/droid/core/StepikLogoutManager.kt b/app/src/main/java/org/stepic/droid/core/StepikLogoutManager.kt new file mode 100644 index 0000000000..9298f74c22 --- /dev/null +++ b/app/src/main/java/org/stepic/droid/core/StepikLogoutManager.kt @@ -0,0 +1,42 @@ +package org.stepic.droid.core + +import android.app.DownloadManager +import org.stepic.droid.concurrency.IMainHandler +import org.stepic.droid.preferences.SharedPreferenceHelper +import org.stepic.droid.preferences.UserPreferences +import org.stepic.droid.store.operations.DatabaseFacade +import org.stepic.droid.util.FileUtil +import org.stepic.droid.util.RWLocks +import java.util.concurrent.ThreadPoolExecutor + +class StepikLogoutManager(private val threadPoolExecutor: ThreadPoolExecutor, + private val mainHandler: IMainHandler, + private val userPreferences: UserPreferences, + private val systemDownloadManager: DownloadManager, + private val sharedPreferenceHelper: SharedPreferenceHelper, + private val databaseFacade: DatabaseFacade) { + + fun logout(afterClearData: () -> Unit) { + threadPoolExecutor.execute { + val directoryForClean = userPreferences.userDownloadFolder + val downloadEntities = databaseFacade.getAllDownloadEntities() + downloadEntities.forEach { + it?.downloadId?.let { + downloadId -> + systemDownloadManager.remove(downloadId) + } + } + FileUtil.cleanDirectory(directoryForClean) + try { + RWLocks.ClearEnrollmentsLock.writeLock().lock() + sharedPreferenceHelper.deleteAuthInfo() + databaseFacade.dropDatabase() + } finally { + RWLocks.ClearEnrollmentsLock.writeLock().unlock() + } + mainHandler.post { + afterClearData.invoke() + } + } + } +} diff --git a/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java b/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java index df728b32c9..b6e22a1d27 100644 --- a/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java +++ b/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java @@ -31,6 +31,7 @@ import org.stepic.droid.core.ShareHelper; import org.stepic.droid.core.ShareHelperImpl; import org.stepic.droid.core.Shell; +import org.stepic.droid.core.StepikLogoutManager; import org.stepic.droid.notifications.INotificationManager; import org.stepic.droid.notifications.LocalReminder; import org.stepic.droid.notifications.LocalReminderImpl; @@ -311,4 +312,10 @@ Retrofit provideRetrofit(IConfig config) { .client(new OkHttpClient()) .build(); } + + @Provides + @Singleton + StepikLogoutManager provideStepikLogoutManager(ThreadPoolExecutor threadPoolExecutor, IMainHandler mainHandler, UserPreferences userPreferences, SharedPreferenceHelper sharedPreferenceHelper, DownloadManager downloadManager, DatabaseFacade dbFacade) { + return new StepikLogoutManager(threadPoolExecutor, mainHandler, userPreferences, downloadManager, sharedPreferenceHelper, dbFacade); + } } diff --git a/app/src/main/java/org/stepic/droid/core/modules/MainFeedModule.java b/app/src/main/java/org/stepic/droid/core/modules/MainFeedModule.java index f03810190e..6e0f5a00f0 100644 --- a/app/src/main/java/org/stepic/droid/core/modules/MainFeedModule.java +++ b/app/src/main/java/org/stepic/droid/core/modules/MainFeedModule.java @@ -1,13 +1,10 @@ package org.stepic.droid.core.modules; -import android.app.DownloadManager; - import org.stepic.droid.analytic.Analytic; import org.stepic.droid.concurrency.IMainHandler; +import org.stepic.droid.core.StepikLogoutManager; import org.stepic.droid.core.presenters.ProfileMainFeedPresenter; import org.stepic.droid.preferences.SharedPreferenceHelper; -import org.stepic.droid.preferences.UserPreferences; -import org.stepic.droid.store.operations.DatabaseFacade; import org.stepic.droid.web.IApi; import java.util.concurrent.ThreadPoolExecutor; @@ -24,9 +21,7 @@ ProfileMainFeedPresenter provideProfileMainFeedPresenter(IMainHandler mainHandle Analytic analytic, SharedPreferenceHelper sharedPreferenceHelper, IApi api, - DatabaseFacade databaseFacade, - DownloadManager systemDownloadManager, - UserPreferences userPreferences) { - return new ProfileMainFeedPresenter(sharedPreferenceHelper, mainHandler, api, threadPoolExecutor, analytic, databaseFacade, userPreferences, systemDownloadManager); + StepikLogoutManager stepikLogoutManager) { + return new ProfileMainFeedPresenter(sharedPreferenceHelper, mainHandler, api, threadPoolExecutor, analytic, stepikLogoutManager); } } diff --git a/app/src/main/java/org/stepic/droid/core/presenters/ProfileMainFeedPresenter.kt b/app/src/main/java/org/stepic/droid/core/presenters/ProfileMainFeedPresenter.kt index ea23ce1e67..853e73d2eb 100644 --- a/app/src/main/java/org/stepic/droid/core/presenters/ProfileMainFeedPresenter.kt +++ b/app/src/main/java/org/stepic/droid/core/presenters/ProfileMainFeedPresenter.kt @@ -1,15 +1,11 @@ package org.stepic.droid.core.presenters -import android.app.DownloadManager import org.stepic.droid.analytic.Analytic import org.stepic.droid.concurrency.IMainHandler +import org.stepic.droid.core.StepikLogoutManager import org.stepic.droid.core.presenters.contracts.ProfileMainFeedView import org.stepic.droid.model.Profile import org.stepic.droid.preferences.SharedPreferenceHelper -import org.stepic.droid.preferences.UserPreferences -import org.stepic.droid.store.operations.DatabaseFacade -import org.stepic.droid.util.FileUtil -import org.stepic.droid.util.RWLocks import org.stepic.droid.web.IApi import java.util.concurrent.ThreadPoolExecutor import java.util.concurrent.atomic.AtomicBoolean @@ -19,9 +15,7 @@ class ProfileMainFeedPresenter(private val sharedPreferenceHelper: SharedPrefere private val api: IApi, private val threadPoolExecutor: ThreadPoolExecutor, private val analytic: Analytic, - private val databaseFacade: DatabaseFacade, - private val userPreferences: UserPreferences, - private val systemDownloadManager: DownloadManager) : PresenterBase() { + private val stepikLogoutManager: StepikLogoutManager) : PresenterBase() { val isProfileFetching = AtomicBoolean(false) var profile: Profile? = null @@ -88,28 +82,9 @@ class ProfileMainFeedPresenter(private val sharedPreferenceHelper: SharedPrefere profile = null view?.showAnonymous() analytic.reportEvent(org.stepic.droid.analytic.Analytic.Interaction.CLICK_YES_LOGOUT) - threadPoolExecutor.execute { - val directoryForClean = userPreferences.userDownloadFolder - val downloadEntities = databaseFacade.getAllDownloadEntities() - downloadEntities.forEach { - it?.downloadId?.let { - downloadId -> - systemDownloadManager.remove(downloadId) - } - } - FileUtil.cleanDirectory(directoryForClean) - try { - RWLocks.ClearEnrollmentsLock.writeLock().lock() - sharedPreferenceHelper.deleteAuthInfo() - databaseFacade.dropDatabase() - } finally { - RWLocks.ClearEnrollmentsLock.writeLock().unlock() - } - mainHandler.post { - view?.onLogoutSuccess() - } + stepikLogoutManager.logout { + view?.onLogoutSuccess() } - } } diff --git a/app/src/main/java/org/stepic/droid/ui/activities/SplashActivity.java b/app/src/main/java/org/stepic/droid/ui/activities/SplashActivity.java index f62cab8de6..b680a67f95 100644 --- a/app/src/main/java/org/stepic/droid/ui/activities/SplashActivity.java +++ b/app/src/main/java/org/stepic/droid/ui/activities/SplashActivity.java @@ -15,6 +15,7 @@ import org.stepic.droid.notifications.StepicInstanceIdService; import org.stepic.droid.util.AppConstants; +import java.io.IOException; import java.util.Arrays; import kotlin.Unit; @@ -36,6 +37,19 @@ protected void onCreate(Bundle savedInstanceState) { return; } + threadPoolExecutor.execute( + new Runnable() { + @Override + public void run() { + try { + shell.getApi().getUserProfile().execute(); // make this "ping" request for updating refresh tokens and log out user, if it is revoked. + } catch (IOException e) { + //ignore + } + } + } + ); + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.N_MR1) { ShortcutManager shortcutManager = getSystemService(ShortcutManager.class); diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index 6eaa5a1628..609864f0a5 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -9,11 +9,14 @@ import android.support.v4.app.FragmentActivity; import android.webkit.CookieManager; import android.webkit.CookieSyncManager; +import android.widget.Toast; +import com.facebook.login.LoginManager; import com.facebook.stetho.okhttp3.StethoInterceptor; import com.google.firebase.analytics.FirebaseAnalytics; import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.vk.sdk.VKSdk; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -21,6 +24,8 @@ import org.stepic.droid.analytic.Analytic; import org.stepic.droid.base.MainApplication; import org.stepic.droid.configuration.IConfig; +import org.stepic.droid.core.ScreenManager; +import org.stepic.droid.core.StepikLogoutManager; import org.stepic.droid.deserializers.DatasetDeserializer; import org.stepic.droid.deserializers.ReplyDeserializer; import org.stepic.droid.model.Course; @@ -56,6 +61,8 @@ import javax.inject.Inject; import javax.inject.Singleton; +import kotlin.Unit; +import kotlin.jvm.functions.Function0; import okhttp3.Credentials; import okhttp3.Headers; import okhttp3.HttpUrl; @@ -89,6 +96,12 @@ public class RetrofitRESTApi implements IApi { @Inject Analytic analytic; + @Inject + StepikLogoutManager stepikLogoutManager; + + @Inject + ScreenManager screenManager; + private StepicRestLoggedService loggedService; private StepicRestOAuthService oAuthService; private StepicEmptyAuthService stepikEmptyAuthService; @@ -167,8 +180,6 @@ public Response intercept(Chain chain) throws IOException { } if (response == null || !response.isSuccess()) { //it is worst case: - - String message; if (response == null) { message = "response was null"; @@ -184,6 +195,26 @@ public Response intercept(Chain chain) throws IOException { } else { try { extendedMessage = "failed " + authenticationStepicResponse.code() + " " + authenticationStepicResponse.errorBody().string(); + if (authenticationStepicResponse.code() == 401) { + // logout user + stepikLogoutManager.logout( + new Function0() { + @Override + public Unit invoke() { + try { + LoginManager.getInstance().logOut(); + VKSdk.logout(); + } catch (Exception e) { + analytic.reportError(Analytic.Error.FAIL_LOGOUT_WHEN_REFRESH, e); + } + screenManager.showLaunchScreen(context); + Toast.makeText(context, R.string.logout_user_error, Toast.LENGTH_SHORT).show(); + return Unit.INSTANCE; + } + } + ); + } + } catch (Exception ex) { analytic.reportError(Analytic.Error.FAIL_REFRESH_TOKEN_INLINE_GETTING, ex); } diff --git a/app/src/main/res/values-ru/strings.xml b/app/src/main/res/values-ru/strings.xml index da6108e7c6..ef2819b3ad 100644 --- a/app/src/main/res/values-ru/strings.xml +++ b/app/src/main/res/values-ru/strings.xml @@ -3,11 +3,13 @@ Регистрация с e-mail Stepik.org: бесплатные курсы - Мы заметили, что Вы до сих пор не выбрали ни одного курса для изучения. Не откладывайте, запишитесь на подходящий бесплатный курс прямо сейчас! + Мы заметили, что Вы до сих пор не выбрали ни одного курса + для изучения. Не откладывайте, запишитесь на подходящий бесплатный курс прямо сейчас! + Доступные курсы Начало Лучшие уроки - Создавая аккаунт, я соглашаюсь с + Создавая аккаунт, я соглашаюсь с Создать аккаунт закрыть меню открыть меню @@ -44,13 +46,15 @@ Кеширование Stepik урока Видео Очистить кэш - Загружать только по Wi-Fi + Загружать только по Wi-Fi Подтверждение Да Нет пройти задание в web-версии Разрешить загрузку через мобильный интернет - Разрешить телефону загружать видео по мобильному интернету, когда Wi-Fi недоступен? + Разрешить телефону загружать видео по мобильному интернету, + когда Wi-Fi недоступен? + Покинуть курс О курсе Вы покинули @@ -62,12 +66,17 @@ Отклонить Разрешить Разрешить? - Для сохранения и просмотра видео в режиме оффлайн Stepik должен иметь права записи файлов в память телефона. + Для сохранения и просмотра видео в режиме оффлайн Stepik + должен иметь права записи файлов в память телефона. + Отсутствует подключение к Интернету Качество видео - Возникли проблемы с синхронизацией данных, пожалуйста, повторите попытку позже + Возникли проблемы с синхронизацией данных, пожалуйста, повторите + попытку позже + Похоже, что Вы не записаны ни на один курс - Посмотрите курсы или войдите, чтобы записаться на них + Посмотрите курсы или войдите, чтобы записаться на них + Кэш успешно очищен! Попробуйте записаться на курс в веб версии Загрузки @@ -91,15 +100,23 @@ Неправильно. Пожалуйста, попробуйте еще раз. Верно! Попробовать снова - Шаги можно проходить только онлайн. Чтобы начать решать, включите интернет-соединение. + Шаги можно проходить только онлайн. Чтобы начать решать, + включите интернет-соединение. + Ваше решение сохранено. Введите ответ здесь… - PyCharm Educational Edition]]> - Условиями использования и Политикой конфиденциальности]]> - Условия использования и Политика конфиденциальности]]> - Условиями использования и Политикой конфиденциальности]]> - Это задание с рецензией. Нажмите, чтобы закончить задание в web и получить баллы. - Минимальное количество символов в пароле: 6. + + PyCharm Educational Edition]]> + + Условиями использования и Политикой конфиденциальности]]> + + Условия использования и Политика конфиденциальности]]> + + Условиями использования и Политикой конфиденциальности]]> + Это задание с рецензией. Нажмите, чтобы закончить задание в web и + получить баллы. + + Минимальное количество символов в пароле: 6. Сбросить пароль Отправить Мы отправили вам письмо. @@ -108,7 +125,9 @@ Приложение нравится, им приятно пользоваться. отлично плохо - Приложение неудобное, долго загружается, видео не воспроизводится. + Приложение неудобное, долго загружается, видео не + воспроизводится. + Оставить отзыв Напишите нам… Напишите нам свое предложение, замечание или идею @@ -151,7 +170,9 @@ Отменить все Загружено Удалить все - Отмена загрузки видео времязатратня операция. Вы уверены? + Отмена загрузки видео времязатратня операция. Вы + уверены? + Напишите замечание или идею От Комментарии @@ -166,16 +187,26 @@ Комментарий Этот комментарий был удален Управление памятью - Приложение поддерживает просмотр видео онлайн, но для просмотра уроков без Интернет-подключения их необходимо сохранять. Большую часть памяти занимают видео-уроки. Удаление всех загруженных видео может занять несколько минут. + Приложение поддерживает просмотр видео онлайн, но для + просмотра уроков без Интернет-подключения их необходимо сохранять. Большую часть памяти + занимают видео-уроки. Удаление всех загруженных видео может занять несколько минут. + Пусто Память - Карта памяти не установлена на устройство. Для того, чтобы сохранять видео на карту памяти, вставьте ее в телефон и перезапустите приложение. - Вы можете сохранять уроки на SD-карту или на внутреннюю память устройства. Обратите внимание, что если уроки были записаны на SD-карту, то, при извлечении SD-карты, они перестанут быть доступны для прохождения офлайн. + Карта памяти не установлена на устройство. Для того, чтобы + сохранять видео на карту памяти, вставьте ее в телефон и перезапустите приложение. + + Вы можете сохранять уроки на SD-карту или на внутреннюю память + устройства. Обратите внимание, что если уроки были записаны на SD-карту, то, при извлечении + SD-карты, они перестанут быть доступны для прохождения офлайн. + Место для хранения Внешняя Внутренняя свободно - Все ранее загруженные видео будут перенесены, новые видео будут сохраняться в выбранное место. Операция может занять несколько минут. Вы уверены? + Все ранее загруженные видео будут перенесены, новые видео + будут сохраняться в выбранное место. Операция может занять несколько минут. Вы уверены? + Извините, файл удален или перемещен Извините, произошла ошибка, когда файлы перемещались Нравится @@ -184,9 +215,12 @@ Готово Перенос Продолжить - К сожалению, курс не найден. Нажмите, чтобы найти другие курсы! + К сожалению, курс не найден. Нажмите, чтобы найти другие курсы! + Авторизация - Для того, чтобы продолжить, необходимо войти или зарегистрироваться. Вы хотите сделать это сейчас? + Для того, чтобы продолжить, необходимо войти или + зарегистрироваться. Вы хотите сделать это сейчас? + Удалить Удалить этот комментарий Извините, не удалось удалить комментарий @@ -201,24 +235,35 @@ Свежие обновления Скопировать текст Календарь - У заданий в данном курсе есть крайний срок сдачи. Для того, чтобы пройти задание вовремя и получить сертификат, мы рекомендуем добавить в календарь крайние сроки сдачи и получать напоминания за 2 дня до их наступления. Управлять появлением данного сообщения можно в настройках приложения. + У заданий в данном курсе есть крайний срок сдачи. Для того, чтобы + пройти задание вовремя и получить сертификат, мы рекомендуем добавить в календарь крайние + сроки сдачи и получать напоминания за 2 дня до их наступления. Управлять появлением данного + сообщения можно в настройках приложения. + Добавить в календарь - Для добавления дедлайнов в календарь приложение должно иметь доступ к календарю. Мы не изменяем и не просматриваем Ваши события, только добавляем дедлайны. + Для добавления дедлайнов в календарь приложение + должно иметь доступ к календарю. Мы не изменяем и не просматриваем Ваши события, только + добавляем дедлайны. + Показывать виджет добавления в календарь Ок Выберите календарь Дедлайны успешно добавлены в календарь - Календарей нет. Попробуйте создать в приложении календаря + Календарей нет. Попробуйте создать в приложении + календаря + Сертификаты Сертификат за курс %s - Сертификат с отличием за курс %s + Сертификат с отличием за курс %s + Результат: %s%% Копировать ссылку Ссылка скопирована Поделиться… Добавить в профиль LinkedIn Пока вы не получили ни одного сертификата - Если Вы выйдите, эта запись будет потеряна + Если Вы выйдите, эта запись будет потеряна + Данный e-mail используется в другом аккаунте Следующий урок Извините, следующий урок недоступен @@ -234,7 +279,9 @@ Прошедшие Применять этот фильтр всегда Принять - Урок не существует или у Вас нет прав на его просмотр + Урок не существует или у Вас нет прав на его + просмотр + Войдите, чтобы продолжить Войти В данном уроке еще нет шагов @@ -243,14 +290,19 @@ Низкое Среднее Высокое - Видео высокого качества занимают больше места и могут загружаться медленнее + Видео высокого качества занимают больше места и могут + загружаться медленнее + Больше не спрашивать - После каждого неправильного решения баллы, которые можно получить за задание, будут уменьшены + После каждого неправильного решения баллы, которые + можно получить за задание, будут уменьшены + У Вас осталась %d попытка, за которую Вы сможете получить баллы У Вас осталось %d попытки, за которые Вы сможете получить баллы У Вас осталось %d попыток, за которые Вы сможете получить баллы - У Вас осталось %d попыток, за которые Вы сможете получить баллы + У Вас осталось %d попыток, за которые Вы сможете получить баллы + У Вас осталась %d попытка @@ -258,11 +310,17 @@ У Вас осталось %d попыток У Вас осталось %d попыток - За Ваши следующие попытки не будут начислены баллы + За Ваши следующие попытки не будут начислены баллы + Прочее - Предупреждать об уроках со штрафами за неверные ответы - Если Вы отправите неверное решение этого задания, то в дальнейшем Вы можете не получить баллы. Вы уверены? - Оставлять экран включенным во время решения задач + Предупреждать об уроках со штрафами за неверные + ответы + + Если Вы отправите неверное решение этого задания, то в + дальнейшем Вы можете не получить баллы. Вы уверены? + + Оставлять экран включенным во время решения задач + Все Обучение Рецензии @@ -271,7 +329,8 @@ Отметить все как прочитанное Пока уведомлений нет Не сейчас - Добавить дедлайны в календарь можно в верхнем меню + Добавить дедлайны в календарь можно в верхнем меню + Получена рецензия Новое сообщение Получен сертификат @@ -280,7 +339,9 @@ Комментарии и ответы Это экзамен, пройдите его в браузере Открыть - Нельзя отправить решение, так как количество попыток было превышено + Нельзя отправить решение, так как количество + попыток было превышено + Слишком много неверных попыток. Попробуйте позже Профиль Решаю без перерыва @@ -295,10 +356,22 @@ дней - Это ваш %dый день, когда Вы решаете задачи без перерыва. Решайте по одной каждый день, чтобы поддержать прогресс. Для этого мы предлагаем Вам включить напоминания. - Это ваш %dй день, когда Вы решаете задачи без перерыва. Решайте по одной каждый день, чтобы поддержать прогресс. Для этого мы предлагаем Вам включить напоминания. - Это ваш %dй день, когда Вы решаете задачи без перерыва. Решайте по одной каждый день, чтобы поддержать прогресс. Для этого мы предлагаем Вам включить напоминания. - Это ваш %dй день, когда Вы решаете задачи без перерыва. Решайте по одной каждый день, чтобы поддержать прогресс. Для этого мы предлагаем Вам включить напоминания. + Это ваш %dый день, когда Вы решаете задачи без перерыва. Решайте по + одной каждый день, чтобы поддержать прогресс. Для этого мы предлагаем Вам включить + напоминания. + + Это ваш %dй день, когда Вы решаете задачи без перерыва. Решайте по + одной каждый день, чтобы поддержать прогресс. Для этого мы предлагаем Вам включить + напоминания. + + Это ваш %dй день, когда Вы решаете задачи без перерыва. Решайте по + одной каждый день, чтобы поддержать прогресс. Для этого мы предлагаем Вам включить + напоминания. + + Это ваш %dй день, когда Вы решаете задачи без перерыва. Решайте по + одной каждый день, чтобы поддержать прогресс. Для этого мы предлагаем Вам включить + напоминания. + Пользователь не найден @@ -309,25 +382,48 @@ Уведомления о занятиях Время учиться! - Вы молодец! Вы решаете уже %d день без перерыва. Не останавливайтесь, решите задачу прямо сейчас! - Вы молодец! Вы решаете уже %d дня без перерыва. Не останавливайтесь, решите задачу прямо сейчас! - Вы молодец! Вы решаете уже %d дней без перерыва. Не останавливайтесь, решите задачу прямо сейчас! - Вы молодец! Вы решаете уже %d дней без перерыва. Не останавливайтесь, решите задачу прямо сейчас! + Вы молодец! Вы решаете уже %d день без перерыва. Не останавливайтесь, + решите задачу прямо сейчас! + + Вы молодец! Вы решаете уже %d дня без перерыва. Не останавливайтесь, + решите задачу прямо сейчас! + + Вы молодец! Вы решаете уже %d дней без перерыва. Не останавливайтесь, + решите задачу прямо сейчас! + + Вы молодец! Вы решаете уже %d дней без перерыва. Не останавливайтесь, + решите задачу прямо сейчас! + - Хорошая работа! Вы увеличили количество дней без перерыва до %d. Так держать! - Обучение требует ежедневной практики. Решите задание прямо сейчас! - Верно! Решайте по одной задаче каждый день, чтобы поддержать прогресс. Для этого мы предлагаем Вам включить напоминания. - Уведомления включены. Вы можете изменить свой выбор в Профиле - Уведомления отключены. Вы можете изменить свой выбор в Профиле - Похоже напоминания не действуют. Мы больше не будем их посылать. Нажмите, чтобы включить снова + Хорошая работа! Вы увеличили количество + дней без перерыва до %d. Так держать! + + Обучение требует ежедневной практики. Решите + задание прямо сейчас! + + Верно! Решайте по одной задаче каждый день, чтобы + поддержать прогресс. Для этого мы предлагаем Вам включить напоминания. + + Уведомления включены. Вы можете изменить + свой выбор в Профиле + + Уведомления отключены. Вы можете изменить свой выбор + в Профиле + + Похоже напоминания не действуют. Мы больше не + будем их посылать. Нажмите, чтобы включить снова + Рекорды обновляются в %s О приложении Условия использования Политика конфиденциальности Позвать друзей Не хочу - Вы всегда можете поделиться ссылкой на курс в меню сверху - Люди, которые проходят курс вместе с друзьями, чаще завершают его. Пригласите друзей прямо сейчас, отправив им ссылку на курс! + Вы всегда можете поделиться ссылкой на курс в меню сверху + + Люди, которые проходят курс вместе с друзьями, чаще + завершают его. Пригласите друзей прямо сейчас, отправив им ссылку на курс! + Проходите курс с друзьями Войти с e-mail Или продолжить с @@ -335,11 +431,13 @@ Учиться Войдите, чтобы мы запомнили Ваши успехи – Шаг %d - Чтобы присоединиться к этому обсуждению Вам нужно Войти + Чтобы присоединиться к этому обсуждению Вам нужно Войти + Чтобы оценивать комментарии Вам нужно Войти Повторить попытку Нажать и перетащить ]]> Введите текст Табличная задача β + Доступ был отозван. Залогиньтесь снова \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dcec2d256d..a41b7fa5c2 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -341,4 +341,5 @@ ]]> Type text Table problem β + Access was revoked. Login again From fd9fa2afae903f82e460e21a1a7446aec98b0c96 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Tue, 14 Feb 2017 16:26:35 +0300 Subject: [PATCH 30/38] restore release check for updating token --- .../org/stepic/droid/web/RetrofitRESTApi.java | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index 609864f0a5..c4a93e164b 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -20,6 +20,8 @@ import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; +import org.joda.time.DateTime; +import org.joda.time.DateTimeZone; import org.stepic.droid.R; import org.stepic.droid.analytic.Analytic; import org.stepic.droid.base.MainApplication; @@ -791,14 +793,13 @@ private boolean isNeededUpdate(AuthenticationStepicResponse response) { Timber.d("Token is null"); return false; } - return true; - -// long timestampStored = sharedPreference.getAccessTokenTimestamp(); -// if (timestampStored == -1) return true; -// -// long nowTemp = DateTime.now(DateTimeZone.UTC).getMillis(); -// long delta = nowTemp - timestampStored; -// long expiresMillis = (response.getExpires_in() - 50) * 1000; -// return delta > expiresMillis;//token expired --> need update + + long timestampStored = sharedPreference.getAccessTokenTimestamp(); + if (timestampStored == -1) return true; + + long nowTemp = DateTime.now(DateTimeZone.UTC).getMillis(); + long delta = nowTemp - timestampStored; + long expiresMillis = (response.getExpires_in() - 50) * 1000; + return delta > expiresMillis;//token expired --> need update } } From e97474455e20449a9a98bd6ad1d85a6b785be922 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Tue, 14 Feb 2017 16:27:44 +0300 Subject: [PATCH 31/38] fix typo in comment --- app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java index c4a93e164b..cf5142a9a7 100644 --- a/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java +++ b/app/src/main/java/org/stepic/droid/web/RetrofitRESTApi.java @@ -783,7 +783,7 @@ private String getAuthHeaderValueForLogged() { return type + " " + access_token; } catch (Exception ex) { analytic.reportError(Analytic.Error.AUTH_ERROR, ex); - //it is unreacheable from app version 1.2 + //it is unreachable from app version 1.2 return ""; } } From 8675fd49995c97742031ac8ce1d83aef841ecc4d Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Tue, 14 Feb 2017 18:03:45 +0300 Subject: [PATCH 32/38] fix opening of relate links in textView #Apps-955 fixed --- .../stepic/droid/core/modules/AppCoreModule.java | 4 ++-- .../util/resolvers/text/TextResolverImpl.kt | 16 ++++++++++++---- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java b/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java index b6e22a1d27..5001b7362c 100644 --- a/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java +++ b/app/src/main/java/org/stepic/droid/core/modules/AppCoreModule.java @@ -286,8 +286,8 @@ FilterApplicator provideFilterApplicator(DefaultFilter defaultFilter, SharedPref @Provides @Singleton - TextResolver provideTextResolver() { - return new TextResolverImpl(); + TextResolver provideTextResolver(IConfig config) { + return new TextResolverImpl(config); } diff --git a/app/src/main/java/org/stepic/droid/util/resolvers/text/TextResolverImpl.kt b/app/src/main/java/org/stepic/droid/util/resolvers/text/TextResolverImpl.kt index 30b71d8717..bf4130f7c0 100644 --- a/app/src/main/java/org/stepic/droid/util/resolvers/text/TextResolverImpl.kt +++ b/app/src/main/java/org/stepic/droid/util/resolvers/text/TextResolverImpl.kt @@ -4,12 +4,19 @@ import android.content.Context import android.os.Build import android.text.Html import android.text.Spanned +import org.stepic.droid.configuration.IConfig import org.stepic.droid.util.HtmlHelper import org.stepic.droid.util.resolvers.CoursePropertyResolver -class TextResolverImpl : TextResolver { - companion object { +class TextResolverImpl(config: IConfig) : TextResolver { + + private val baseUrl: String + init { + baseUrl = config.baseUrl + } + + companion object { val tagHandler = OlLiTagHandler() } @@ -57,10 +64,11 @@ class TextResolverImpl : TextResolver { override fun fromHtml(content: String?): CharSequence { if (content == null) return "" val fromHtml: Spanned + val textWithBaseUrl = content.replace("href=\"/", "href=\"$baseUrl/") if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - fromHtml = Html.fromHtml(content, Html.FROM_HTML_MODE_LEGACY, null, tagHandler) + fromHtml = Html.fromHtml(textWithBaseUrl, Html.FROM_HTML_MODE_LEGACY, null, tagHandler) } else { - fromHtml = Html.fromHtml(content, null, tagHandler) + fromHtml = Html.fromHtml(textWithBaseUrl, null, tagHandler) } return fromHtml } From 645c7aa3900e0d90aa5703360bed16f7715a1b90 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Tue, 14 Feb 2017 18:54:31 +0300 Subject: [PATCH 33/38] not init google Api for sign in and log out if services is not enabled --- .../ui/activities/LaunchActivity.java | 40 ++++++++----------- .../org/stepic/droid/analytic/Analytic.java | 1 + .../droid/ui/activities/MainFeedActivity.java | 8 +++- .../droid/ui/activities/SplashActivity.java | 1 - .../droid/ui/adapters/SocialAuthAdapter.java | 15 +++++-- app/src/main/res/values/strings.xml | 1 + 6 files changed, 36 insertions(+), 30 deletions(-) diff --git a/app/src/classic/java/org.stepic.droid/ui/activities/LaunchActivity.java b/app/src/classic/java/org.stepic.droid/ui/activities/LaunchActivity.java index cc425bf07d..6a885f5574 100644 --- a/app/src/classic/java/org.stepic.droid/ui/activities/LaunchActivity.java +++ b/app/src/classic/java/org.stepic.droid/ui/activities/LaunchActivity.java @@ -6,6 +6,7 @@ import android.graphics.Point; import android.os.Bundle; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.method.LinkMovementMethod; @@ -71,6 +72,7 @@ public class LaunchActivity extends BackToExitActivityBase { @BindString(R.string.terms_message_launch) String termsMessageHtml; + @Nullable private GoogleApiClient googleApiClient; private ProgressDialog progressLogin; private ProgressHandler progressHandler; @@ -116,15 +118,17 @@ public void onClick(View v) { .requestScopes(new Scope(Scopes.EMAIL), new Scope(Scopes.PROFILE)) .requestServerAuthCode(serverClientId) .build(); - googleApiClient = new GoogleApiClient.Builder(this) - .enableAutoManage(this /* FragmentActivity */, new GoogleApiClient.OnConnectionFailedListener() { - @Override - public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { - Toast.makeText(LaunchActivity.this, R.string.connectionProblems, Toast.LENGTH_SHORT).show(); - } - } /* OnConnectionFailedListener */) - .addApi(Auth.GOOGLE_SIGN_IN_API, gso) - .addApi(AppIndex.API).build(); + if (checkPlayServices()) { + googleApiClient = new GoogleApiClient.Builder(this) + .enableAutoManage(this /* FragmentActivity */, new GoogleApiClient.OnConnectionFailedListener() { + @Override + public void onConnectionFailed(@NonNull ConnectionResult connectionResult) { + Toast.makeText(LaunchActivity.this, R.string.connectionProblems, Toast.LENGTH_SHORT).show(); + } + } /* OnConnectionFailedListener */) + .addApi(Auth.GOOGLE_SIGN_IN_API, gso) + .addApi(AppIndex.API).build(); + } initSocialRecycler(googleApiClient); @@ -187,7 +191,7 @@ public void onError(FacebookException exception) { } - private void initSocialRecycler(GoogleApiClient googleApiClient) { + private void initSocialRecycler(@Nullable GoogleApiClient googleApiClient) { float pixelForPadding = DpPixelsHelper.convertDpToPixel(4f, this);//pixelForPadding * (count+1) float widthOfItem = getResources().getDimension(R.dimen.height_of_social);//width == height int count = SocialManager.SocialType.values().length; @@ -210,18 +214,6 @@ private void initSocialRecycler(GoogleApiClient googleApiClient) { socialRecyclerView.setAdapter(new SocialAuthAdapter(this, googleApiClient)); } - @Override - protected void onStart() { - super.onStart(); - googleApiClient.connect(); - } - - @Override - protected void onStop() { - googleApiClient.disconnect(); - super.onStop(); - } - @Override protected void onDestroy() { signInTextView.setOnClickListener(null); @@ -308,7 +300,9 @@ public void onFinish() { new FailLoginSupplementaryHandler() { @Override public void onFailLogin(Throwable t) { - Auth.GoogleSignInApi.signOut(googleApiClient); + if (googleApiClient != null) { + Auth.GoogleSignInApi.signOut(googleApiClient); + } } }, getCourseFromExtra()); } else { diff --git a/app/src/main/java/org/stepic/droid/analytic/Analytic.java b/app/src/main/java/org/stepic/droid/analytic/Analytic.java index dd7df8418a..fcd1af20f0 100644 --- a/app/src/main/java/org/stepic/droid/analytic/Analytic.java +++ b/app/src/main/java/org/stepic/droid/analytic/Analytic.java @@ -77,6 +77,7 @@ interface Interaction { java.lang.String CLICK_FIND_COURSE_LAUNCH = "click_find_courses_launch"; java.lang.String USER_OPEN_IMAGE = "user_open_image"; java.lang.String SCREENSHOT = "screenshot"; + java.lang.String GOOGLE_SOCIAL_IS_NOT_ENABLED = "google_social_is_not_enabled"; } interface Screens { diff --git a/app/src/main/java/org/stepic/droid/ui/activities/MainFeedActivity.java b/app/src/main/java/org/stepic/droid/ui/activities/MainFeedActivity.java index 41830be608..8d4d56b263 100644 --- a/app/src/main/java/org/stepic/droid/ui/activities/MainFeedActivity.java +++ b/app/src/main/java/org/stepic/droid/ui/activities/MainFeedActivity.java @@ -10,6 +10,7 @@ import android.os.Bundle; import android.os.Handler; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.support.design.widget.NavigationView; import android.support.v4.app.DialogFragment; import android.support.v4.app.Fragment; @@ -113,6 +114,7 @@ public class MainFeedActivity extends BackToExitActivityBase private int currentIndex; + @Nullable GoogleApiClient googleApiClient; @Inject @@ -170,7 +172,9 @@ protected void onCreate(Bundle savedInstanceState) { setContentView(R.layout.activity_main_feed); unbinder = ButterKnife.bind(this); notificationClickedCheck(getIntent()); - initGoogleApiClient(); + if (checkPlayServices()) { + initGoogleApiClient(); + } initDrawerHeader(); setUpToolbar(); setUpDrawerLayout(); @@ -643,7 +647,7 @@ public void onLogoutSuccess() { ProgressHelper.dismiss(getSupportFragmentManager(), PROGRESS_LOGOUT_TAG); LoginManager.getInstance().logOut(); VKSdk.logout(); - if (googleApiClient.isConnected()) { + if (googleApiClient != null && googleApiClient.isConnected()) { Auth.GoogleSignInApi.signOut(googleApiClient); } shell.getScreenProvider().showLaunchScreen(this, true, currentIndex); diff --git a/app/src/main/java/org/stepic/droid/ui/activities/SplashActivity.java b/app/src/main/java/org/stepic/droid/ui/activities/SplashActivity.java index b680a67f95..222b637eb5 100644 --- a/app/src/main/java/org/stepic/droid/ui/activities/SplashActivity.java +++ b/app/src/main/java/org/stepic/droid/ui/activities/SplashActivity.java @@ -81,7 +81,6 @@ public void run() { if (checkPlayServices() && !sharedPreferenceHelper.isGcmTokenOk()) { - threadPoolExecutor.execute(new Runnable() { @Override public void run() { diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/SocialAuthAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/SocialAuthAdapter.java index 230c68448f..f087290fd5 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/SocialAuthAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/SocialAuthAdapter.java @@ -1,12 +1,14 @@ package org.stepic.droid.ui.adapters; import android.content.Intent; +import android.support.annotation.Nullable; import android.support.v4.app.FragmentActivity; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ImageView; +import android.widget.Toast; import com.facebook.login.LoginManager; import com.google.android.gms.auth.api.Auth; @@ -45,9 +47,10 @@ public class SocialAuthAdapter extends RecyclerView.Adapter socialList; private FragmentActivity activity; + @Nullable private GoogleApiClient client; - public SocialAuthAdapter(FragmentActivity activity, GoogleApiClient client) { + public SocialAuthAdapter(FragmentActivity activity, @Nullable GoogleApiClient client) { this.client = client; MainApplication.component().inject(this); this.activity = activity; @@ -64,7 +67,6 @@ public SocialViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { @Override public void onBindViewHolder(SocialViewHolder holder, int position) { ISocialType socialType = socialList.get(position); - holder.imageView.setImageDrawable(socialType.getIcon()); } @@ -78,8 +80,13 @@ public void onClick(int position) { ISocialType type = socialList.get(position); analytic.reportEvent(Analytic.Interaction.CLICK_SIGN_IN_SOCIAL, type.getIdentifier()); if (type == SocialManager.SocialType.google) { - Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(client); - activity.startActivityForResult(signInIntent, AppConstants.REQUEST_CODE_GOOGLE_SIGN_IN); + if (client == null) { + analytic.reportEvent(Analytic.Interaction.GOOGLE_SOCIAL_IS_NOT_ENABLED); + Toast.makeText(MainApplication.getAppContext(), R.string.google_services_late, Toast.LENGTH_SHORT).show(); + } else { + Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(client); + activity.startActivityForResult(signInIntent, AppConstants.REQUEST_CODE_GOOGLE_SIGN_IN); + } } else if (type == SocialManager.SocialType.facebook) { List permissions = new ArrayList<>(); permissions.add("email"); diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a41b7fa5c2..8abc1b6d11 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -342,4 +342,5 @@ Type text Table problem β Access was revoked. Login again + Update Google Play Services for signing in with it From 4d4e6baa5a0c881a266a26b1467ec6bd3a81c8a4 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 20 Feb 2017 20:28:05 +0300 Subject: [PATCH 34/38] update version to 1.28 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index d5b84eedd8..db4d02a319 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,8 +31,8 @@ android { applicationId "org.stepic.droid" minSdkVersion minSdk targetSdkVersion 25 - versionCode 121 - versionName "1.27.2" + versionCode 122 + versionName "1.28" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" // Enabling multidex support. multiDexEnabled true From 2dd5f2da8585967dcddcbd363963a35b03f5c609 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Wed, 22 Feb 2017 16:49:41 +0300 Subject: [PATCH 35/38] crash on rotate in comment list #Apps-966 fixed --- .../java/org/stepic/droid/util/svg/GlideSvgRequestFactory.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/stepic/droid/util/svg/GlideSvgRequestFactory.java b/app/src/main/java/org/stepic/droid/util/svg/GlideSvgRequestFactory.java index a9829996cb..b70a4d09b0 100644 --- a/app/src/main/java/org/stepic/droid/util/svg/GlideSvgRequestFactory.java +++ b/app/src/main/java/org/stepic/droid/util/svg/GlideSvgRequestFactory.java @@ -15,7 +15,7 @@ public class GlideSvgRequestFactory { public static GenericRequestBuilder create(Context context, Drawable placeholder) { - return Glide.with(context) + return Glide.with(context.getApplicationContext()) .using(Glide.buildStreamModelLoader(Uri.class, context), InputStream.class) .from(Uri.class) .as(SVG.class) From 34b31fd83155baeb30aa53cd64f35229401cb612 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 27 Feb 2017 14:31:08 +0300 Subject: [PATCH 36/38] latex problem in table quiz is fixed --- .../droid/ui/adapters/TableChoiceAdapter.java | 25 +------------------ .../droid/ui/custom/ProgressLatexView.java | 9 ++++--- 2 files changed, 7 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java index 15911ffe36..6a7e550afd 100644 --- a/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java +++ b/app/src/main/java/org/stepic/droid/ui/adapters/TableChoiceAdapter.java @@ -11,7 +11,6 @@ import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; -import android.view.ViewTreeObserver; import android.widget.CompoundButton; import org.jetbrains.annotations.NotNull; @@ -41,9 +40,6 @@ public class TableChoiceAdapter extends RecyclerView.Adapter answers; - private final int doublePadding; - private final int minUXTouchableSize; - private final int deviceWidthPx75Percent; private boolean isAllEnabled = true; @Override @@ -71,11 +67,6 @@ public TableChoiceAdapter(Activity context, List rows, List colu Display display = context.getWindowManager().getDefaultDisplay(); Point size = new Point(); display.getSize(size); - deviceWidthPx75Percent = (int) (size.x * 0.75); - - doublePadding = (int) context.getResources().getDimension(R.dimen.half_padding) * 2; - - minUXTouchableSize = (int) context.getResources().getDimension(R.dimen.min_ux_touchable_size); } @@ -89,21 +80,7 @@ public GenericViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { return new CheckboxCellViewHolder(v, this); } else if (viewType == DESCRIPTION_TYPE || viewType == ROW_HEADER_TYPE || viewType == COLUMN_HEADER_TYPE) { View v = LayoutInflater.from(parent.getContext()).inflate(R.layout.view_table_quiz_text_cell, parent, false); - final DescriptionViewHolder descriptionViewHolder = new DescriptionViewHolder(v); - - descriptionViewHolder.latexView.getViewTreeObserver().addOnPreDrawListener(new ViewTreeObserver.OnPreDrawListener() { - @Override - public boolean onPreDraw() { - int localWidth = descriptionViewHolder.latexView.getMeasuredWidthOfInnerLayout() + doublePadding; - if (localWidth > deviceWidthPx75Percent) { - descriptionViewHolder.latexView.getLayoutParams().width = Math.min(Math.max(localWidth, minUXTouchableSize), deviceWidthPx75Percent); - descriptionViewHolder.latexView.getViewTreeObserver().removeOnPreDrawListener(this); - } - return true; - } - }); - - return descriptionViewHolder; + return new DescriptionViewHolder(v); } else { throw new IllegalStateException("viewType with index " + viewType + " is not supported in table quiz"); } diff --git a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java index ecd473dae6..a7887070ca 100644 --- a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java +++ b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java @@ -17,7 +17,8 @@ public class ProgressLatexView extends FrameLayout { private LatexSupportableEnhancedFrameLayout optionText; - private String beforeText = null; + public String beforeText = null; + private ProgressBar progressBar; public ProgressLatexView(Context context) { this(context, null); @@ -36,7 +37,7 @@ public ProgressLatexView(Context context, AttributeSet attributeSet, int defStyl private void init(Context context) { LayoutInflater.from(context).inflate(R.layout.progressable_latex_supportable_frame_layout, this, true); optionText = (LatexSupportableEnhancedFrameLayout) findViewById(R.id.latex_text); - final ProgressBar progressBar = (ProgressBar) findViewById(R.id.load_progressbar); + progressBar = (ProgressBar) findViewById(R.id.load_progressbar); setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)); @@ -45,12 +46,14 @@ private void init(Context context) { public void onPageStarted(WebView view, String url, Bitmap favicon) { super.onPageStarted(view, url, favicon); progressBar.setVisibility(VISIBLE); + optionText.setVisibility(INVISIBLE); } @Override public void onPageFinished(WebView view, String url) { super.onPageFinished(view, url); - progressBar.setVisibility(GONE); + progressBar.setVisibility(INVISIBLE); // warning: use INVISIBLE instead of GONE for right LaTeX rendering + optionText.setVisibility(VISIBLE); } }; optionText.getWebView().setWebViewClient(client); From a62e6a6f0bb5b6508df638949ffe883af0b98022 Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 27 Feb 2017 15:15:35 +0300 Subject: [PATCH 37/38] update version to 1.28.1 --- app/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle b/app/build.gradle index db4d02a319..dfe950942b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -31,8 +31,8 @@ android { applicationId "org.stepic.droid" minSdkVersion minSdk targetSdkVersion 25 - versionCode 122 - versionName "1.28" + versionCode 123 + versionName "1.28.1" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" // Enabling multidex support. multiDexEnabled true From 43a6898915bf2fb50f3d1ee574ef18bfdbccbdda Mon Sep 17 00:00:00 2001 From: Kirlill Makarov Date: Mon, 27 Feb 2017 15:18:33 +0300 Subject: [PATCH 38/38] make before Text field in Progress Latex View private --- .../main/java/org/stepic/droid/ui/custom/ProgressLatexView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java index a7887070ca..77bf4c4056 100644 --- a/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java +++ b/app/src/main/java/org/stepic/droid/ui/custom/ProgressLatexView.java @@ -17,7 +17,7 @@ public class ProgressLatexView extends FrameLayout { private LatexSupportableEnhancedFrameLayout optionText; - public String beforeText = null; + private String beforeText = null; private ProgressBar progressBar; public ProgressLatexView(Context context) {