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