Browse Source

Forum section init

pull/24/head
Ezerous 8 years ago
parent
commit
bca02536c9
  1. 2
      app/build.gradle
  2. 102
      app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumAdapter.java
  3. 125
      app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java
  4. 3
      app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentAdapter.java
  5. 4
      app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java
  6. 34
      app/src/main/java/gr/thmmy/mthmmy/data/Board.java
  7. 58
      app/src/main/java/gr/thmmy/mthmmy/data/Category.java
  8. 1
      app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java
  9. 29
      app/src/main/res/layout/fragment_forum.xml
  10. 16
      app/src/main/res/layout/fragment_forum_board_row.xml
  11. 27
      app/src/main/res/layout/fragment_forum_category_row.xml
  12. 3
      app/src/main/res/layout/fragment_recent.xml

2
app/build.gradle

@ -43,6 +43,8 @@ dependencies {
}
compile 'com.mikepenz:fontawesome-typeface:4.7.0.0@aar'
compile 'pl.droidsonroids.gif:android-gif-drawable:1.2.3'
compile 'com.google.code.gson:gson:2.8.0'
compile 'com.bignerdranch.android:expandablerecyclerview:3.0.0-RC1'
}
apply plugin: 'com.google.gms.google-services'

102
app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumAdapter.java

@ -1,16 +1,24 @@
package gr.thmmy.mthmmy.activities.main.forum;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import com.bignerdranch.expandablerecyclerview.ChildViewHolder;
import com.bignerdranch.expandablerecyclerview.ExpandableRecyclerAdapter;
import com.bignerdranch.expandablerecyclerview.ParentViewHolder;
import java.util.List;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.base.BaseFragment;
import gr.thmmy.mthmmy.data.Board;
import gr.thmmy.mthmmy.data.Category;
import gr.thmmy.mthmmy.data.TopicSummary;
@ -18,68 +26,90 @@ import gr.thmmy.mthmmy.data.TopicSummary;
* {@link RecyclerView.Adapter} that can display a {@link TopicSummary} and makes a call to the
* specified {@link ForumFragment.ForumFragmentInteractionListener}.
*/
class ForumAdapter extends RecyclerView.Adapter<ForumAdapter.ViewHolder> {
class ForumAdapter extends ExpandableRecyclerAdapter<Category, Board, ForumAdapter.CategoryViewHolder, ForumAdapter.BoardViewHolder> {
private final Context context;
private final List<TopicSummary> recentList;
private final LayoutInflater layoutInflater;
private final List<Category> categories;
private final ForumFragment.ForumFragmentInteractionListener mListener;
ForumAdapter(Context context, List<TopicSummary> topicSummaryList, BaseFragment.FragmentInteractionListener listener) {
ForumAdapter(Context context, @NonNull List<Category> categories, BaseFragment.FragmentInteractionListener listener) {
super(categories);
this.context = context;
this.recentList = topicSummaryList;
this.categories = categories;
mListener = (ForumFragment.ForumFragmentInteractionListener)listener;
layoutInflater = LayoutInflater.from(context);
}
@NonNull
@Override
public CategoryViewHolder onCreateParentViewHolder(@NonNull ViewGroup parentViewGroup, int viewType) {
View categoryView = layoutInflater.inflate(R.layout.fragment_forum_category_row, parentViewGroup, false);
return new CategoryViewHolder(categoryView);
}
@NonNull
@Override
public ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.fragment_recent_row, parent, false);
return new ViewHolder(view);
public BoardViewHolder onCreateChildViewHolder(@NonNull ViewGroup childViewGroup, int viewType) {
View boardView = layoutInflater.inflate(R.layout.fragment_forum_board_row, childViewGroup, false);
return new BoardViewHolder(boardView);
}
@Override
public void onBindParentViewHolder(@NonNull CategoryViewHolder parentViewHolder, int parentPosition, @NonNull Category parent) {
parentViewHolder.bind(parent);
}
@Override
public void onBindViewHolder(final ViewHolder holder, final int position) {
public void onBindChildViewHolder(@NonNull BoardViewHolder childViewHolder, int parentPosition, int childPosition, @NonNull Board child) {
childViewHolder.bind(child);
}
holder.mTitleView.setText(recentList.get(position).getTitle());
holder.mDateTimeView.setText(recentList.get(position).getDateTimeModified());
holder.mUserView.setText(context.getString(R.string.byUser, recentList.get(position).getLastUser()));
holder.topic = recentList.get(position);
class CategoryViewHolder extends ParentViewHolder {
holder.mView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
private TextView categoryTextview;
private ImageView arrowImageView;
if (null != mListener) {
// Notify the active callbacks interface (the activity, if the
// fragment is attached to one) that an item has been selected.
mListener.onFragmentInteraction(holder.topic); //?
CategoryViewHolder(View itemView) {
super(itemView);
categoryTextview = (TextView) itemView.findViewById(R.id.category);
arrowImageView = (ImageView) itemView.findViewById(R.id.arrow); //todo animated arrow up/down
arrowImageView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (isExpanded()) {
collapseView();
} else {
expandView();
}
}
});
}
void bind(Category category) {
categoryTextview.setText(category.getName());
}
@Override
public int getItemCount() {
return recentList.size();
public boolean shouldItemViewClickToggleExpansion() {
return false;
}
}
class BoardViewHolder extends ChildViewHolder {
private TextView boardTextView;
BoardViewHolder(View itemView) {
super(itemView);
boardTextView = (TextView) itemView.findViewById(R.id.board);
}
class ViewHolder extends RecyclerView.ViewHolder {
final View mView;
final TextView mTitleView;
final TextView mUserView;
final TextView mDateTimeView;
public TopicSummary topic;
ViewHolder(View view) {
super(view);
mView = view;
mTitleView = (TextView) view.findViewById(R.id.title);
mUserView = (TextView) view.findViewById(R.id.lastUser);
mDateTimeView = (TextView) view.findViewById(R.id.dateTime);
void bind(Board board) {
boardTextView.setText(board.getName());
}
}
}

125
app/src/main/java/gr/thmmy/mthmmy/activities/main/forum/ForumFragment.java

@ -2,8 +2,8 @@ package gr.thmmy.mthmmy.activities.main.forum;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.widget.SwipeRefreshLayout;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
@ -11,21 +11,23 @@ import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.Toast;
import com.bignerdranch.expandablerecyclerview.ExpandableRecyclerAdapter;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.activities.base.BaseFragment;
import gr.thmmy.mthmmy.data.Board;
import gr.thmmy.mthmmy.data.Category;
import gr.thmmy.mthmmy.data.TopicSummary;
import gr.thmmy.mthmmy.session.SessionManager;
import gr.thmmy.mthmmy.utils.CustomRecyclerView;
import mthmmy.utils.Report;
import okhttp3.HttpUrl;
import okhttp3.Request;
@ -45,10 +47,9 @@ public class ForumFragment extends BaseFragment
// Fragment initialization parameters, e.g. ARG_SECTION_NUMBER
private ProgressBar progressBar;
private SwipeRefreshLayout swipeRefreshLayout;
private ForumAdapter forumAdapter;
private List<TopicSummary> topicSummaries;
private List<Category> categories;
private ForumTask forumTask;
@ -72,13 +73,13 @@ public class ForumFragment extends BaseFragment
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
topicSummaries = new ArrayList<>();
categories = new ArrayList<>();
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
if (topicSummaries.isEmpty())
if (categories.isEmpty())
{
forumTask =new ForumTask();
forumTask.execute();
@ -91,30 +92,36 @@ public class ForumFragment extends BaseFragment
public View onCreateView(LayoutInflater inflater, ViewGroup container,
Bundle savedInstanceState) {
// Inflate the layout for this fragment
final View rootView = inflater.inflate(R.layout.fragment_recent, container, false);
final View rootView = inflater.inflate(R.layout.fragment_forum, container, false);
// Set the adapter
if (rootView instanceof RelativeLayout) {
progressBar = (ProgressBar) rootView.findViewById(R.id.progressBar);
forumAdapter = new ForumAdapter(getActivity(), topicSummaries, fragmentInteractionListener);
CustomRecyclerView recyclerView = (CustomRecyclerView) rootView.findViewById(R.id.list);
recyclerView.setLayoutManager(new LinearLayoutManager(rootView.findViewById(R.id.list).getContext()));
recyclerView.setAdapter(forumAdapter);
swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.swiperefresh);
swipeRefreshLayout.setOnRefreshListener(
new SwipeRefreshLayout.OnRefreshListener() {
forumAdapter = new ForumAdapter(getContext(), categories, fragmentInteractionListener);
forumAdapter.setExpandCollapseListener(new ExpandableRecyclerAdapter.ExpandCollapseListener() {
@Override
public void onRefresh() {
if (forumTask != null && forumTask.getStatus() != AsyncTask.Status.RUNNING) {
public void onParentExpanded(int parentPosition) {
if(forumTask.getStatus()== AsyncTask.Status.RUNNING)
forumTask.cancel(true);
forumTask =new ForumTask();
forumTask.setUrl(categories.get(parentPosition).getCategoryURL());
forumTask.execute();
}
}
@Override
public void onParentCollapsed(int parentPosition) {
if(forumTask.getStatus()== AsyncTask.Status.RUNNING)
forumTask.cancel(true);
forumTask =new ForumTask();
forumTask.setUrl(categories.get(parentPosition).getCategoryURL());
forumTask.execute();
}
);
});
RecyclerView recyclerView = (RecyclerView) rootView.findViewById(R.id.list);
recyclerView.setLayoutManager(new LinearLayoutManager(rootView.findViewById(R.id.list).getContext()));
recyclerView.setAdapter(forumAdapter);
}
return rootView;
}
@ -134,25 +141,30 @@ public class ForumFragment extends BaseFragment
public class ForumTask extends AsyncTask<Void, Void, Integer> {
private static final String TAG = "ForumTask";
private final HttpUrl thmmyUrl = SessionManager.indexUrl;
private HttpUrl forumUrl = SessionManager.forumUrl; //may change upon collapse/expand
private Document document;
private List<Category> fetchedCategories;
protected void onPreExecute() {
ForumTask() {
fetchedCategories = new ArrayList<>();
}
protected void onPreExecute() {
progressBar.setVisibility(ProgressBar.VISIBLE);
}
protected Integer doInBackground(Void... voids) {
Request request = new Request.Builder()
.url(thmmyUrl)
.url(forumUrl)
.build();
try {
Response response = client.newCall(request).execute();
document = Jsoup.parse(response.body().string());
parse(document);
categories.clear();
categories.addAll(fetchedCategories);
fetchedCategories.clear();
return 0;
} catch (IOException e) {
Report.d(TAG, "Network Error", e);
@ -168,51 +180,46 @@ public class ForumFragment extends BaseFragment
protected void onPostExecute(Integer result) {
if (result == 0)
forumAdapter.notifyDataSetChanged();
forumAdapter.notifyParentDataSetChanged(false);
else if (result == 1)
Toast.makeText(getActivity(), "Network error", Toast.LENGTH_SHORT).show();
progressBar.setVisibility(ProgressBar.INVISIBLE);
swipeRefreshLayout.setRefreshing(false);
}
private void parse(Document document) {
Elements recent = document.select("#block8 :first-child div");
if (recent.size() == 30) {
topicSummaries.clear();
for (int i = 0; i < recent.size(); i += 3) {
String link = recent.get(i).child(0).attr("href");
String title = recent.get(i).child(0).attr("title");
private void parse(Document document)
{
Elements categoryBlocks = document.select(".tborder:not([style])>table[cellpadding=5]");
if (categoryBlocks.size() != 0) {
for(Element categoryBlock: categoryBlocks)
{
Element categoryElement = categoryBlock.select("td[colspan=2]>[name]").first();
String categoryUrl = categoryElement.attr("href");
Category category = new Category(categoryElement.text(), categoryUrl);
String lastUser = recent.get(i + 1).text();
Pattern pattern = Pattern.compile("\\b (.*)");
Matcher matcher = pattern.matcher(lastUser);
if (matcher.find())
lastUser = matcher.group(1);
else {
Report.e(TAG, "Parsing failed (lastUser)!");
return;
category.setExpanded(categoryUrl.contains("sa=collapse"));
if(categoryUrl.contains("sa=collapse"))
{
category.setExpanded(true);
Elements boardsElements = categoryBlock.select("b [name]");
for(Element boardElement: boardsElements) {
Board board = new Board(boardElement.text(), boardElement.attr("href"));
category.getBoards().add(board);
}
String dateTime = recent.get(i + 2).text();
pattern = Pattern.compile("\\[(.*)\\]");
matcher = pattern.matcher(dateTime);
if (matcher.find())
dateTime = matcher.group(1);
else {
Report.e(TAG, "Parsing failed (dateTime)!");
return;
}
else
category.setExpanded(false);
topicSummaries.add(new TopicSummary(link, title, lastUser, dateTime));
fetchedCategories.add(category);
}
return;
}
else
Report.e(TAG, "Parsing failed!");
}
}
public void setUrl(String string)
{
forumUrl = HttpUrl.parse(string);
}
}
}

3
app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentAdapter.java

@ -1,6 +1,7 @@
package gr.thmmy.mthmmy.activities.main.recent;
import android.content.Context;
import android.support.annotation.NonNull;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
@ -23,7 +24,7 @@ class RecentAdapter extends RecyclerView.Adapter<RecentAdapter.ViewHolder> {
private final List<TopicSummary> recentList;
private final RecentFragment.RecentFragmentInteractionListener mListener;
RecentAdapter(Context context, List<TopicSummary> topicSummaryList, BaseFragment.FragmentInteractionListener listener) {
RecentAdapter(Context context, @NonNull List<TopicSummary> topicSummaryList, BaseFragment.FragmentInteractionListener listener) {
this.context = context;
this.recentList = topicSummaryList;
mListener = (RecentFragment.RecentFragmentInteractionListener) listener;

4
app/src/main/java/gr/thmmy/mthmmy/activities/main/recent/RecentFragment.java

@ -135,12 +135,10 @@ public class RecentFragment extends BaseFragment {
//---------------------------------------ASYNC TASK-----------------------------------
public class RecentTask extends AsyncTask<Void, Void, Integer> {
private static final String TAG = "ForumTask";
private static final String TAG = "RecentTask";
private final HttpUrl thmmyUrl = SessionManager.indexUrl;
private Document document;
protected void onPreExecute() {
progressBar.setVisibility(ProgressBar.VISIBLE);

34
app/src/main/java/gr/thmmy/mthmmy/data/Board.java

@ -0,0 +1,34 @@
package gr.thmmy.mthmmy.data;
import java.util.ArrayList;
public class Board {
private final String name;
private final String boardURL;
private ArrayList <Board> subBoards;
private ArrayList <TopicSummary> topicSummaries;
public Board(String name, String boardURL) {
this.name = name;
this.boardURL = boardURL;
subBoards = new ArrayList<>();
topicSummaries = new ArrayList<>();
}
public String getName() {
return name;
}
public String getBoardURL() {
return boardURL;
}
public ArrayList<Board> getSubBoards() {
return subBoards;
}
public ArrayList<TopicSummary> getTopicSummaries() {
return topicSummaries;
}
}

58
app/src/main/java/gr/thmmy/mthmmy/data/Category.java

@ -0,0 +1,58 @@
package gr.thmmy.mthmmy.data;
import com.bignerdranch.expandablerecyclerview.model.Parent;
import java.util.ArrayList;
import java.util.List;
import static android.R.attr.id;
public class Category implements Parent<Board>
{
private final String name;
private final String categoryURL;
private boolean expanded = false;
private List<Board> boards;
public Category(String name, String categoryURL) {
this.name = name;
this.categoryURL = categoryURL;
boards = new ArrayList<>();
}
public int getId() {
return id;
}
public String getName() {
return name;
}
public String getCategoryURL() {
return categoryURL;
}
public boolean isExpanded() {
return expanded;
}
public List<Board> getBoards() {
return boards;
}
public void setExpanded(boolean expanded) {
this.expanded = expanded;
}
@Override
public List<Board> getChildList() {
return getBoards();
}
@Override
public boolean isInitiallyExpanded() {
return expanded;
}
}

1
app/src/main/java/gr/thmmy/mthmmy/session/SessionManager.java

@ -36,6 +36,7 @@ public class SessionManager
//Generic constants
public static final HttpUrl indexUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php");
public static final HttpUrl forumUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=forum");
private static final HttpUrl loginUrl = HttpUrl.parse("https://www.thmmy.gr/smf/index.php?action=login2");
private static final String guestName = "Guest";

29
app/src/main/res/layout/fragment_forum.xml

@ -0,0 +1,29 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.RecyclerView
android:id="@+id/list"
android:name="gr.thmmy.mthmmy.sections.forum.ForumFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"
android:clipToPadding="false"
android:paddingBottom="4dp"
android:paddingTop="4dp"
app:layoutManager="LinearLayoutManager"
tools:context=".activities.main.forum.ForumFragment" />
<ProgressBar
android:id="@+id/progressBar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:visibility="invisible"/>
</RelativeLayout>

16
app/src/main/res/layout/fragment_forum_board_row.xml

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
android:paddingEnd="4dp"
android:paddingStart="4dp">
<TextView
android:id="@+id/board"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="@color/primary_text"/>
</LinearLayout>

27
app/src/main/res/layout/fragment_forum_category_row.xml

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingEnd="4dp"
android:paddingStart="4dp">
<TextView
android:id="@+id/category"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentStart="true"
android:textAppearance="?attr/textAppearanceListItem"
android:textColor="@color/md_yellow_600"/>
<ImageView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentEnd="true"
app:srcCompat="@android:drawable/arrow_down_float"
android:id="@+id/arrow"
android:contentDescription="arrow" />
</RelativeLayout>

3
app/src/main/res/layout/fragment_recent.xml

@ -11,10 +11,9 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<view
<gr.thmmy.mthmmy.utils.CustomRecyclerView
android:id="@+id/list"
android:name="gr.thmmy.mthmmy.sections.recent.RecentFragment"
class="gr.thmmy.mthmmy.utils.CustomRecyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/background"

Loading…
Cancel
Save