com.achow101.bitcointalkforum.fragments.TopicFragment.java Source code

Java tutorial

Introduction

Here is the source code for com.achow101.bitcointalkforum.fragments.TopicFragment.java

Source

/*
 * Copyright (c) 2015 Andrew Chow
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

package com.achow101.bitcointalkforum.fragments;

import android.app.Activity;
import android.content.Context;
import android.database.DataSetObserver;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.AsyncTask;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.text.Html;
import android.text.Spanned;
import android.text.method.LinkMovementMethod;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.ListAdapter;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import com.achow101.bitcointalkforum.R;
import com.achow101.bitcointalkforum.items.Board;
import com.achow101.bitcointalkforum.items.Post;
import com.achow101.bitcointalkforum.items.Poster;
import com.achow101.bitcointalkforum.items.Topic;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.nodes.TextNode;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;

public class TopicFragment extends Fragment {

    private String mTopicURL;
    private String mSessId;

    private ProgressBar mProgressView;

    private Button mPrevButton;
    private Button mNextButton;
    private Button mReplyButton;

    private ListView mListView;

    private TextView mPageNumText;

    private GetPosts mGetPostsTask;

    private OnTopicInteraction mListener;

    public static TopicFragment newInstance(String topicURL, String sessId) {
        TopicFragment fragment = new TopicFragment();
        Bundle args = new Bundle();
        args.putString("Topic URL", topicURL);
        args.putString("Session ID", sessId);
        fragment.setArguments(args);
        return fragment;
    }

    public TopicFragment() {
        // Required empty public constructor
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        View v = inflater.inflate(R.layout.fragment_topic, container, false);

        // Get arguments stuff
        mTopicURL = getArguments().getString("Topic URL");
        mSessId = getArguments().getString("Session ID");

        // Get layout stuff
        mProgressView = (ProgressBar) v.findViewById(R.id.posts_progress_bar);
        mListView = (ListView) v.findViewById(R.id.posts_list);
        mPrevButton = (Button) v.findViewById(R.id.prev_page_button);
        mNextButton = (Button) v.findViewById(R.id.next_page_button);
        mReplyButton = (Button) v.findViewById(R.id.reply_button);

        // Set page number
        mPageNumText = (TextView) v.findViewById(R.id.page_num);

        // get posts
        showProgress(true);
        mGetPostsTask = new GetPosts(mTopicURL, mSessId);
        mGetPostsTask.execute((Void) null);

        return v;
    }

    public void showProgress(final boolean show) {
        // Show and hide ui stuff
        mProgressView.setVisibility(show ? View.VISIBLE : View.GONE);
        mListView.setVisibility(show ? View.GONE : View.VISIBLE);
        mPrevButton.setVisibility(show ? View.GONE : View.VISIBLE);
        mNextButton.setVisibility(show ? View.GONE : View.VISIBLE);
        mPageNumText.setVisibility(show ? View.GONE : View.VISIBLE);
        mReplyButton.setVisibility(show ? View.GONE : View.VISIBLE);
    }

    @Override
    public void onAttach(Activity activity) {
        super.onAttach(activity);
        try {
            mListener = (OnTopicInteraction) activity;
        } catch (ClassCastException e) {
            throw new ClassCastException(activity.toString() + " must implement OnTopicInteraction");
        }
    }

    @Override
    public void onDetach() {
        super.onDetach();
        mListener = null;
    }

    private class PostsListAdapter implements ListAdapter {
        private List<Post> posts;

        public PostsListAdapter(List<Post> posts) {
            this.posts = posts;
        }

        @Override
        public boolean areAllItemsEnabled() {
            return false;
        }

        @Override
        public boolean isEnabled(int position) {
            return false;
        }

        @Override
        public void registerDataSetObserver(DataSetObserver observer) {

        }

        @Override
        public void unregisterDataSetObserver(DataSetObserver observer) {

        }

        @Override
        public int getCount() {
            return posts.size();
        }

        @Override
        public Object getItem(int position) {
            return posts.get(position);
        }

        @Override
        public long getItemId(int position) {
            return posts.get(position).getId();
        }

        @Override
        public boolean hasStableIds() {
            return true;
        }

        @Override
        public View getView(int position, View convertView, ViewGroup parent) {
            View v = convertView;
            if (v == null) {
                LayoutInflater infalInflater = (LayoutInflater) getContext()
                        .getSystemService(Context.LAYOUT_INFLATER_SERVICE);
                v = infalInflater.inflate(R.layout.post_layout, null);
            }

            // Get post and poster
            final Post post = posts.get(position);
            Poster poster = post.getPoster();

            // Get post text views
            TextView subjectTitle = (TextView) v.findViewById(R.id.subject_title);
            TextView postTime = (TextView) v.findViewById(R.id.post_time);

            // Set post text views
            subjectTitle.setText(post.getSubject());
            postTime.setText(post.getPostedTime());

            // Get poster text views
            TextView posterTxt = (TextView) v.findViewById(R.id.poster);
            TextView rank = (TextView) v.findViewById(R.id.rank);
            TextView personalText = (TextView) v.findViewById(R.id.personal_text);
            TextView activity = (TextView) v.findViewById(R.id.activity);
            TextView specialPos = (TextView) v.findViewById(R.id.spec_pos);

            // set text for poster
            posterTxt.setText(poster.getName());
            rank.setText(poster.getRank());
            activity.setText(poster.getActivityStr());
            personalText.setText(poster.getPersonalText());

            // Get and set poster avatar image
            ImageView avatar = (ImageView) v.findViewById(R.id.avatar);
            avatar.setImageDrawable(poster.getAvatar());

            // Set special position text
            if (poster.isSpecial())
                specialPos.setText(poster.getSpecialPos());
            else {
                specialPos.setText("");
                specialPos.setVisibility(View.GONE);
            }

            // Set rank coins
            ImageView coins = (ImageView) v.findViewById(R.id.coins);
            if (poster.isSpecial() && !poster.getSpecialPos().equals("Staff")) {
                switch (poster.getSpecialPos()) {
                case "Administrator":
                    coins.setImageResource(R.drawable.admin);
                    break;
                case "Global Moderator":
                    coins.setImageResource(R.drawable.global_mod);
                    break;
                case "Founder":
                    coins.setImageResource(R.drawable.founder);
                    break;
                case "Moderator":
                    coins.setImageResource(R.drawable.moderator);
                    break;
                case "Donator":
                    coins.setImageResource(R.drawable.donator);
                    break;
                case "VIP":
                    coins.setImageResource(R.drawable.vip);
                    break;
                }
            } else {
                switch (poster.getRank()) {
                case "Brand New":
                    coins.setImageResource(R.drawable.coin);
                    break;
                case "Newbie":
                    coins.setImageResource(R.drawable.coin);
                    break;
                case "Jr. Member":
                    coins.setImageResource(R.drawable.coin);
                    break;
                case "Member":
                    coins.setImageResource(R.drawable.member);
                    break;
                case "Full Member":
                    coins.setImageResource(R.drawable.full);
                    break;
                case "Sr. Member":
                    coins.setImageResource(R.drawable.sr);
                    break;
                case "Hero Member":
                    coins.setImageResource(R.drawable.hero);
                    break;
                case "Legendary":
                    coins.setImageResource(R.drawable.legendary);
                }
            }

            // Display the post
            TextView postText = (TextView) v.findViewById(R.id.post);
            postText.setText(post.getPostBody());
            postText.setMovementMethod(LinkMovementMethod.getInstance());

            // Get the buttons
            Button quoteButton = (Button) v.findViewById(R.id.quote_button);
            Button editButton = (Button) v.findViewById(R.id.edit_button);
            Button replyButton = (Button) v.findViewById(R.id.reply_button);
            Button deleteButton = (Button) v.findViewById(R.id.delete_button);

            // Hide reply button
            replyButton.setVisibility(View.GONE);

            // Hide delete and edit buttons if post is not by user
            if (post.getDeleteURL() == null) {
                deleteButton.setVisibility(View.GONE);
            } else {
                deleteButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mListener.onPageSelected(post.getDeleteURL());
                    }
                });
            }

            if (post.getEditURL() == null) {
                editButton.setVisibility(View.GONE);
            } else {
                editButton.setOnClickListener(new View.OnClickListener() {
                    @Override
                    public void onClick(View v) {
                        mListener.onReplySelected(post.getEditURL());
                    }
                });
            }

            // Set listener for quote button
            quoteButton.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mListener.onReplySelected(post.getQuoteURL());
                }
            });

            return v;
        }

        @Override
        public int getItemViewType(int position) {
            return 1;
        }

        @Override
        public int getViewTypeCount() {
            return 1;
        }

        @Override
        public boolean isEmpty() {
            return false;
        }

    }

    private class GetPosts extends AsyncTask<Void, Void, List<List<Object>>> {
        private String topicURL;
        private String sessId;

        public GetPosts(String topicURL, String sessId) {
            this.topicURL = topicURL;
            this.sessId = sessId;
        }

        @Override
        protected List<List<Object>> doInBackground(Void... params) {
            List<Object> posts = new ArrayList<Object>();
            List<Object> nextPrevPageURLS = new ArrayList<Object>();
            List<Object> pageNums = new ArrayList<Object>();
            List<Object> replyURLs = new ArrayList<Object>();

            try {
                Document doc = Jsoup.connect(topicURL).cookie("PHPSESSID", mSessId).get();

                // Get prev and next page URLs
                Elements prevnexts = doc.select("span.prevnext > a.navPages");
                for (Element prevnext : prevnexts) {
                    switch (prevnext.text()) {
                    case "":
                        nextPrevPageURLS.add(prevnext.attr("href"));
                        break;
                    case "":
                        nextPrevPageURLS.add(prevnext.attr("href"));
                        break;
                    }
                }

                // Set current page
                Elements boldNavPages = doc.select("td.middletext[valign=bottom][style=padding-bottom: 4px;] > b");
                for (Element page : boldNavPages) {
                    if (!page.text().contains("..."))
                        pageNums.add(Integer.parseInt(page.text()));
                }

                // Get and set last page
                Element lastNavPage = doc
                        .select("td.middletext[valign=bottom][style=padding-bottom: 4px;] > a.navPages").last();
                if (lastNavPage == null) {
                    pageNums.add(1);
                } else if (Integer.parseInt(lastNavPage.text()) > (Integer) pageNums.get(0)) {
                    pageNums.add(Integer.parseInt(lastNavPage.text()));
                } else {
                    pageNums.add(Integer.parseInt(lastNavPage.text()) + 1);
                }

                // Get table with all the posts
                Elements postsTable = doc.select("div#bodyarea > form > table.bordercolor");

                // Get first post of page and its class name
                String postClassName = postsTable.select("tr").get(0).className();

                // Get all posts on page
                Elements postElements = postsTable.select("tr." + postClassName);

                // Get data from each post
                for (Element post : postElements) {
                    // Get element with posterInfo
                    Element posterInfo = post.select("td.poster_info").first();

                    // Get poster name
                    String posterName = posterInfo.select("b > a[href]").text();

                    // Get poster rank and activity
                    String posterText = posterInfo.text();
                    String posterActivityStr = posterText.substring(posterText.indexOf("Activity"),
                            posterText.indexOf(" ", posterText.indexOf("Activity") + 10));
                    String posterPersText;
                    if (posterText.contains("Ignore")) {
                        posterPersText = posterText.substring(
                                posterText.indexOf(posterActivityStr) + posterActivityStr.length(),
                                posterText.lastIndexOf("Ignore"));
                    } else {
                        posterPersText = posterText
                                .substring(posterText.indexOf(posterActivityStr) + posterActivityStr.length());
                    }

                    // Get rank
                    String posterRank = "Brand New";
                    if (posterText.contains("Brand New"))
                        posterRank = "Brand New";
                    else if (posterText.contains("Newbie"))
                        posterRank = "Newbie";
                    else if (posterText.contains("Jr. Member"))
                        posterRank = "Jr. Member";
                    else if (posterText.contains("Full Member"))
                        posterRank = "Full Member";
                    else if (posterText.contains("Sr. Member"))
                        posterRank = "Sr. Member";
                    else if (posterText.contains("Hero Member"))
                        posterRank = "Hero Member";
                    else if (posterText.contains("Legendary"))
                        posterRank = "Legendary";
                    else if (posterText.contains("Member"))
                        posterRank = "Member";
                    // get special positions
                    String specialPosition = null;
                    if (posterText.contains("Staff"))
                        specialPosition = "Staff";
                    else if (posterText.contains("Global Moderator"))
                        specialPosition = "Global Moderator";
                    else if (posterText.contains("Moderator"))
                        specialPosition = "Moderator";
                    else if (posterText.contains("Administrator"))
                        specialPosition = "Administrator";
                    else if (posterText.contains("Founder"))
                        specialPosition = "Founder";
                    else if (posterText.contains(" Donator"))
                        specialPosition = "Donator";
                    else if (posterText.contains("VIP"))
                        specialPosition = "VIP";

                    // Get poster avatar
                    Elements avatarImgs = posterInfo.select("img.avatar");
                    BitmapDrawable avatar = null;
                    if (!avatarImgs.isEmpty()) {
                        // Get avatar element data
                        Element avatarImg = avatarImgs.first();
                        String avatarURL = avatarImg.absUrl("src");

                        // Download avatar
                        URL url = new URL(avatarURL);
                        HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                        connection.setDoInput(true);
                        connection.connect();
                        InputStream input = connection.getInputStream();
                        avatar = new BitmapDrawable(getResources(), input);
                        avatar.setBounds(0, 0, avatar.getIntrinsicWidth() * 100, avatar.getIntrinsicHeight() * 100);
                    }

                    // Create poster object
                    Poster poster = new Poster(posterName, avatar, posterPersText, posterActivityStr, posterRank);
                    if (specialPosition != null)
                        poster.setSpecialPos(specialPosition);

                    // Get elements with post and header
                    Element headerAndPost = post.select("td.td_headerandpost").first();

                    // Get subject and post times
                    String subject = headerAndPost.select("table > tbody > tr > td > div > a[href]").first().text();
                    String postURL = headerAndPost.select("table > tbody > tr > td > div > a[href]").first()
                            .attr("href");
                    long id = Long.parseLong(postURL.substring(postURL.indexOf("#msg") + 4));
                    String postedTime = headerAndPost.select("table > tbody > tr > td > div.smalltext").first()
                            .text();

                    // Get body of post
                    String postBodyStr = headerAndPost.select(".post").first().html();
                    Spanned postBody = Html.fromHtml(postBodyStr, new ImageGetter(), null);

                    // Get quote, edit, and delete urls
                    Elements URLs = headerAndPost.select("td.td_buttons > div > a[href]");
                    String quoteURL = URLs.first().attr("href");
                    String editURL = null;
                    String deleteURL = null;
                    if (URLs.size() > 2) {
                        editURL = URLs.get(1).attr("href");
                        deleteURL = URLs.get(2).attr("href");
                    }

                    // Create post object
                    Post postObj = new Post(poster, postedTime, subject, postBody, id, quoteURL, editURL,
                            deleteURL);
                    posts.add(postObj);
                }

                // Get the actual reply url
                Elements threadActions = doc.select("td.mirrortab_back > a[href]");
                for (Element item : threadActions) {
                    if (item.text().contains("Reply")) {
                        replyURLs.add(item.attr("href"));
                    } else if (item.text().contains("Watch") || item.text().contains("Unwatch")
                            || item.text().contains("Mark unread") || item.text().contains("Notify")
                            || item.text().contains("Print") || item.text().contains("Lock topic")
                            || item.text().contains("Move Topic")) {

                    } else {
                        replyURLs.add("Thread Locked");
                    }
                }

            } catch (IOException e) {
                e.printStackTrace();
            }

            List<List<Object>> out = new ArrayList<List<Object>>();
            out.add(posts);
            out.add(nextPrevPageURLS);
            out.add(pageNums);
            out.add(replyURLs);

            return out;
        }

        private class ImageGetter implements Html.ImageGetter {

            @Override
            public Drawable getDrawable(String source) {
                // Download bitmap
                if (!source.contains("bitcointalk.org"))
                    source = "https://bitcointalk.org" + source;
                BitmapDrawable bmp = null;
                try {
                    URL url = new URL(source);
                    HttpURLConnection connection = (HttpURLConnection) url.openConnection();
                    connection.setDoInput(true);
                    connection.connect();
                    InputStream input = connection.getInputStream();
                    bmp = new BitmapDrawable(getResources(), input);
                    bmp.setBounds(0, 0, bmp.getIntrinsicWidth() * 10, bmp.getIntrinsicHeight() * 10);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                return bmp;
            }
        }

        @Override
        protected void onPostExecute(List<List<Object>> result) {
            mGetPostsTask = null;
            showProgress(false);

            if (result.size() > 0) {
                List<Object> postObjs = result.get(0);
                final List<Object> prevNextURLs = result.get(1);
                List<Post> posts = new ArrayList<Post>();
                List<Object> pageNums = result.get(2);
                final List<Object> replyURLs = result.get(3);

                for (Object post : postObjs) {
                    posts.add((Post) post);
                }

                if (mTopicURL.contains(".0")) {
                    mPrevButton.setClickable(false);
                    mPrevButton.setVisibility(View.GONE);
                    if (posts.size() < 20) {
                        mNextButton.setClickable(false);
                        mNextButton.setVisibility(View.GONE);
                    } else {
                        mNextButton.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                mListener.onPageSelected((String) prevNextURLs.get(0));
                            }
                        });
                    }
                } else {
                    if (posts.size() < 20) {
                        mNextButton.setClickable(false);
                        mNextButton.setVisibility(View.GONE);
                        mPrevButton.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                mListener.onPageSelected((String) prevNextURLs.get(0));
                            }
                        });
                    } else {
                        mPrevButton.setClickable(true);
                        mNextButton.setClickable(true);
                        mPrevButton.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                mListener.onPageSelected((String) prevNextURLs.get(0));
                            }
                        });
                        mNextButton.setOnClickListener(new View.OnClickListener() {
                            @Override
                            public void onClick(View v) {
                                mListener.onPageSelected((String) prevNextURLs.get(1));
                            }
                        });
                    }
                }

                // Set page numbers
                mPageNumText.setText("Page " + pageNums.get(0) + "/" + pageNums.get(1));

                PostsListAdapter mAdapter = new PostsListAdapter(posts);
                mListView.setAdapter(mAdapter);

                // Scroll to bottom if last post jump
                if (mTopicURL.contains(".msg"))
                    mListView.setSelection(posts.size() - 1);

                final long id = Long.parseLong(mTopicURL.substring(mTopicURL.indexOf("topic=") + 6,
                        mTopicURL.indexOf(".", mTopicURL.indexOf("topic="))));
                final int replyCount = (Integer) pageNums.get(1) * 20;

                if (replyURLs.get(replyURLs.size() - 1).equals("Thread Locked")) {
                    mReplyButton.setVisibility(View.GONE);
                } else {
                    mReplyButton.setVisibility(View.VISIBLE);
                    mReplyButton.setOnClickListener(new View.OnClickListener() {
                        @Override
                        public void onClick(View v) {
                            mListener.onReplySelected((String) replyURLs.get(replyURLs.size() - 1));
                        }
                    });
                }

            } else {
                Toast toast = Toast.makeText(getContext(), "An error occurred", Toast.LENGTH_LONG);
                toast.show();
            }

        }

        @Override
        protected void onCancelled() {
            mGetPostsTask = null;
            showProgress(false);
        }
    }

    public interface OnTopicInteraction {

        public void onPageSelected(String topicURL);

        public void onReplySelected(String replyURL);
    }

}