Browse Source

Code cleanup, fixes and commenting

pull/24/head
Apostolos Fanakis 8 years ago
parent
commit
d9c55a258f
  1. 22
      app/src/main/assets/style.css
  2. 8
      app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java
  3. 36
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java
  4. 23
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java
  5. 41
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java
  6. 21
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java
  7. 49
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java
  8. 14
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  9. 86
      app/src/main/res/layout/activity_board.xml

22
app/src/main/assets/style.css

@ -100,7 +100,7 @@ body
/* By default (td, body..) use verdana in black. */ /* By default (td, body..) use verdana in black. */
body, td, th , tr body, td, th , tr
{ {
color: #000000; color: #FFFFFF;
font-size: small; font-size: small;
font-family: Trebuchet, sans-serif; font-family: Trebuchet, sans-serif;
} }
@ -110,7 +110,7 @@ body, td, th , tr
/* Input boxes - just a bit smaller than normal so they align well. */ /* Input boxes - just a bit smaller than normal so they align well. */
input, textarea, button input, textarea, button
{ {
color: #000000; color: #FFFFFF;
font-family: Trebuchet, sans-serif; font-family: Trebuchet, sans-serif;
border: 1px solid #aaa; border: 1px solid #aaa;
} }
@ -122,7 +122,7 @@ input, button
textarea textarea
{ {
font-size: 100%; font-size: 100%;
color: #000000; color: #FFFFFF;
font-family: Trebuchet, sans-serif; font-family: Trebuchet, sans-serif;
} }
@ -136,7 +136,7 @@ select
{ {
font-size: 90%; font-size: 90%;
font-weight: normal; font-weight: normal;
color: #000000; color: #FFFFFF;
font-family: Trebuchet, sans-serif; font-family: Trebuchet, sans-serif;
} }
@ -170,7 +170,7 @@ a img
/* A code block - maybe even PHP ;). */ /* A code block - maybe even PHP ;). */
.code .code
{ {
color: #000000; color: #26A69A;
background-color: #dddddd; background-color: #dddddd;
font-family: "Comic Sans MS", "times new roman", monospace; font-family: "Comic Sans MS", "times new roman", monospace;
font-size: x-small; font-size: x-small;
@ -228,17 +228,17 @@ a img
/* Alternating backgrounds for posts, and several other sections of the forum. */ /* Alternating backgrounds for posts, and several other sections of the forum. */
.windowbg .windowbg
{ {
color: #000000; color: #FFFFFF;
background-color: #E3E6E1; background-color: #E3E6E1;
} }
.windowbg2 .windowbg2
{ {
color: #000000; color: #FFFFFF;
background-color: #F2F5F0; background-color: #F2F5F0;
} }
.windowbg3 .windowbg3
{ {
color: #000000; color: #FFFFFF;
background-color: #E1E8E0; background-color: #E1E8E0;
} }
/* the today container in calendar */ /* the today container in calendar */
@ -267,7 +267,7 @@ a img
{ {
font-weight: bold; font-weight: bold;
background-color: #e4e2e0; background-color: #e4e2e0;
color: #000000; color: #FFFFFF;
} }
/* This is used for tables that have a grid/border background color (such as the topic listing.) */ /* This is used for tables that have a grid/border background color (such as the topic listing.) */
.bordercolor .bordercolor
@ -517,3 +517,7 @@ img
opacity: 0.7; opacity: 0.7;
z-index: 2; z-index: 2;
} }
.customSignature{
background: #323232;
}

8
app/src/main/java/gr/thmmy/mthmmy/activities/main/MainActivity.java

@ -20,8 +20,8 @@ import gr.thmmy.mthmmy.activities.topic.TopicActivity;
import gr.thmmy.mthmmy.data.Board; import gr.thmmy.mthmmy.data.Board;
import gr.thmmy.mthmmy.data.TopicSummary; import gr.thmmy.mthmmy.data.TopicSummary;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.EXTRAS_BOARD_TITLE; import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.EXTRAS_BOARD_URL; import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE; import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_TITLE;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL; import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
@ -96,8 +96,8 @@ public class MainActivity extends BaseActivity implements RecentFragment.RecentF
@Override @Override
public void onForumFragmentInteraction(Board board) { public void onForumFragmentInteraction(Board board) {
Intent i = new Intent(MainActivity.this, BoardActivity.class); Intent i = new Intent(MainActivity.this, BoardActivity.class);
i.putExtra(EXTRAS_BOARD_URL, board.getBoardURL()); i.putExtra(BUNDLE_BOARD_URL, board.getBoardURL());
i.putExtra(EXTRAS_BOARD_TITLE, board.getTitle()); i.putExtra(BUNDLE_BOARD_TITLE, board.getTitle());
startActivity(i); startActivity(i);
} }

36
app/src/main/java/gr/thmmy/mthmmy/activities/profile/ProfileActivity.java

@ -51,15 +51,10 @@ import static gr.thmmy.mthmmy.activities.topic.TopicActivity.BUNDLE_TOPIC_URL;
/** /**
* Activity for user profile. When creating an Intent of this activity you need to bundle a <b>String</b> * Activity for user profile. When creating an Intent of this activity you need to bundle a <b>String</b>
* containing this user's profile url using the key {@link #BUNDLE_PROFILE_URL}, a <b>String</b> containing * containing this user's profile url using the key {@link #BUNDLE_PROFILE_URL}, a <b>String</b> containing
* this user's avatar url and a <b>String</b> containing the username. * this user's avatar url using the key {@link #BUNDLE_THUMBNAIL_URL} and a <b>String</b> containing
* the username using the key {@link #BUNDLE_USERNAME}.
*/ */
public class ProfileActivity extends BaseActivity implements LatestPostsFragment.LatestPostsFragmentInteractionListener{ public class ProfileActivity extends BaseActivity implements LatestPostsFragment.LatestPostsFragmentInteractionListener {
//Graphics
private TextView personalTextView;
private MaterialProgressBar progressBar;
private FloatingActionButton replyFAB;
private ViewPager viewPager;
//Other variables and constants
/** /**
* Debug Tag for logging debug output to LogCat * Debug Tag for logging debug output to LogCat
*/ */
@ -79,6 +74,12 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
*/ */
public static final String BUNDLE_USERNAME = "USERNAME"; public static final String BUNDLE_USERNAME = "USERNAME";
private static final int THUMBNAIL_SIZE = 200; private static final int THUMBNAIL_SIZE = 200;
private TextView personalTextView;
private MaterialProgressBar progressBar;
private FloatingActionButton replyFAB;
private ViewPager viewPager;
private ProfileTask profileTask; private ProfileTask profileTask;
private String personalText; private String personalText;
private String profileUrl; private String profileUrl;
@ -90,6 +91,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
Bundle extras = getIntent().getExtras(); Bundle extras = getIntent().getExtras();
String thumbnailUrl = extras.getString(BUNDLE_THUMBNAIL_URL); String thumbnailUrl = extras.getString(BUNDLE_THUMBNAIL_URL);
if (thumbnailUrl == null) thumbnailUrl = "";
String username = extras.getString(BUNDLE_USERNAME); String username = extras.getString(BUNDLE_USERNAME);
profileUrl = extras.getString(BUNDLE_PROFILE_URL); profileUrl = extras.getString(BUNDLE_PROFILE_URL);
@ -107,7 +109,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
progressBar = (MaterialProgressBar) findViewById(R.id.progressBar); progressBar = (MaterialProgressBar) findViewById(R.id.progressBar);
ImageView thumbnailView = (ImageView) findViewById(R.id.user_thumbnail); ImageView thumbnailView = (ImageView) findViewById(R.id.user_thumbnail);
if (thumbnailUrl != null && !Objects.equals(thumbnailUrl, "")) if (!Objects.equals(thumbnailUrl, ""))
//noinspection ConstantConditions //noinspection ConstantConditions
Picasso.with(this) Picasso.with(this)
.load(thumbnailUrl) .load(thumbnailUrl)
@ -156,7 +158,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
}); });
profileTask = new ProfileTask(); profileTask = new ProfileTask();
profileTask.execute(profileUrl); //Attempt data parsing profileTask.execute(profileUrl); //Attempts data parsing
} }
@Override @Override
@ -170,15 +172,19 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
public void onLatestPostsFragmentInteraction(TopicSummary topicSummary) { public void onLatestPostsFragmentInteraction(TopicSummary topicSummary) {
Intent i = new Intent(ProfileActivity.this, TopicActivity.class); Intent i = new Intent(ProfileActivity.this, TopicActivity.class);
i.putExtra(BUNDLE_TOPIC_URL, topicSummary.getTopicUrl()); i.putExtra(BUNDLE_TOPIC_URL, topicSummary.getTopicUrl());
i.putExtra(BUNDLE_TOPIC_TITLE, topicSummary.getTitle()); i.putExtra(BUNDLE_TOPIC_TITLE, topicSummary.getTitle().substring(topicSummary.getTitle().
lastIndexOf("/ ") + 2));
startActivity(i); startActivity(i);
} }
/** /**
* An {@link AsyncTask} that handles asynchronous fetching of a profile page and parsing this * An {@link AsyncTask} that handles asynchronous fetching of a profile page and parsing this
* user's personal text. * user's personal text. The {@link Document} resulting from the parse is stored for use in
* the {@link SummaryFragment}.
* <p>ProfileTask's {@link AsyncTask#execute execute} method needs a profile's url as String * <p>ProfileTask's {@link AsyncTask#execute execute} method needs a profile's url as String
* parameter!</p> * parameter!</p>
*
* @see Jsoup
*/ */
public class ProfileTask extends AsyncTask<String, Void, Boolean> { public class ProfileTask extends AsyncTask<String, Void, Boolean> {
//Class variables //Class variables
@ -225,6 +231,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
protected void onPostExecute(Boolean result) { protected void onPostExecute(Boolean result) {
if (!result) { //Parse failed! if (!result) { //Parse failed!
Report.d(TAG, "Parse failed!");
Toast.makeText(getBaseContext() Toast.makeText(getBaseContext()
, "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show(); , "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show();
finish(); finish();
@ -247,6 +254,7 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
/** /**
* Simple method that sets up the {@link ViewPager} of a {@link ProfileActivity} * Simple method that sets up the {@link ViewPager} of a {@link ProfileActivity}
*
* @param viewPager the ViewPager to be setup * @param viewPager the ViewPager to be setup
* @param profilePage this profile's parsed page * @param profilePage this profile's parsed page
*/ */
@ -265,18 +273,22 @@ public class ProfileActivity extends BaseActivity implements LatestPostsFragment
ViewPagerAdapter(FragmentManager manager) { ViewPagerAdapter(FragmentManager manager) {
super(manager); super(manager);
} }
@Override @Override
public Fragment getItem(int position) { public Fragment getItem(int position) {
return mFragmentList.get(position); return mFragmentList.get(position);
} }
@Override @Override
public int getCount() { public int getCount() {
return mFragmentList.size(); return mFragmentList.size();
} }
void addFrag(Fragment fragment, String title) { void addFrag(Fragment fragment, String title) {
mFragmentList.add(fragment); mFragmentList.add(fragment);
mFragmentTitleList.add(title); mFragmentTitleList.add(title);
} }
@Override @Override
public CharSequence getPageTitle(int position) { public CharSequence getPageTitle(int position) {
return mFragmentTitleList.get(position); return mFragmentTitleList.get(position);

23
app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java

@ -1,6 +1,5 @@
package gr.thmmy.mthmmy.activities.profile.latestPosts; package gr.thmmy.mthmmy.activities.profile.latestPosts;
import android.annotation.SuppressLint;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -16,12 +15,15 @@ import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import static gr.thmmy.mthmmy.activities.profile.latestPosts.LatestPostsFragment.parsedTopicSummaries; import static gr.thmmy.mthmmy.activities.profile.latestPosts.LatestPostsFragment.parsedTopicSummaries;
/**
* {@link RecyclerView.Adapter} that can display a {@link TopicSummary} and makes a call to the
* specified {@link LatestPostsFragment.LatestPostsFragmentInteractionListener}.
*/
class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "LatestPostsAdapter"; private static final String TAG = "LatestPostsAdapter";
private final int VIEW_TYPE_ITEM = 0; private final int VIEW_TYPE_ITEM = 0;
private final int VIEW_TYPE_LOADING = 1; private final int VIEW_TYPE_LOADING = 1;
//private OnLoadMoreListener mOnLoadMoreListener; final private LatestPostsFragment.LatestPostsFragmentInteractionListener interactionListener;
private LatestPostsFragment.LatestPostsFragmentInteractionListener interactionListener;
LatestPostsAdapter(BaseFragment.FragmentInteractionListener interactionListener){ LatestPostsAdapter(BaseFragment.FragmentInteractionListener interactionListener){
this.interactionListener = (LatestPostsFragment.LatestPostsFragmentInteractionListener) interactionListener; this.interactionListener = (LatestPostsFragment.LatestPostsFragmentInteractionListener) interactionListener;
@ -31,10 +33,6 @@ class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
void onLoadMore(); void onLoadMore();
} }
void setOnLoadMoreListener(OnLoadMoreListener mOnLoadMoreListener) {
//this.mOnLoadMoreListener = mOnLoadMoreListener;
}
@Override @Override
public int getItemViewType(int position) { public int getItemViewType(int position) {
return parsedTopicSummaries.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM; return parsedTopicSummaries.get(position) == null ? VIEW_TYPE_LOADING : VIEW_TYPE_ITEM;
@ -54,7 +52,6 @@ class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
return null; return null;
} }
@SuppressLint("SetJavaScriptEnabled")
@Override @Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) { public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
if (holder instanceof LatestPostViewHolder) { if (holder instanceof LatestPostViewHolder) {
@ -90,10 +87,10 @@ class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
} }
private static class LatestPostViewHolder extends RecyclerView.ViewHolder { private static class LatestPostViewHolder extends RecyclerView.ViewHolder {
RelativeLayout latestPostsRow; final RelativeLayout latestPostsRow;
TextView postTitle; final TextView postTitle;
TextView postDate; final TextView postDate;
WebView post; final WebView post;
LatestPostViewHolder(View itemView) { LatestPostViewHolder(View itemView) {
super(itemView); super(itemView);
@ -105,7 +102,7 @@ class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
} }
private static class LoadingViewHolder extends RecyclerView.ViewHolder { private static class LoadingViewHolder extends RecyclerView.ViewHolder {
MaterialProgressBar progressBar; final MaterialProgressBar progressBar;
LoadingViewHolder(View itemView) { LoadingViewHolder(View itemView) {
super(itemView); super(itemView);

41
app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java

@ -41,20 +41,20 @@ public class LatestPostsFragment extends BaseFragment {
/** /**
* The key to use when putting profile's url String to {@link LatestPostsFragment}'s Bundle. * The key to use when putting profile's url String to {@link LatestPostsFragment}'s Bundle.
*/ */
static final String PROFILE_URL = "PROFILE_DOCUMENT"; private static final String PROFILE_URL = "PROFILE_URL";
/** /**
* {@link ArrayList} of {@link TopicSummary} objects used to hold profile's latest posts. Data * {@link ArrayList} of {@link TopicSummary} objects used to hold profile's latest posts. Data
* are added in {@link LatestPostsFragment.ProfileLatestPostsTask}. * are added in {@link LatestPostsTask}.
*/ */
static ArrayList<TopicSummary> parsedTopicSummaries; static ArrayList<TopicSummary> parsedTopicSummaries;
private LatestPostsAdapter latestPostsAdapter; private LatestPostsAdapter latestPostsAdapter;
private int numberOfPages = -1; private int numberOfPages = -1;
private int pagesLoaded = 0; private int pagesLoaded = 0;
private String profileUrl; private String profileUrl;
private ProfileLatestPostsTask profileLatestPostsTask; private LatestPostsTask profileLatestPostsTask;
private MaterialProgressBar progressBar; private MaterialProgressBar progressBar;
private boolean isLoadingMore; private boolean isLoadingMore;
static int visibleThreshold = 5; private static final int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount; private int lastVisibleItem, totalItemCount;
public LatestPostsFragment() { public LatestPostsFragment() {
@ -87,7 +87,6 @@ public class LatestPostsFragment extends BaseFragment {
public View onCreateView(LayoutInflater inflater, ViewGroup container, public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) { Bundle savedInstanceState) {
final View rootView = inflater.inflate(R.layout.profile_fragment_latest_posts, container, false); final View rootView = inflater.inflate(R.layout.profile_fragment_latest_posts, container, false);
latestPostsAdapter = new LatestPostsAdapter(fragmentInteractionListener); latestPostsAdapter = new LatestPostsAdapter(fragmentInteractionListener);
RecyclerView mainContent = (RecyclerView) rootView.findViewById(R.id.profile_latest_posts_recycler); RecyclerView mainContent = (RecyclerView) rootView.findViewById(R.id.profile_latest_posts_recycler);
mainContent.setAdapter(latestPostsAdapter); mainContent.setAdapter(latestPostsAdapter);
@ -105,19 +104,18 @@ public class LatestPostsFragment extends BaseFragment {
latestPostsAdapter.notifyItemInserted(parsedTopicSummaries.size() - 1); latestPostsAdapter.notifyItemInserted(parsedTopicSummaries.size() - 1);
//Load data //Load data
profileLatestPostsTask = new ProfileLatestPostsTask(); profileLatestPostsTask = new LatestPostsTask();
profileLatestPostsTask.execute(profileUrl + ";sa=showPosts;start=" + pagesLoaded * 15); profileLatestPostsTask.execute(profileUrl + ";sa=showPosts;start=" + pagesLoaded * 15);
++pagesLoaded; ++pagesLoaded;
} }
} }
}; };
latestPostsAdapter.setOnLoadMoreListener(onLoadMoreListener); //latestPostsAdapter.setOnLoadMoreListener();
mainContent.addOnScrollListener(new RecyclerView.OnScrollListener() { mainContent.addOnScrollListener(new RecyclerView.OnScrollListener() {
@Override @Override
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { public void onScrolled(RecyclerView recyclerView, int dx, int dy) {
super.onScrolled(recyclerView, dx, dy); super.onScrolled(recyclerView, dx, dy);
totalItemCount = layoutManager.getItemCount(); totalItemCount = layoutManager.getItemCount();
lastVisibleItem = layoutManager.findLastVisibleItemPosition(); lastVisibleItem = layoutManager.findLastVisibleItemPosition();
@ -135,7 +133,7 @@ public class LatestPostsFragment extends BaseFragment {
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
if (parsedTopicSummaries.isEmpty()) { if (parsedTopicSummaries.isEmpty()) {
profileLatestPostsTask = new ProfileLatestPostsTask(); profileLatestPostsTask = new LatestPostsTask();
profileLatestPostsTask.execute(profileUrl + ";sa=showPosts"); profileLatestPostsTask.execute(profileUrl + ";sa=showPosts");
pagesLoaded = 1; pagesLoaded = 1;
} }
@ -155,22 +153,20 @@ public class LatestPostsFragment extends BaseFragment {
/** /**
* An {@link AsyncTask} that handles asynchronous fetching of a profile page and parsing this * An {@link AsyncTask} that handles asynchronous fetching of a profile page and parsing this
* user's personal text. * user's latest posts.
* <p>ProfileTask's {@link AsyncTask#execute execute} method needs a profile's url as String * <p>LatestPostsTask's {@link AsyncTask#execute execute} method needs a profile's url as String
* parameter!</p> * parameter!</p>
*/ */
public class ProfileLatestPostsTask extends AsyncTask<String, Void, Boolean> { public class LatestPostsTask extends AsyncTask<String, Void, Boolean> {
//Class variables //Class variables
/** /**
* Debug Tag for logging debug output to LogCat * Debug Tag for logging debug output to LogCat
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final String TAG = "ProfileLatestPostsTask"; //Separate tag for AsyncTask private static final String TAG = "LatestPostsTask"; //Separate tag for AsyncTask
protected void onPreExecute() { protected void onPreExecute() {
if (!isLoadingMore) { if (!isLoadingMore) progressBar.setVisibility(ProgressBar.VISIBLE);
progressBar.setVisibility(ProgressBar.VISIBLE);
}
} }
protected Boolean doInBackground(String... profileUrl) { protected Boolean doInBackground(String... profileUrl) {
@ -190,6 +186,7 @@ public class LatestPostsFragment extends BaseFragment {
protected void onPostExecute(Boolean result) { protected void onPostExecute(Boolean result) {
if (!result) { //Parse failed! if (!result) { //Parse failed!
Report.d(TAG, "Parse failed!");
Toast.makeText(getContext() Toast.makeText(getContext()
, "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show(); , "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show();
getActivity().finish(); getActivity().finish();
@ -203,14 +200,13 @@ public class LatestPostsFragment extends BaseFragment {
private boolean parseLatestPosts(Document latestPostsPage) { private boolean parseLatestPosts(Document latestPostsPage) {
Elements latestPostsRows = latestPostsPage. Elements latestPostsRows = latestPostsPage.
select("td:has(table:Contains(Show Posts)):not([style]) > table"); select("td:has(table:Contains(Show Posts)):not([style]) > table");
if (latestPostsRows == null) if (latestPostsRows.isEmpty()) {
latestPostsRows = latestPostsPage. latestPostsRows = latestPostsPage.
select("td:has(table:Contains(Show Posts)):not([style]) > table"); select("td:has(table:Contains(Εμφάνιση μηνυμάτων)):not([style]) > table");
}
//Removes loading item //Removes loading item
if (isLoadingMore) { if (isLoadingMore) {
parsedTopicSummaries.remove(parsedTopicSummaries.size() - 1); parsedTopicSummaries.remove(parsedTopicSummaries.size() - 1);
} }
for (Element row : latestPostsRows) { for (Element row : latestPostsRows) {
@ -219,7 +215,7 @@ public class LatestPostsFragment extends BaseFragment {
if (numberOfPages == -1) { if (numberOfPages == -1) {
Elements pages = row.select("tr.catbg3 a"); Elements pages = row.select("tr.catbg3 a");
for (Element page : pages) { for (Element page : pages) {
if (Integer.parseInt(page.text()) >= numberOfPages) if (Integer.parseInt(page.text()) > numberOfPages)
numberOfPages = Integer.parseInt(page.text()); numberOfPages = Integer.parseInt(page.text());
} }
} }
@ -228,7 +224,7 @@ public class LatestPostsFragment extends BaseFragment {
if (rowHeader.size() != 2) { if (rowHeader.size() != 2) {
return false; return false;
} else { } else {
pTopicTitle = rowHeader.text(); pTopicTitle = rowHeader.first().text().trim();
pTopicUrl = rowHeader.first().select("a").last().attr("href"); pTopicUrl = rowHeader.first().select("a").last().attr("href");
pDateTime = rowHeader.last().text(); pDateTime = rowHeader.last().text();
} }
@ -256,7 +252,6 @@ public class LatestPostsFragment extends BaseFragment {
+ "<img src=\"https://img.youtube.com/vi/" + "<img src=\"https://img.youtube.com/vi/"
+ embededVideosUrls.get(tmp_counter) + "/default.jpg\" alt=\"\" border=\"0\">" + embededVideosUrls.get(tmp_counter) + "/default.jpg\" alt=\"\" border=\"0\">"
+ "</a>" + "</a>"
//+ "<img class=\"embedded-video-play\" src=\"http://www.youtube.com/yt/brand/media/image/YouTube_light_color_icon.png\">"
+ "</div>"); + "</div>");
} }
} }

21
app/src/main/java/gr/thmmy/mthmmy/activities/profile/stats/StatsFragment.java

@ -54,7 +54,7 @@ public class StatsFragment extends Fragment {
/** /**
* The key to use when putting profile's url String to {@link StatsFragment}'s Bundle. * The key to use when putting profile's url String to {@link StatsFragment}'s Bundle.
*/ */
static final String PROFILE_URL = "PROFILE_DOCUMENT"; private static final String PROFILE_URL = "PROFILE_DOCUMENT";
private String profileUrl; private String profileUrl;
private ProfileStatsTask profileStatsTask; private ProfileStatsTask profileStatsTask;
private LinearLayout mainContent; private LinearLayout mainContent;
@ -62,9 +62,9 @@ public class StatsFragment extends Fragment {
private boolean haveParsed = false; private boolean haveParsed = false;
private String generalStatisticsTitle = "", generalStatistics = "", postingActivityByTimeTitle = "", mostPopularBoardsByPostsTitle = "", mostPopularBoardsByActivityTitle = ""; private String generalStatisticsTitle = "", generalStatistics = "", postingActivityByTimeTitle = "", mostPopularBoardsByPostsTitle = "", mostPopularBoardsByActivityTitle = "";
private List<Entry> postingActivityByTime = new ArrayList<>(); final private List<Entry> postingActivityByTime = new ArrayList<>();
private List<BarEntry> mostPopularBoardsByPosts = new ArrayList<>(), mostPopularBoardsByActivity = new ArrayList<>(); final private List<BarEntry> mostPopularBoardsByPosts = new ArrayList<>(), mostPopularBoardsByActivity = new ArrayList<>();
private ArrayList<String> mostPopularBoardsByPostsLabels = new ArrayList<>(), mostPopularBoardsByActivityLabels = new ArrayList<>(); final private ArrayList<String> mostPopularBoardsByPostsLabels = new ArrayList<>(), mostPopularBoardsByActivityLabels = new ArrayList<>();
public StatsFragment() { public StatsFragment() {
// Required empty public constructor // Required empty public constructor
@ -124,7 +124,7 @@ public class StatsFragment extends Fragment {
* {@link AsyncTask#onPostExecute(Object) OnPostExecute} method calls {@link #()} * {@link AsyncTask#onPostExecute(Object) OnPostExecute} method calls {@link #()}
* to build graphics. * to build graphics.
* <p> * <p>
* <p>Calling ProfileSummaryTask's {@link AsyncTask#execute execute} method needs to have profile's url * <p>Calling SummaryTask's {@link AsyncTask#execute execute} method needs to have profile's url
* as String parameter!</p> * as String parameter!</p>
*/ */
public class ProfileStatsTask extends AsyncTask<String, Void, Boolean> { public class ProfileStatsTask extends AsyncTask<String, Void, Boolean> {
@ -160,6 +160,7 @@ public class StatsFragment extends Fragment {
@Override @Override
protected void onPostExecute(Boolean result) { protected void onPostExecute(Boolean result) {
if (!result) { //Parse failed! if (!result) { //Parse failed!
Report.d(TAG, "Parse failed!");
Toast.makeText(getContext() Toast.makeText(getContext()
, "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show(); , "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show();
getActivity().finish(); getActivity().finish();
@ -170,17 +171,17 @@ public class StatsFragment extends Fragment {
} }
private boolean parseStats(Document statsPage) { private boolean parseStats(Document statsPage) {
if (statsPage.select("table.bordercolor>tbody>tr").size() != 6) if (statsPage.select("table.bordercolor[align]>tbody>tr").size() != 6)
return false; //It's my profile return false;
{ {
Elements titleRows = statsPage.select("table.bordercolor>tbody>tr.titlebg"); Elements titleRows = statsPage.select("table.bordercolor[align]>tbody>tr.titlebg");
generalStatisticsTitle = titleRows.first().text(); generalStatisticsTitle = titleRows.first().text();
postingActivityByTimeTitle = titleRows.get(1).text(); postingActivityByTimeTitle = titleRows.get(1).text();
mostPopularBoardsByPostsTitle = titleRows.last().select("td").first().text(); mostPopularBoardsByPostsTitle = titleRows.last().select("td").first().text();
mostPopularBoardsByActivityTitle = titleRows.last().select("td").last().text(); mostPopularBoardsByActivityTitle = titleRows.last().select("td").last().text();
} }
{ {
Elements statsRows = statsPage.select("table.bordercolor>tbody>tr:not(.titlebg)"); Elements statsRows = statsPage.select("table.bordercolor[align]>tbody>tr:not(.titlebg)");
{ {
Elements generalStatisticsRows = statsRows.first().select("tbody>tr"); Elements generalStatisticsRows = statsRows.first().select("tbody>tr");
for (Element generalStatisticsRow : generalStatisticsRows) for (Element generalStatisticsRow : generalStatisticsRows)
@ -341,7 +342,7 @@ public class StatsFragment extends Fragment {
} }
class MyXAxisValueFormatter implements IAxisValueFormatter { class MyXAxisValueFormatter implements IAxisValueFormatter {
private ArrayList<String> mValues; private final ArrayList<String> mValues;
MyXAxisValueFormatter(ArrayList<String> values) { MyXAxisValueFormatter(ArrayList<String> values) {
this.mValues = values; this.mValues = values;

49
app/src/main/java/gr/thmmy/mthmmy/activities/profile/summary/SummaryFragment.java

@ -5,7 +5,6 @@ import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.text.Html; import android.text.Html;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -37,17 +36,17 @@ public class SummaryFragment extends Fragment {
/** /**
* The key to use when putting profile's source code String to {@link SummaryFragment}'s Bundle. * The key to use when putting profile's source code String to {@link SummaryFragment}'s Bundle.
*/ */
static final String PROFILE_DOCUMENT = "PROFILE_DOCUMENT"; private static final String PROFILE_DOCUMENT = "PROFILE_DOCUMENT";
/** /**
* {@link ArrayList} of Strings used to hold profile's information. Data are added in * {@link ArrayList} of Strings used to hold profile's information. Data are added in
* {@link SummaryFragment.ProfileSummaryTask}. * {@link SummaryTask}.
*/ */
private ArrayList<String> parsedProfileSummaryData; private ArrayList<String> parsedProfileSummaryData;
/** /**
* A {@link Document} holding this profile's source code. * A {@link Document} holding this profile's source code.
*/ */
private Document profileSummaryDocument; private Document profileSummaryDocument;
private ProfileSummaryTask profileSummaryTask; private SummaryTask summaryTask;
private LinearLayout mainContent; private LinearLayout mainContent;
public SummaryFragment() { public SummaryFragment() {
@ -90,8 +89,8 @@ public class SummaryFragment extends Fragment {
public void onActivityCreated(Bundle savedInstanceState) { public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState); super.onActivityCreated(savedInstanceState);
if (parsedProfileSummaryData.isEmpty()) { if (parsedProfileSummaryData.isEmpty()) {
profileSummaryTask = new ProfileSummaryTask(); summaryTask = new SummaryTask();
profileSummaryTask.execute(profileSummaryDocument); summaryTask.execute(profileSummaryDocument);
} }
Report.d(TAG, "onActivityCreated"); Report.d(TAG, "onActivityCreated");
} }
@ -99,8 +98,8 @@ public class SummaryFragment extends Fragment {
@Override @Override
public void onDestroy() { public void onDestroy() {
super.onDestroy(); super.onDestroy();
if (profileSummaryTask != null && profileSummaryTask.getStatus() != AsyncTask.Status.RUNNING) if (summaryTask != null && summaryTask.getStatus() != AsyncTask.Status.RUNNING)
profileSummaryTask.cancel(true); summaryTask.cancel(true);
} }
/** /**
@ -108,16 +107,16 @@ public class SummaryFragment extends Fragment {
* {@link AsyncTask#onPostExecute(Object) OnPostExecute} method calls {@link #populateLayout()} * {@link AsyncTask#onPostExecute(Object) OnPostExecute} method calls {@link #populateLayout()}
* to build graphics. * to build graphics.
* <p> * <p>
* <p>Calling ProfileSummaryTask's {@link AsyncTask#execute execute} method needs to have profile's url * <p>Calling SummaryTask's {@link AsyncTask#execute execute} method needs to have profile's url
* as String parameter!</p> * as String parameter!</p>
*/ */
public class ProfileSummaryTask extends AsyncTask<Document, Void, Void> { public class SummaryTask extends AsyncTask<Document, Void, Void> {
//Class variables //Class variables
/** /**
* Debug Tag for logging debug output to LogCat * Debug Tag for logging debug output to LogCat
*/ */
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static final String TAG = "TopicTask"; //Separate tag for AsyncTask private static final String TAG = "SummaryTask"; //Separate tag for AsyncTask
protected Void doInBackground(Document... profileSummaryPage) { protected Void doInBackground(Document... profileSummaryPage) {
parsedProfileSummaryData = parseProfileSummary(profileSummaryPage[0]); parsedProfileSummaryData = parseProfileSummary(profileSummaryPage[0]);
@ -142,16 +141,15 @@ public class SummaryFragment extends Fragment {
//Contains all summary's rows //Contains all summary's rows
Elements summaryRows = profile.select(".bordercolor > tbody:nth-child(1) > tr:nth-child(2) tr"); Elements summaryRows = profile.select(".bordercolor > tbody:nth-child(1) > tr:nth-child(2) tr");
for (Element row : summaryRows) { for (Element summaryRow : summaryRows) {
String rowText = row.text(), pHtml = ""; String rowText = summaryRow.text(), pHtml = "";
//Horizontal rule rows if (summaryRow.select("td").size() == 1) //Horizontal rule rows
if (row.select("td").size() == 1)
pHtml = ""; pHtml = "";
else if (rowText.contains("Signature") || rowText.contains("Υπογραφή")) { else if (rowText.contains("Signature") || rowText.contains("Υπογραφή")) {
//This needs special handling since it may have css //This needs special handling since it may have css
{ //Fix embedded videos { //Fix embedded videos
Elements noembedTag = row.select("noembed"); Elements noembedTag = summaryRow.select("noembed");
ArrayList<String> embededVideosUrls = new ArrayList<>(); ArrayList<String> embededVideosUrls = new ArrayList<>();
for (Element _noembed : noembedTag) { for (Element _noembed : noembedTag) {
@ -160,7 +158,7 @@ public class SummaryFragment extends Fragment {
, _noembed.text().indexOf("target") - 2)); , _noembed.text().indexOf("target") - 2));
} }
pHtml = row.html(); pHtml = summaryRow.html();
int tmp_counter = 0; int tmp_counter = 0;
while (pHtml.contains("<embed")) { while (pHtml.contains("<embed")) {
@ -181,13 +179,14 @@ public class SummaryFragment extends Fragment {
//Add stuff to make it work in WebView //Add stuff to make it work in WebView
//style.css //style.css
pHtml = ("<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />" + pHtml); pHtml = ("<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />\n" +
} else if (!rowText.contains("Name") && !rowText.contains("Όνομα")) { //Don't add username twice "<div class=\"customSignature\">\n" + pHtml + "\n</div>");
if (Objects.equals(row.select("td").get(1).text(), "")) } else if (!rowText.contains("Name") && !rowText.contains("Όνομα")) { //Doesn't add username twice
if (Objects.equals(summaryRow.select("td").get(1).text(), ""))
continue; continue;
//Style parsed information with html //Style parsed information with html
pHtml = "<b>" + row.select("td").first().text() + "</b> " pHtml = "<b>" + summaryRow.select("td").first().text() + "</b> "
+ row.select("td").get(1).text(); + summaryRow.select("td").get(1).text();
} }
parsedInformation.add(pHtml); parsedInformation.add(pHtml);
} }
@ -204,10 +203,12 @@ public class SummaryFragment extends Fragment {
private void populateLayout() { private void populateLayout() {
for (String profileSummaryRow : parsedProfileSummaryData) { for (String profileSummaryRow : parsedProfileSummaryData) {
if (profileSummaryRow.contains("Signature") if (profileSummaryRow.contains("Signature")
|| profileSummaryRow.contains("Υπογραφή")) { || profileSummaryRow.contains("Υπογραφή")) { //This may contain css
WebView signatureEntry = new WebView(this.getContext()); WebView signatureEntry = new WebView(this.getContext());
signatureEntry.loadDataWithBaseURL("file:///android_asset/", profileSummaryRow, signatureEntry.loadDataWithBaseURL("file:///android_asset/", profileSummaryRow,
"text/html", "UTF-8", null); "text/html", "UTF-8", null);
mainContent.addView(signatureEntry);
continue;
} }
TextView entry = new TextView(this.getContext()); TextView entry = new TextView(this.getContext());
@ -216,7 +217,6 @@ public class SummaryFragment extends Fragment {
} else { } else {
//noinspection deprecation //noinspection deprecation
entry.setTextColor(getResources().getColor(R.color.primary_text)); entry.setTextColor(getResources().getColor(R.color.primary_text));
} }
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
entry.setText(Html.fromHtml(profileSummaryRow, Html.FROM_HTML_MODE_LEGACY)); entry.setText(Html.fromHtml(profileSummaryRow, Html.FROM_HTML_MODE_LEGACY));
@ -226,7 +226,6 @@ public class SummaryFragment extends Fragment {
} }
mainContent.addView(entry); mainContent.addView(entry);
Log.d(TAG, "new: " + profileSummaryRow);
} }
} }
} }

14
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java

@ -322,6 +322,7 @@ public class TopicActivity extends BaseActivity {
protected void onPreExecute() { protected void onPreExecute() {
progressBar.setVisibility(ProgressBar.VISIBLE); progressBar.setVisibility(ProgressBar.VISIBLE);
paginationEnable(false);
replyFAB.setEnabled(false); replyFAB.setEnabled(false);
} }
@ -392,10 +393,7 @@ public class TopicActivity extends BaseActivity {
pageIndicator.setText(String.valueOf(thisPage) + "/" + String.valueOf(numberOfPages)); pageIndicator.setText(String.valueOf(thisPage) + "/" + String.valueOf(numberOfPages));
pageRequestValue = thisPage; pageRequestValue = thisPage;
firstPage.setEnabled(true); paginationEnable(true);
previousPage.setEnabled(true);
nextPage.setEnabled(true);
lastPage.setEnabled(true);
if (topicTitle == null || Objects.equals(topicTitle, "")) if (topicTitle == null || Objects.equals(topicTitle, ""))
toolbar.setTitle(parsedTitle); toolbar.setTitle(parsedTitle);
@ -408,6 +406,7 @@ public class TopicActivity extends BaseActivity {
break; break;
default: default:
//Parse failed - should never happen //Parse failed - should never happen
Report.d(TAG, "Parse failed!");
Toast.makeText(getBaseContext(), "Fatal Error", Toast.LENGTH_SHORT).show(); Toast.makeText(getBaseContext(), "Fatal Error", Toast.LENGTH_SHORT).show();
finish(); finish();
break; break;
@ -477,4 +476,11 @@ public class TopicActivity extends BaseActivity {
} }
} }
} }
private void paginationEnable(boolean enabled) {
firstPage.setEnabled(enabled);
previousPage.setEnabled(enabled);
nextPage.setEnabled(enabled);
lastPage.setEnabled(enabled);
}
} }

86
app/src/main/res/layout/activity_board.xml

@ -7,7 +7,7 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:fitsSystemWindows="true" android:fitsSystemWindows="true"
tools:context=".activities.board.BoardActivity"> tools:context=".activities.topic.TopicActivity">
<android.support.design.widget.AppBarLayout <android.support.design.widget.AppBarLayout
android:id="@+id/appbar" android:id="@+id/appbar"
@ -25,16 +25,92 @@
</android.support.v7.widget.Toolbar> </android.support.v7.widget.Toolbar>
</android.support.design.widget.AppBarLayout> </android.support.design.widget.AppBarLayout>
<android.support.v7.widget.RecyclerView
android:id="@+id/board_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="top|start"
android:layout_marginTop="64dp"
android:background="@color/background"
android:scrollbars="none"
tools:context="gr.thmmy.mthmmy.activities.topic.TopicActivity">
</android.support.v7.widget.RecyclerView>
<LinearLayout
android:id="@+id/bottom_navigation_bar"
android:layout_width="match_parent"
android:layout_height="50dp"
android:layout_gravity="bottom|end"
android:background="@color/primary"
app:elevation="8dp"
app:layout_behavior="gr.thmmy.mthmmy.utils.ScrollAwareLinearBehavior">
<ImageButton
android:id="@+id/page_first_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:contentDescription="@string/text_first"
app:srcCompat="@drawable/page_first"/>
<ImageButton
android:id="@+id/page_previous_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:contentDescription="@string/text_previous"
app:srcCompat="@drawable/page_previous"/>
<TextView
android:id="@+id/page_indicator"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_gravity="center"
android:layout_weight="1"
android:gravity="center"
android:hint="@string/text_page"
android:maxLines="1"
android:textColor="@color/white"
android:textSize="22sp"/>
<ImageButton
android:id="@+id/page_next_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:contentDescription="@string/text_next"
app:srcCompat="@drawable/page_next"/>
<ImageButton
android:id="@+id/page_last_button"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:layout_weight="0.8"
android:contentDescription="@string/text_last"
app:srcCompat="@drawable/page_last"/>
</LinearLayout>
<me.zhanghai.android.materialprogressbar.MaterialProgressBar <me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:indeterminate="true"
android:visibility="invisible"
app:layout_anchor="@id/appbar" app:layout_anchor="@id/appbar"
app:layout_anchorGravity="bottom|center" app:layout_anchorGravity="bottom|center"
app:mpb_indeterminateTint="@color/accent" app:mpb_indeterminateTint="@color/accent"
android:visibility="invisible" app:mpb_progressStyle="horizontal"/>
android:indeterminate="true"
app:mpb_progressStyle="horizontal"
style="@style/Widget.MaterialProgressBar.ProgressBar.Horizontal.NoPadding" />
<android.support.design.widget.FloatingActionButton
android:id="@+id/board_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_marginBottom="50dp"
android:layout_marginEnd="@dimen/fab_margins"
app:layout_behavior="gr.thmmy.mthmmy.utils.ScrollAwareFABBehavior"
app:srcCompat="@drawable/ic_add_fab"/>
</android.support.design.widget.CoordinatorLayout> </android.support.design.widget.CoordinatorLayout>

Loading…
Cancel
Save