From 55afa63852df304110b36af1063043b83227ce23 Mon Sep 17 00:00:00 2001
From: Thodoris1999
Date: Fri, 10 Aug 2018 15:26:16 +0300
Subject: [PATCH] add/improve topic's behavior on network errors
---
.../activities/topic/TopicActivity.java | 50 ++++++++++++++-----
.../activities/topic/tasks/DeleteTask.java | 2 +-
.../topic/tasks/PrepareForReply.java | 13 ++---
.../topic/tasks/PrepareForReplyResult.java | 8 ++-
.../mthmmy/utils/ScrollAwareFABBehavior.java | 15 +++++-
.../utils/ScrollAwareLinearBehavior.java | 17 ++++++-
.../mthmmy/viewmodel/TopicViewModel.java | 18 ++++---
app/src/main/res/layout/activity_topic.xml | 10 ++++
app/src/main/res/values/strings.xml | 4 ++
9 files changed, 106 insertions(+), 31 deletions(-)
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
index f755838a..c4dff2d7 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
@@ -11,6 +11,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.design.widget.FloatingActionButton;
+import android.support.design.widget.Snackbar;
import android.support.v7.app.AlertDialog;
import android.support.v7.app.AppCompatDelegate;
import android.support.v7.widget.RecyclerView;
@@ -30,7 +31,6 @@ import android.widget.TextView;
import android.widget.Toast;
import java.util.ArrayList;
-import java.util.Objects;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.topic.tasks.DeleteTask;
@@ -110,6 +110,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
private TextView pageIndicator;
private ImageButton nextPage;
private ImageButton lastPage;
+ private Snackbar snackbar;
private TopicViewModel viewModel;
//Fix for vector drawables on android <21
@@ -449,6 +450,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
@Override
public void onTopicTaskStarted() {
progressBar.setVisibility(ProgressBar.VISIBLE);
+ if (snackbar != null) snackbar.dismiss();
}
@Override
@@ -469,7 +471,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
if (result)
viewModel.reloadPage();
else
- Toast.makeText(TopicActivity.this, "Post deleted!", Toast.LENGTH_SHORT).show();
+ Toast.makeText(getBaseContext(), "Delete failed!", Toast.LENGTH_SHORT).show();
}
});
viewModel.setReplyFinishListener(new ReplyTask.ReplyTaskCallbacks() {
@@ -498,7 +500,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
viewModel.reloadPage();
}
} else {
- Toast.makeText(TopicActivity.this, "Post failed!", Toast.LENGTH_SHORT).show();
+ Toast.makeText(getBaseContext(), "Post failed!", Toast.LENGTH_SHORT).show();
recyclerView.getChildAt(postsList.size() - 1).setAlpha(1);
recyclerView.getChildAt(postsList.size() - 1).setEnabled(true);
}
@@ -539,7 +541,7 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
viewModel.setEditingPost(false);
viewModel.reloadPage();
} else {
- Toast.makeText(TopicActivity.this, "Edit failed!", Toast.LENGTH_SHORT).show();
+ Toast.makeText(getBaseContext(), "Edit failed!", Toast.LENGTH_SHORT).show();
recyclerView.getChildAt(viewModel.getPostBeingEditedPosition()).setAlpha(1);
recyclerView.getChildAt(viewModel.getPostBeingEditedPosition()).setEnabled(true);
}
@@ -594,17 +596,37 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
});
viewModel.getTopicTaskResultCode().observe(this, resultCode -> {
if (resultCode == null) return;
+ progressBar.setVisibility(ProgressBar.GONE);
switch (resultCode) {
case SUCCESS:
paginationEnabled(true);
- progressBar.setVisibility(ProgressBar.GONE);
break;
case NETWORK_ERROR:
- Toast.makeText(getBaseContext(), "Network Error", Toast.LENGTH_SHORT).show();
+ if (viewModel.getPostsList().getValue() == null) {
+ // no page has been loaded yet. Give user the ability to refresh
+ recyclerView.setVisibility(View.GONE);
+ TextView errorTextview = findViewById(R.id.error_textview);
+ errorTextview.setText(getString(R.string.network_error_retry_prompt));
+ errorTextview.setVisibility(View.VISIBLE);
+ errorTextview.setOnClickListener(view -> {
+ viewModel.reloadPage();
+ errorTextview.setVisibility(View.GONE);
+ recyclerView.setVisibility(View.VISIBLE);
+ });
+ } else {
+ // a page has already been loaded
+ viewModel.setPageIndicatorIndex(viewModel.getCurrentPageIndex(), false);
+ snackbar = Snackbar.make(findViewById(R.id.main_content),
+ R.string.generic_network_error, Snackbar.LENGTH_INDEFINITE);
+ snackbar.setAction(R.string.retry, view -> viewModel.reloadPage());
+ snackbar.show();
+ }
break;
case UNAUTHORIZED:
- progressBar.setVisibility(ProgressBar.GONE);
- Toast.makeText(getBaseContext(), "This topic is either missing or off limits to you", Toast.LENGTH_SHORT).show();
+ recyclerView.setVisibility(View.GONE);
+ TextView errorTextview = findViewById(R.id.error_textview);
+ errorTextview.setText(getString(R.string.unauthorized_topic_error));
+ errorTextview.setVisibility(View.VISIBLE);
break;
default:
//Parse failed - should never happen
@@ -615,26 +637,30 @@ public class TopicActivity extends BaseActivity implements TopicAdapter.OnPostFo
}
});
viewModel.getPrepareForReplyResult().observe(this, prepareForReplyResult -> {
- if (prepareForReplyResult != null) {
+ progressBar.setVisibility(ProgressBar.GONE);
+ if (prepareForReplyResult != null && prepareForReplyResult.isSuccessful()) {
//prepare for a reply
+ viewModel.setWritingReply(true);
postsList.add(Post.newQuickReply());
topicAdapter.notifyItemInserted(postsList.size());
recyclerView.scrollToPosition(postsList.size() - 1);
- progressBar.setVisibility(ProgressBar.GONE);
replyFAB.hide();
bottomNavBar.setVisibility(View.GONE);
+ } else {
+ Snackbar.make(findViewById(R.id.main_content), getString(R.string.generic_network_error), Snackbar.LENGTH_SHORT).show();
}
-
});
viewModel.getPrepareForEditResult().observe(this, result -> {
+ progressBar.setVisibility(ProgressBar.GONE);
if (result != null && result.isSuccessful()) {
viewModel.setEditingPost(true);
postsList.get(result.getPosition()).setPostType(Post.TYPE_EDIT);
topicAdapter.notifyItemChanged(result.getPosition());
recyclerView.scrollToPosition(result.getPosition());
- progressBar.setVisibility(ProgressBar.GONE);
replyFAB.hide();
bottomNavBar.setVisibility(View.GONE);
+ } else {
+ Snackbar.make(findViewById(R.id.main_content), getString(R.string.generic_network_error), Snackbar.LENGTH_SHORT).show();
}
});
}
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java
index 5d4a0531..f3523953 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/DeleteTask.java
@@ -41,7 +41,7 @@ public class DeleteTask extends AsyncTask {
return true;
default:
Timber.e("Something went wrong. Request string: %s", delete.toString());
- return true;
+ return false;
}
} catch (IOException e) {
Timber.e(e, "Delete failed.");
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReply.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReply.java
index 42ea2774..2e0d7148 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReply.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/tasks/PrepareForReply.java
@@ -33,18 +33,13 @@ public class PrepareForReply extends AsyncTask {
@@ -48,4 +49,16 @@ public class ScrollAwareFABBehavior extends CoordinatorLayout.BehaviorWhen a nested ScrollView is scrolled down, the view will disappear.
- * When the ScrollView is scrolled back up, the view will reappear.
+ * When the ScrollView is scrolled back up, the view will reappear. It also pushes the
+ * {@link android.widget.LinearLayout} up when a {@link Snackbar} is shown
+ *
*/
@SuppressWarnings("unused")
public class ScrollAwareLinearBehavior extends CoordinatorLayout.Behavior {
@@ -111,4 +114,16 @@ public class ScrollAwareLinearBehavior extends CoordinatorLayout.Behavior
animator.start();
}
+
+ @Override
+ public boolean layoutDependsOn(CoordinatorLayout parent, View child, View dependency) {
+ return dependency instanceof Snackbar.SnackbarLayout;
+ }
+
+ @Override
+ public boolean onDependentViewChanged(CoordinatorLayout parent, View child, View dependency) {
+ float translationY = Math.min(0, dependency.getTranslationY() - dependency.getHeight());
+ child.setTranslationY(translationY);
+ return true;
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java b/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
index abc9ac09..080414ab 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/viewmodel/TopicViewModel.java
@@ -84,7 +84,7 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
}
public void reloadPage() {
- if (topicUrl == null) throw new NullPointerException("No topic task has finished yet!");
+ if (topicUrl == null) throw new NullPointerException("No topic task has been requested yet!");
loadUrl(topicUrl);
}
@@ -194,7 +194,6 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
@Override
public void onPrepareForReplyFinished(PrepareForReplyResult result) {
- writingReply = true;
prepareForReplyResult.setValue(result);
}
@@ -207,26 +206,31 @@ public class TopicViewModel extends BaseViewModel implements TopicTask.OnTopicTa
public void incrementPageRequestValue(int step, boolean changePage) {
if (pageIndicatorIndex.getValue() == null)
throw new NullPointerException("No page has been loaded yet!");
- if (pageIndicatorIndex.getValue() <= pageCount - step) {
+ int oldIndicatorIndex = pageIndicatorIndex.getValue();
+ if (oldIndicatorIndex <= pageCount - step) {
pageIndicatorIndex.setValue(pageIndicatorIndex.getValue() + step);
} else
pageIndicatorIndex.setValue(pageCount);
- if (changePage) performPageChange();
+ if (changePage && oldIndicatorIndex != pageIndicatorIndex.getValue()) performPageChange();
}
public void decrementPageRequestValue(int step, boolean changePage) {
if (pageIndicatorIndex.getValue() == null)
throw new NullPointerException("No page has been loaded yet!");
- if (pageIndicatorIndex.getValue() >= step) {
+ int oldIndicatorIndex = pageIndicatorIndex.getValue();
+ if (oldIndicatorIndex > step) {
pageIndicatorIndex.setValue(pageIndicatorIndex.getValue() - step);
} else
pageIndicatorIndex.setValue(1);
- if (changePage) performPageChange();
+ if (changePage && oldIndicatorIndex != pageIndicatorIndex.getValue()) performPageChange();
}
public void setPageIndicatorIndex(int pageIndicatorIndex, boolean changePage) {
+ if (this.pageIndicatorIndex.getValue() == null)
+ throw new NullPointerException("No page has been loaded yet!");
+ int oldIndicatorIndex = this.pageIndicatorIndex.getValue();
this.pageIndicatorIndex.setValue(pageIndicatorIndex);
- if (changePage) performPageChange();
+ if (changePage && oldIndicatorIndex != this.pageIndicatorIndex.getValue()) performPageChange();
}
// <-------------Just getters, setters and helper methods below here---------------->
diff --git a/app/src/main/res/layout/activity_topic.xml b/app/src/main/res/layout/activity_topic.xml
index cb98088e..cb3a1072 100644
--- a/app/src/main/res/layout/activity_topic.xml
+++ b/app/src/main/res/layout/activity_topic.xml
@@ -47,6 +47,16 @@
app:layout_behavior="@string/appbar_scrolling_view_behavior">
+
+
Subject…
Submit
Message…
+ Could not connect to thmmy.gr \n\n Tap to retry
+ Network error
+ retry
+ This topic is either missing or off limits to you
Username