Browse Source

Work in progress: latest posts tab completed

pull/24/head
Apostolos Fanakis 8 years ago
parent
commit
22610da03f
  1. 16
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsAdapter.java
  2. 124
      app/src/main/java/gr/thmmy/mthmmy/activities/profile/latestPosts/LatestPostsFragment.java
  3. 14
      app/src/main/res/layout/profile_fragment_latest_posts_row.xml
  4. 12
      app/src/main/res/layout/recycler_loading_item.xml

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

@ -1,19 +1,24 @@
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.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;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import gr.thmmy.mthmmy.R; import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.data.TopicSummary; import gr.thmmy.mthmmy.data.TopicSummary;
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;
class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> { class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
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; private OnLoadMoreListener mOnLoadMoreListener;
@ -38,6 +43,7 @@ class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
inflate(R.layout.profile_fragment_latest_posts_row, parent, false); inflate(R.layout.profile_fragment_latest_posts_row, parent, false);
return new LatestPostViewHolder(view); return new LatestPostViewHolder(view);
} else if (viewType == VIEW_TYPE_LOADING) { } else if (viewType == VIEW_TYPE_LOADING) {
Log.d(TAG, "GOT");
View view = LayoutInflater.from(parent.getContext()). View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.recycler_loading_item, parent, false); inflate(R.layout.recycler_loading_item, parent, false);
return new LoadingViewHolder(view); return new LoadingViewHolder(view);
@ -45,14 +51,16 @@ class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
return null; return null;
} }
@SuppressLint("SetJavaScriptEnabled")
@Override @Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) { public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
if (holder instanceof LatestPostViewHolder) { if (holder instanceof LatestPostViewHolder) {
TopicSummary topic = parsedTopicSummaries.get(position); TopicSummary topic = parsedTopicSummaries.get(position);
LatestPostViewHolder latestPostViewHolder = (LatestPostViewHolder) holder; final LatestPostViewHolder latestPostViewHolder = (LatestPostViewHolder) holder;
latestPostViewHolder.postTitle.setText(topic.getTitle()); latestPostViewHolder.postTitle.setText(topic.getTitle());
latestPostViewHolder.postDate.setText(topic.getDateTimeModified()); latestPostViewHolder.postDate.setText(topic.getDateTimeModified());
//latestPostViewHolder.post. latestPostViewHolder.post.loadDataWithBaseURL("file:///android_asset/"
, topic.getPost(), "text/html", "UTF-8", null);
} else if (holder instanceof LoadingViewHolder) { } else if (holder instanceof LoadingViewHolder) {
LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder; LoadingViewHolder loadingViewHolder = (LoadingViewHolder) holder;
loadingViewHolder.progressBar.setIndeterminate(true); loadingViewHolder.progressBar.setIndeterminate(true);
@ -78,11 +86,11 @@ class LatestPostsAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
} }
private static class LoadingViewHolder extends RecyclerView.ViewHolder { private static class LoadingViewHolder extends RecyclerView.ViewHolder {
ProgressBar progressBar; MaterialProgressBar progressBar;
LoadingViewHolder(View itemView) { LoadingViewHolder(View itemView) {
super(itemView); super(itemView);
progressBar = (ProgressBar) itemView.findViewById(R.id.progress_bar); progressBar = (MaterialProgressBar) itemView.findViewById(R.id.recycler_progress_bar);
} }
} }
} }

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

@ -3,8 +3,10 @@ package gr.thmmy.mthmmy.activities.profile.latestPosts;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.Fragment; import android.support.v4.app.Fragment;
import android.support.v7.widget.DividerItemDecoration;
import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
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;
@ -46,13 +48,13 @@ public class LatestPostsFragment extends Fragment {
* are added in {@link LatestPostsFragment.ProfileLatestPostsTask}. * are added in {@link LatestPostsFragment.ProfileLatestPostsTask}.
*/ */
static ArrayList<TopicSummary> parsedTopicSummaries; static ArrayList<TopicSummary> parsedTopicSummaries;
private RecyclerView mainContent;
private LatestPostsAdapter latestPostsAdapter = new LatestPostsAdapter(); private LatestPostsAdapter latestPostsAdapter = new LatestPostsAdapter();
private int numberOfPages = -1; private int numberOfPages = -1;
private int pagesLoaded = 0;
private String profileUrl; private String profileUrl;
private ProfileLatestPostsTask profileLatestPostsTask; private ProfileLatestPostsTask profileLatestPostsTask;
private MaterialProgressBar progressBar; private MaterialProgressBar progressBar;
private boolean isLoading; private boolean isLoadingMore;
static int visibleThreshold = 5; static int visibleThreshold = 5;
private int lastVisibleItem, totalItemCount; private int lastVisibleItem, totalItemCount;
@ -82,60 +84,46 @@ public class LatestPostsFragment extends Fragment {
parsedTopicSummaries = new ArrayList<>(); parsedTopicSummaries = new ArrayList<>();
} }
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (parsedTopicSummaries.isEmpty()) {
profileLatestPostsTask = new ProfileLatestPostsTask();
profileLatestPostsTask.execute(profileUrl);
}
Report.d(TAG, "onActivityCreated");
}
@Override
public void onDestroy() {
super.onDestroy();
if (profileLatestPostsTask != null && profileLatestPostsTask.getStatus() != AsyncTask.Status.RUNNING)
profileLatestPostsTask.cancel(true);
}
@Override @Override
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);
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);
final LinearLayoutManager layoutManager = new LinearLayoutManager(getContext());
mainContent.setLayoutManager(layoutManager);
DividerItemDecoration dividerItemDecoration = new DividerItemDecoration(mainContent.getContext(),
layoutManager.getOrientation());
mainContent.addItemDecoration(dividerItemDecoration);
final LatestPostsAdapter.OnLoadMoreListener onLoadMoreListener = new LatestPostsAdapter.OnLoadMoreListener() { final LatestPostsAdapter.OnLoadMoreListener onLoadMoreListener = new LatestPostsAdapter.OnLoadMoreListener() {
@Override @Override
public void onLoadMore() { public void onLoadMore() {
parsedTopicSummaries.add(null); if (pagesLoaded < numberOfPages) {
latestPostsAdapter.notifyItemInserted(parsedTopicSummaries.size() - 1); parsedTopicSummaries.add(null);
latestPostsAdapter.notifyItemInserted(parsedTopicSummaries.size() - 1);
//Removes loading item
parsedTopicSummaries.remove(parsedTopicSummaries.size() - 1);
latestPostsAdapter.notifyItemRemoved(parsedTopicSummaries.size());
//Load data //Load data
profileLatestPostsTask = new ProfileLatestPostsTask(); profileLatestPostsTask = new ProfileLatestPostsTask();
profileLatestPostsTask.execute(profileUrl); profileLatestPostsTask.execute(profileUrl + ";sa=showPosts;start=" + pagesLoaded * 15);
++pagesLoaded;
}
} }
}; };
latestPostsAdapter.setOnLoadMoreListener(onLoadMoreListener); latestPostsAdapter.setOnLoadMoreListener(onLoadMoreListener);
final LinearLayoutManager linearLayoutManager = (LinearLayoutManager) mainContent.getLayoutManager();
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 = linearLayoutManager.getItemCount(); totalItemCount = layoutManager.getItemCount();
lastVisibleItem = linearLayoutManager.findLastVisibleItemPosition(); lastVisibleItem = layoutManager.findLastVisibleItemPosition();
if (!isLoading && totalItemCount <= (lastVisibleItem + visibleThreshold)) { if (!isLoadingMore && totalItemCount <= (lastVisibleItem + visibleThreshold)) {
isLoadingMore = true;
onLoadMoreListener.onLoadMore(); onLoadMoreListener.onLoadMore();
isLoading = true;
} }
} }
}); });
@ -143,6 +131,24 @@ public class LatestPostsFragment extends Fragment {
return rootView; return rootView;
} }
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (parsedTopicSummaries.isEmpty()) {
profileLatestPostsTask = new ProfileLatestPostsTask();
profileLatestPostsTask.execute(profileUrl + ";sa=showPosts");
pagesLoaded = 1;
}
Report.d(TAG, "onActivityCreated");
}
@Override
public void onDestroy() {
super.onDestroy();
if (profileLatestPostsTask != null && profileLatestPostsTask.getStatus() != AsyncTask.Status.RUNNING)
profileLatestPostsTask.cancel(true);
}
/** /**
* 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.
@ -158,11 +164,14 @@ public class LatestPostsFragment extends Fragment {
private static final String TAG = "ProfileLatestPostsTask"; //Separate tag for AsyncTask private static final String TAG = "ProfileLatestPostsTask"; //Separate tag for AsyncTask
protected void onPreExecute() { protected void onPreExecute() {
progressBar.setVisibility(ProgressBar.VISIBLE); if (!isLoadingMore) {
Log.d(TAG, "false");
progressBar.setVisibility(ProgressBar.VISIBLE);
}
} }
protected Boolean doInBackground(String... profileUrl) { protected Boolean doInBackground(String... profileUrl) {
String pageUrl = profileUrl[0] + ";sa=showPosts"; //Profile's page wap url String pageUrl = profileUrl[0];
Request request = new Request.Builder() Request request = new Request.Builder()
.url(pageUrl) .url(pageUrl)
@ -187,7 +196,7 @@ public class LatestPostsFragment extends Fragment {
//Parse was successful //Parse was successful
progressBar.setVisibility(ProgressBar.INVISIBLE); progressBar.setVisibility(ProgressBar.INVISIBLE);
latestPostsAdapter.notifyDataSetChanged(); latestPostsAdapter.notifyDataSetChanged();
isLoading = false; isLoadingMore = false;
} }
private boolean parseLatestPosts(Document latestPostsPage) { private boolean parseLatestPosts(Document latestPostsPage) {
@ -197,10 +206,15 @@ public class LatestPostsFragment extends Fragment {
latestPostsRows = latestPostsPage. latestPostsRows = latestPostsPage.
select("td:has(table:Contains(Show Posts)):not([style]) > table"); select("td:has(table:Contains(Show Posts)):not([style]) > table");
//Removes loading item
if (isLoadingMore) {
parsedTopicSummaries.remove(parsedTopicSummaries.size() - 1);
}
for (Element row : latestPostsRows) { for (Element row : latestPostsRows) {
String pTopicUrl, pTopicTitle, pDateTime, pPost; String pTopicUrl, pTopicTitle, pDateTime, pPost;
if (Integer.parseInt(row.attr("cellpadding")) == 4) {
if (row.text().contains("Show Posts Pages: ") || row.text().contains("")) {
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) {
@ -217,7 +231,37 @@ public class LatestPostsFragment extends Fragment {
pTopicUrl = rowHeader.first().select("a").last().attr("href"); pTopicUrl = rowHeader.first().select("a").last().attr("href");
pDateTime = rowHeader.last().text(); pDateTime = rowHeader.last().text();
} }
pPost = rowHeader.select("div.post").first().html(); pPost = row.select("div.post").first().outerHtml();
{ //Fixes embedded videos
Elements noembedTag = row.select("div").select(".post").first().select("noembed");
ArrayList<String> embededVideosUrls = new ArrayList<>();
for (Element _noembed : noembedTag) {
embededVideosUrls.add(_noembed.text().substring(_noembed.text()
.indexOf("href=\"https://www.youtube.com/watch?") + 38
, _noembed.text().indexOf("target") - 2));
}
int tmp_counter = 0;
while (pPost.contains("<embed")) {
if (tmp_counter > embededVideosUrls.size())
break;
pPost = pPost.replace(
pPost.substring(pPost.indexOf("<embed"), pPost.indexOf("/noembed>") + 9)
, "<div class=\"embedded-video\">"
+ "<a href=\"https://www.youtube.com/"
+ embededVideosUrls.get(tmp_counter) + "\" target=\"_blank\">"
+ "<img src=\"https://img.youtube.com/vi/"
+ embededVideosUrls.get(tmp_counter) + "/default.jpg\" alt=\"\" border=\"0\">"
+ "</a>"
//+ "<img class=\"embedded-video-play\" src=\"http://www.youtube.com/yt/brand/media/image/YouTube_light_color_icon.png\">"
+ "</div>");
}
}
//Add stuff to make it work in WebView
//style.css
pPost = ("<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />" + pPost);
parsedTopicSummaries.add(new TopicSummary(pTopicUrl, pTopicTitle, "", pDateTime, pPost)); parsedTopicSummaries.add(new TopicSummary(pTopicUrl, pTopicTitle, "", pDateTime, pPost));
} }

14
app/src/main/res/layout/profile_fragment_latest_posts_row.xml

@ -3,7 +3,7 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:background="@color/primary_light" android:background="@color/card_background"
android:clickable="true" android:clickable="true"
android:foreground="?android:attr/selectableItemBackground" android:foreground="?android:attr/selectableItemBackground"
android:paddingBottom="6dp" android:paddingBottom="6dp"
@ -28,11 +28,21 @@
android:layout_below="@+id/title" android:layout_below="@+id/title"
android:textColor="@color/secondary_text"/> android:textColor="@color/secondary_text"/>
<View
android:id="@+id/spacer_divider"
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_below="@+id/date"
android:layout_marginBottom="3dp"
android:layout_marginTop="3dp"
android:background="@color/divider"/>
<FrameLayout <FrameLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_below="@+id/date"> android:layout_below="@+id/spacer_divider">
<WebView <WebView
android:id="@+id/post" android:id="@+id/post"

12
app/src/main/res/layout/recycler_loading_item.xml

@ -1,13 +1,17 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout <LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:orientation="vertical"> android:orientation="vertical">
<ProgressBar
android:id="@+id/progress_bar" <me.zhanghai.android.materialprogressbar.MaterialProgressBar
android:id="@+id/recycler_progress_bar"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"/> android:layout_gravity="center_horizontal"
android:indeterminate="true"
app:mpb_indeterminateTint="@color/accent"/>
</LinearLayout> </LinearLayout>
Loading…
Cancel
Save