From 18b765f56d076a7c368e744a79dc8a29a53b8358 Mon Sep 17 00:00:00 2001
From: Apostolof
Date: Thu, 5 Oct 2017 13:17:07 +0300
Subject: [PATCH 01/23] Rebase, comments, minor fix, animation tweak
---
.../activities/topic/TopicActivity.java | 113 ++++++++++++++----
.../mthmmy/activities/topic/TopicAdapter.java | 2 +-
.../activities/topic/TopicAnimations.java | 57 +++++----
3 files changed, 117 insertions(+), 55 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 d95b5a7d..c8d6ea9c 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
@@ -65,13 +65,14 @@ import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_
import static gr.thmmy.mthmmy.activities.topic.Posting.replyStatus;
/**
- * Activity for topics. When creating an Intent of this activity you need to bundle a String
- * containing this topics's url using the key {@link #BUNDLE_TOPIC_URL} and a String containing
- * this topic's title using the key {@link #BUNDLE_TOPIC_TITLE}.
+ * Activity for parsing and rendering topics. When creating an Intent of this activity you need to
+ * bundle a String containing this topic's url using the key {@link #BUNDLE_TOPIC_URL}.
+ * You can also bundle a String containing this topic's title, if its available, using the
+ * key {@link #BUNDLE_TOPIC_TITLE} for faster title rendering.
*/
@SuppressWarnings("unchecked")
public class TopicActivity extends BaseActivity {
- //Class variables
+ //Activity's variables
/**
* The key to use when putting topic's url String to {@link TopicActivity}'s Bundle.
*/
@@ -81,46 +82,110 @@ public class TopicActivity extends BaseActivity {
*/
public static final String BUNDLE_TOPIC_TITLE = "TOPIC_TITLE";
private static TopicTask topicTask;
- //About posts
+ private MaterialProgressBar progressBar;
+ private TextView toolbarTitle;
+ /**
+ * Holds this topic's base url. For example a topic with url similar to
+ * "https://www.thmmy.gr/smf/index.php?topic=1.15;topicseen" or
+ * "https://www.thmmy.gr/smf/index.php?topic=1.msg1#msg1"
+ * has the base url "https://www.thmmy.gr/smf/index.php?topic=1"
+ */
+ private static String base_url = "";
+ /**
+ * Holds this topic's title. At first this gets the value of the topic title that came with
+ * bundle and is rendered in the toolbar while parsing this topic. Later, after topic's parsing
+ * is done, it gets the value of {@link #parsedTitle} if bundle title and parsed title differ.
+ */
+ private String topicTitle;
+ /**
+ * Holds this topic's title as parsed from the html source. If this (parsed) title is different
+ * than the one that came with activity's bundle then the parsed title is preferred over the
+ * bundle one and gets rendered in the toolbar.
+ */
+ private String parsedTitle;
+ private RecyclerView recyclerView;
+ /**
+ * Holds the url of this page
+ */
+ private String loadedPageUrl = "";
+ /**
+ * Becomes true after user has posted in this topic and the page is being reloaded and false
+ * when topic's reloading is done
+ */
+ private boolean reloadingPage = false;
+ //Posts related
private TopicAdapter topicAdapter;
+ /**
+ * Holds a list of this topic's posts
+ */
private ArrayList postsList;
+ /**
+ * Gets assigned to {@link #postFocus} when there is no post focus information in the url
+ */
private static final int NO_POST_FOCUS = -1;
+ /**
+ * Holds the index of the post that has focus
+ */
private int postFocus = NO_POST_FOCUS;
+ /**
+ * Holds the position in the {@link #postsList} of the post with focus
+ */
private static int postFocusPosition = 0;
- //Reply
+ //Reply related
private FloatingActionButton replyFAB;
+ /**
+ * Holds this topic's reply url
+ */
private String replyPageUrl = null;
- //Topic's pages
+ //Topic's pages related
+ /**
+ * Holds current page's index (starting from 1, not 0)
+ */
private int thisPage = 1;
+ /**
+ * Holds this topic's number of pages
+ */
private int numberOfPages = 1;
+ /**
+ * Holds a list of this topic's pages urls
+ */
private final SparseArray pagesUrls = new SparseArray<>();
- //Page select
+ //Page select related
+ /**
+ * Used for handling bottom navigation bar's buttons long click user interactions
+ */
private final Handler repeatUpdateHandler = new Handler();
+ /**
+ * Holds the initial time delay before a click on bottom navigation bar is considered long
+ */
private final long INITIAL_DELAY = 500;
private boolean autoIncrement = false;
private boolean autoDecrement = false;
+ /**
+ * Holds the number of pages to be added or subtracted from current page on each step while a
+ * long click is held in either next or previous buttons
+ */
private static final int SMALL_STEP = 1;
+ /**
+ * Holds the number of pages to be added or subtracted from current page on each step while a
+ * long click is held in either first or last buttons
+ */
private static final int LARGE_STEP = 10;
+ /**
+ * Holds the value (index) of the page to be requested when a user interaction with bottom
+ * navigation bar occurs
+ */
private Integer pageRequestValue;
- //Bottom navigation graphics
+ //Bottom navigation bar graphics related
private LinearLayout bottomNavBar;
private ImageButton firstPage;
private ImageButton previousPage;
private TextView pageIndicator;
private ImageButton nextPage;
private ImageButton lastPage;
- //Topic's info
+ //Topic's info related
private SpannableStringBuilder topicTreeAndMods = new SpannableStringBuilder("Loading..."),
topicViewers = new SpannableStringBuilder("Loading...");
- //Other variables
- private MaterialProgressBar progressBar;
- private TextView toolbarTitle;
- private static String base_url = "";
- private String topicTitle;
- private String parsedTitle;
- private RecyclerView recyclerView;
- private String loadedPageUrl = "";
- private boolean reloadingPage = false;
@Override
@@ -464,12 +529,10 @@ public class TopicActivity extends BaseActivity {
//------------------------------------BOTTOM NAV BAR METHODS END------------------------------------
/**
- * An {@link AsyncTask} that handles asynchronous fetching of a topic page and parsing it's
- * data. {@link AsyncTask#onPostExecute(Object) OnPostExecute} method calls {@link RecyclerView#swapAdapter}
- * to build graphics.
- *
- *
Calling TopicTask's {@link AsyncTask#execute execute} method needs to have profile's url
- * as String parameter!
+ * An {@link AsyncTask} that handles asynchronous fetching of this topic page and parsing of it's
+ * data.
+ *
TopicTask's {@link AsyncTask#execute execute} method needs a topic's url as String
+ * parameter.
*/
class TopicTask extends AsyncTask {
private static final int SUCCESS = 0;
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
index fd95cc71..6fd1a57c 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
@@ -396,7 +396,7 @@ class TopicAdapter extends RecyclerView.Adapter {
TopicAnimations.animateUserExtraInfoVisibility(holder.username,
holder.subject, Color.parseColor("#FFFFFF"),
- Color.parseColor("#757575"), v);
+ Color.parseColor("#757575"), (LinearLayout) v);
}
});
} else {
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAnimations.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAnimations.java
index ae4516ef..4cabbdfb 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAnimations.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAnimations.java
@@ -4,68 +4,67 @@ import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.text.TextUtils;
import android.view.View;
+import android.widget.LinearLayout;
import android.widget.TextView;
class TopicAnimations {
-//--------------------------USER'S INFO VISIBILITY CHANGE ANIMATION METHOD--------------------------
-
/**
* Method that animates view's visibility changes for user's extra info
*/
- static void animateUserExtraInfoVisibility(TextView username, TextView subject,
- int expandedColor, int collapsedColor,
- final View userExtra) {
- //If the view is gone fade it in
- if (userExtra.getVisibility() == View.GONE) {
- userExtra.clearAnimation();
- userExtra.setVisibility(View.VISIBLE);
- userExtra.setAlpha(0.0f);
+ static void animateUserExtraInfoVisibility(final TextView username, final TextView subject,
+ int expandedColor, final int collapsedColor,
+ final LinearLayout userExtraInfo) {
+ //If the view is currently gone it fades it in
+ if (userExtraInfo.getVisibility() == View.GONE) {
+ userExtraInfo.clearAnimation();
+ userExtraInfo.setVisibility(View.VISIBLE);
+ userExtraInfo.setAlpha(0.0f);
- // Start the animation
- userExtra.animate()
+ //Animation start
+ userExtraInfo.animate()
.alpha(1.0f)
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- userExtra.setVisibility(View.VISIBLE);
+ userExtraInfo.setVisibility(View.VISIBLE);
}
});
- //Show full username
+ //Shows full username
username.setMaxLines(Integer.MAX_VALUE); //As in the android sourcecode
username.setEllipsize(null);
- //Show full subject
+ //Shows full subject
subject.setTextColor(expandedColor);
subject.setMaxLines(Integer.MAX_VALUE); //As in the android sourcecode
subject.setEllipsize(null);
}
- //If the view is visible fade it out
+ //If the view is currently visible then it fades it out
else {
- userExtra.clearAnimation();
+ userExtraInfo.clearAnimation();
- // Start the animation
- userExtra.animate()
+ //Animation start
+ userExtraInfo.animate()
.alpha(0.0f)
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
- userExtra.setVisibility(View.GONE);
- }
- });
+ userExtraInfo.setVisibility(View.GONE);
- username.setMaxLines(1); //As in the android sourcecode
- username.setEllipsize(TextUtils.TruncateAt.END);
+ //Ellipsizes username
+ username.setMaxLines(1); //As in the android sourcecode
+ username.setEllipsize(TextUtils.TruncateAt.END);
- subject.setTextColor(collapsedColor);
- subject.setMaxLines(1); //As in the android sourcecode
- subject.setEllipsize(TextUtils.TruncateAt.END);
+ //Ellipsizes subject
+ subject.setTextColor(collapsedColor);
+ subject.setMaxLines(1); //As in the android sourcecode
+ subject.setEllipsize(TextUtils.TruncateAt.END);
+ }
+ });
}
}
-//------------------------POST'S INFO VISIBILITY CHANGE ANIMATION METHOD END------------------------
-
}
From d03cd6d0827d3f0fdcf83d67b76e3aff6113c8fa Mon Sep 17 00:00:00 2001
From: Apostolof
Date: Thu, 5 Oct 2017 18:03:36 +0300
Subject: [PATCH 02/23] User profiles with zero posts fix
---
.../latestPosts/LatestPostsAdapter.java | 9 ++
.../latestPosts/LatestPostsFragment.java | 14 ++-
.../profile/stats/StatsFragment.java | 86 ++++++++++++-------
.../activities/topic/TopicActivity.java | 3 +-
.../fragment_latest_posts_empty_message.xml | 14 +++
app/src/main/res/values/strings.xml | 1 +
6 files changed, 90 insertions(+), 37 deletions(-)
create mode 100644 app/src/main/res/layout/fragment_latest_posts_empty_message.xml
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java
index 9a2696ac..9e8c40ea 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java
@@ -1,6 +1,7 @@
package gr.thmmy.mthmmy.activities.profile.latestPosts;
import android.support.v7.widget.RecyclerView;
+import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@@ -21,6 +22,7 @@ import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
* specified {@link LatestPostsFragment.LatestPostsFragmentInteractionListener}.
*/
class LatestPostsAdapter extends RecyclerView.Adapter {
+ private final int VIEW_TYPE_EMPTY = -1;
private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1;
final private LatestPostsFragment.LatestPostsFragmentInteractionListener interactionListener;
@@ -38,11 +40,18 @@ class LatestPostsAdapter extends RecyclerView.Adapter {
@Override
public int getItemViewType(int position) {
+ if (parsedTopicSummaries.get(position) == null && position == 0) return VIEW_TYPE_EMPTY;
return parsedTopicSummaries.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
}
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ if (viewType == VIEW_TYPE_EMPTY) {
+ Log.d("This", "in");
+ View view = LayoutInflater.from(parent.getContext()).
+ inflate(R.layout.fragment_latest_posts_empty_message, parent, false);
+ return new RecyclerView.ViewHolder(view){};
+ }
if (viewType == VIEW_TYPE_ITEM) {
View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.fragment_latest_posts_row, parent, false);
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java
index 11cb671e..a8d75451 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java
@@ -50,6 +50,7 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap
private LatestPostsTask profileLatestPostsTask;
private MaterialProgressBar progressBar;
private boolean isLoadingMore;
+ private boolean userHasPosts = true;
private static final int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount;
@@ -100,7 +101,8 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap
totalItemCount = layoutManager.getItemCount();
lastVisibleItem = layoutManager.findLastVisibleItemPosition();
- if (!isLoadingMore && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
+ if (userHasPosts && !isLoadingMore &&
+ totalItemCount <= (lastVisibleItem + visibleThreshold)) {
isLoadingMore = true;
onLoadMore();
}
@@ -126,7 +128,7 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
- if (parsedTopicSummaries.isEmpty()) {
+ if (parsedTopicSummaries.isEmpty() && userHasPosts) {
profileLatestPostsTask = new LatestPostsTask();
profileLatestPostsTask.execute(profileUrl + ";sa=showPosts");
pagesLoaded = 1;
@@ -186,6 +188,7 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap
//TODO: better parse error handling (ParseException etc.)
private boolean parseLatestPosts(Document latestPostsPage) {
+ //td:contains( Sorry, no matches were found)
Elements latestPostsRows = latestPostsPage.
select("td:has(table:Contains(Show Posts)):not([style]) > table");
if (latestPostsRows.isEmpty()) {
@@ -197,6 +200,13 @@ public class LatestPostsFragment extends BaseFragment implements LatestPostsAdap
parsedTopicSummaries.remove(parsedTopicSummaries.size() - 1);
}
+ if (!latestPostsRows.select("td:contains(Sorry, no matches were found)").isEmpty() ||
+ !latestPostsRows.select("td:contains(Δυστυχώς δεν βρέθηκε τίποτα)").isEmpty()){
+ userHasPosts = false;
+ parsedTopicSummaries.add(null);
+ return true;
+ }
+
for (Element row : latestPostsRows) {
String pTopicUrl, pTopicTitle, pDateTime, pPost;
if (Integer.parseInt(row.attr("cellpadding")) == 4) {
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java
index fc1867c0..5822d635 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java
@@ -56,6 +56,7 @@ public class StatsFragment extends Fragment {
private MaterialProgressBar progressBar;
private boolean haveParsed = false;
+ private boolean userHasPosts = true;
private String generalStatisticsTitle = "", generalStatistics = "", postingActivityByTimeTitle = "", mostPopularBoardsByPostsTitle = "", mostPopularBoardsByActivityTitle = "";
final private List postingActivityByTime = new ArrayList<>();
final private List mostPopularBoardsByPosts = new ArrayList<>(), mostPopularBoardsByActivity = new ArrayList<>();
@@ -123,6 +124,7 @@ public class StatsFragment extends Fragment {
* as String parameter!