A mobile app for thmmy.gr
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

953 lines
40 KiB

package gr.thmmy.mthmmy.activities;
import android.animation.Animator;
import android.animation.AnimatorListenerAdapter;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.ActionBar;
import android.support.v7.widget.CardView;
import android.text.TextUtils;
import android.util.Log;
import android.util.SparseArray;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import com.android.volley.toolbox.ImageLoader;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import javax.net.ssl.SSLHandshakeException;
import gr.thmmy.mthmmy.R;
import gr.thmmy.mthmmy.data.Post;
import gr.thmmy.mthmmy.utils.CircularNetworkImageView;
import gr.thmmy.mthmmy.utils.ImageController;
import okhttp3.Request;
import okhttp3.Response;
public class TopicActivity extends BaseActivity {
//-----------------------------------------CLASS VARIABLES------------------------------------------
/* --Posts-- */
private List<Post> postsList;
private LinearLayout postsLinearLayout;
private static final int NO_POST_FOCUS = -1;
private int postFocus = NO_POST_FOCUS;
//Quote
//TODO
/* --Topic's pages-- */
private int thisPage = 1;
private String base_url = "";
private int numberOfPages = 1;
private final SparseArray<String> pagesUrls = new SparseArray<>();
//Page select
private TextView pageIndicator;
private final Handler repeatUpdateHandler = new Handler();
private final long INITIAL_DELAY = 500;
private boolean autoIncrement = false;
private boolean autoDecrement = false;
private static final int SMALL_STEP = 1;
private static final int LARGE_STEP = 10;
private Integer pageValue;
private ImageButton firstPage;
private ImageButton previousPage;
private ImageButton nextPage;
private ImageButton lastPage;
/* --Thumbnail-- */
private static final int THUMBNAIL_SIZE = 80;
private ImageLoader imageLoader = ImageController.getInstance().getImageLoader();
//Other variables
private ProgressBar progressBar;
private static final String TAG = "TopicActivity";
private String topicTitle;
private String parsedTitle;
private ActionBar actionbar;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_topic);
Bundle extras = getIntent().getExtras();
topicTitle = getIntent().getExtras().getString("TOPIC_TITLE");
//Variables initialization
postsLinearLayout = (LinearLayout) findViewById(R.id.posts_list);
progressBar = (ProgressBar) findViewById(R.id.progressBar);
if (imageLoader == null)
imageLoader = ImageController.getInstance().getImageLoader();
postsList = new ArrayList<>();
actionbar = getSupportActionBar();
if (actionbar != null)
if(!Objects.equals(topicTitle, ""))
actionbar.setTitle(topicTitle);
firstPage = (ImageButton) findViewById(R.id.page_first_button);
previousPage = (ImageButton) findViewById(R.id.page_previous_button);
pageIndicator = (TextView) findViewById(R.id.page_indicator);
nextPage = (ImageButton) findViewById(R.id.page_next_button);
lastPage = (ImageButton) findViewById(R.id.page_last_button);
initDecrementButton(firstPage, LARGE_STEP);
initDecrementButton(previousPage, SMALL_STEP);
initIncrementButton(nextPage, SMALL_STEP);
initIncrementButton(lastPage, LARGE_STEP);
firstPage.setEnabled(false);
previousPage.setEnabled(false);
nextPage.setEnabled(false);
lastPage.setEnabled(false);
new TopicTask().execute(extras.getString("TOPIC_URL")); //Attempt data parsing
}
@Override
protected void onDestroy() { //When finished cancel whatever request can still be canceled
super.onDestroy();
ImageController.getInstance().cancelPendingRequests();
}
private void initIncrementButton(ImageButton increment, final int step){
// Increment once for a click
increment.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(!autoIncrement && step == LARGE_STEP){ //If just clicked go to last page
changePage(numberOfPages - 1);
return;
}
//Clicked and holden
autoIncrement = false; //Stop incrementing
increment(step);
changePage(pageValue - 1);
}
});
// Auto increment for a long click
increment.setOnLongClickListener(
new View.OnLongClickListener(){
public boolean onLongClick(View arg0) {
autoIncrement = true;
repeatUpdateHandler.postDelayed(new RepetitiveUpdater(step), INITIAL_DELAY);
return false;
}
}
);
// When the button is released
increment.setOnTouchListener( new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if( event.getAction() == MotionEvent.ACTION_UP && autoIncrement ){
changePage(pageValue - 1);
}
return false;
}
});
}
private void initDecrementButton(ImageButton decrement, final int step){
// Decrement once for a click
decrement.setOnClickListener(new View.OnClickListener() {
public void onClick(View v) {
if(!autoDecrement && step == LARGE_STEP){ //If just clicked go to first page
changePage(0);
return;
}
//Clicked and holden
autoDecrement = false; //Stop incrementing
decrement(step);
changePage(pageValue - 1);
}
});
// Auto Decrement for a long click
decrement.setOnLongClickListener(
new View.OnLongClickListener(){
public boolean onLongClick(View arg0) {
autoDecrement = true;
repeatUpdateHandler.postDelayed( new RepetitiveUpdater(step), INITIAL_DELAY);
return false;
}
}
);
// When the button is released
decrement.setOnTouchListener( new View.OnTouchListener() {
public boolean onTouch(View v, MotionEvent event) {
if( event.getAction() == MotionEvent.ACTION_UP && autoDecrement ){
changePage(pageValue - 1);
}
return false;
}
});
}
private void increment(int step){
if( pageValue < numberOfPages - step){
pageValue = pageValue + step;
}
else
pageValue = numberOfPages;
pageIndicator.setText(pageValue + "/" + String.valueOf(numberOfPages));
if(pageValue >= 1000)
pageIndicator.setTextSize(16);
else
pageIndicator.setTextSize(20);
}
private void decrement(int step){
if( pageValue > step)
pageValue = pageValue - step;
else
pageValue = 1;
pageIndicator.setText(pageValue + "/" + String.valueOf(numberOfPages));
if(numberOfPages >= 1000)
pageIndicator.setTextSize(16);
else
pageIndicator.setTextSize(20);
}
private void changePage(int pageRequested){
if(pageRequested != thisPage - 1){
//Restart activity with new page
Intent intent = getIntent();
intent.putExtra("TOPIC_URL", pagesUrls.get(pageRequested));
intent.putExtra("TOPIC_TITLE", topicTitle);
finish();
startActivity(intent);
}
}
//---------------------------------------TOPIC ASYNC TASK-------------------------------------------
public class TopicTask extends AsyncTask<String, Void, Boolean> {
//Class variables
private static final String TAG = "TopicTask"; //Separate tag for AsyncTask
//Show a progress bar until done
protected void onPreExecute() {
progressBar.setVisibility(ProgressBar.VISIBLE);
}
protected Boolean doInBackground(String... strings) {
Document document;
base_url = strings[0].substring(0, strings[0].lastIndexOf(".")); //This topic's base url
String pageUrl = strings[0]; //This page's url
//Find message focus if present
{
if(pageUrl.contains("msg")){
String tmp = pageUrl.substring(pageUrl.indexOf("msg") + 3);
if(tmp.contains(";"))
postFocus = Integer.parseInt(tmp.substring(0, tmp.indexOf(";")));
else
postFocus = Integer.parseInt(tmp.substring(0, tmp.indexOf("#")));
}
}
Request request = new Request.Builder()
.url(pageUrl)
.build();
try {
Response response = client.newCall(request).execute();
document = Jsoup.parse(response.body().string());
parse(document); //Parse data
return true;
} catch (SSLHandshakeException e) {
Log.w(TAG, "Certificate problem (please switch to unsafe connection).");
} catch (Exception e) {
Log.e("TAG", "ERROR", e);
}
return false;
}
protected void onPostExecute(Boolean result) {
if (!result) { //Parse failed!
//Should never happen
Toast.makeText(getBaseContext()
, "Fatal error!\n Aborting...", Toast.LENGTH_LONG).show();
finish();
}
//Parse was successful
progressBar.setVisibility(ProgressBar.INVISIBLE); //Hide progress bar
populateLayout(); //Show parsed data
//Set current page
pageIndicator.setText(String.valueOf(thisPage) + "/" + String.valueOf(numberOfPages));
pageValue = thisPage;
if(numberOfPages >= 1000)
pageIndicator.setTextSize(16);
}
/* Parse method */
private void parse(Document document) {
//Method's variables
final int NO_INDEX = -1;
//Find topic title if missing
if(topicTitle == null || Objects.equals(topicTitle, "")){
parsedTitle = document.select("td[id=top_subject]").first().text();
Log.d(TAG, parsedTitle);
parsedTitle = parsedTitle.substring(parsedTitle.indexOf("Topic:") + 7
, parsedTitle.indexOf("(Read") - 8);
Log.d(TAG, parsedTitle);
}
{ //Find current page's index
Elements findCurrentPage = document.select("td:contains(Pages:)>b"); //Contains pages
for (Element item : findCurrentPage) {
if (!item.text().contains("...") //It's not "..."
&& !item.text().contains("Pages")) { //Nor "Pages"
thisPage = Integer.parseInt(item.text());
break;
}
}
}
{ //Find number of pages
Elements pages = document.select("td:contains(Pages:)>a.navPages"); //Contains all pages
if (pages.size() != 0) {
numberOfPages = thisPage; //Initialize the number
for (Element item : pages) { //Just a max
if (Integer.parseInt(item.text()) > numberOfPages)
numberOfPages = Integer.parseInt(item.text());
}
}
for (int i = 0; i < numberOfPages; i++) {
//Generate each page's url from topic's base url +".15*numberOfPage"
pagesUrls.put(i, base_url + "." + String.valueOf(i * 15));
}
}
//Each element is a post's row
Elements rows = document.select("form[id=quickModForm]>table>tbody>tr:matches(on)");
for (Element item : rows) { //For every post
//Variables to pass
String p_userName, p_thumbnailUrl, p_subject, p_post, p_postDate, p_rank,
p_specialRank, p_gender, p_personalText, p_numberOfPosts, p_urlOfStars;
int p_postNum, p_postIndex, p_numberOfStars;
boolean p_isDeleted = false;
//Initialize variables
p_rank = "Rank";
p_specialRank = "Special rank";
p_gender = "";
p_personalText = "";
p_numberOfPosts = "";
p_urlOfStars = "";
p_numberOfStars = 0;
//Find the Username
Element userName = item.select("a[title^=View the profile of]").first();
if (userName == null) { //Deleted profile
p_isDeleted = true;
p_userName = item
.select("td:has(div.smalltext:containsOwn(Guest))[style^=overflow]")
.first().text();
p_userName = p_userName.substring(0, p_userName.indexOf(" Guest"));
} else
p_userName = userName.html();
//Find thumbnail url
Element thumbnailUrl = item.select("img.avatar").first();
p_thumbnailUrl = null; //In case user doesn't have an avatar
if (thumbnailUrl != null) {
p_thumbnailUrl = thumbnailUrl.attr("abs:src");
}
//Find subject
p_subject = item.select("div[id^=subject_]").first().select("a").first().text();
//Find post's text
p_post = item.select("div").select(".post").first().html();
//Add stuff to make it work in WebView
p_post = ("<link rel=\"stylesheet\" type=\"text/css\" href=\"style.css\" />"
+ p_post); //style.css
//Find post's submit date
Element postDate = item.select("div.smalltext:matches(on:)").first();
p_postDate = postDate.text();
p_postDate = p_postDate.substring(p_postDate.indexOf("on:") + 4
, p_postDate.indexOf(" »"));
//Find post's number
Element postNum = item.select("div.smalltext:matches(Reply #)").first();
if (postNum == null) { //Topic starter
p_postNum = 0;
} else {
String tmp_str = postNum.text().substring(9);
p_postNum = Integer.parseInt(tmp_str.substring(0, tmp_str.indexOf(" on")));
}
//Find post's index
Element postIndex = item.select("a[name^=msg]").first();
if (postIndex == null)
p_postIndex = NO_INDEX;
else {
String tmp = postIndex.attr("name");
p_postIndex = Integer.parseInt(tmp.substring(tmp.indexOf("msg") + 3));
}
if (!p_isDeleted) { //Active user
//Get extra info
int postsLineIndex = -1;
int starsLineIndex = -1;
Element info = userName.parent().nextElementSibling(); //Get sibling "div"
List<String> infoList = Arrays.asList(info.html().split("<br>"));
for (String line : infoList) {
Log.i(TAG, line);
if (line.contains("Posts:")) {
postsLineIndex = infoList.indexOf(line);
//Remove any line breaks and spaces on the start and end
p_numberOfPosts = line.replace("\n", "")
.replace("\r", "").trim();
}
if (line.contains("Gender:")) {
if (line.contains("alt=\"Male\""))
p_gender = "Gender: Male";
else
p_gender = "Gender: Female";
}
if (line.contains("alt=\"*\"")) {
starsLineIndex = infoList.indexOf(line);
Document starsHtml = Jsoup.parse(line);
p_numberOfStars = starsHtml.select("img[alt]").size();
p_urlOfStars = starsHtml.select("img[alt]").first().attr("abs:src");
}
}
//If this member has no stars yet ==> New member,
//or is just a member
if (starsLineIndex == -1 || starsLineIndex == 1) {
//In this case:
p_rank = infoList.get(0).trim(); //First line has the rank
p_specialRank = null; //They don't have a special rank
} else if (starsLineIndex == 2) { //This member has a special rank
p_specialRank = infoList.get(0).trim(); //First line has the special rank
p_rank = infoList.get(1).trim(); //Second line has the rank
}
for (int i = postsLineIndex + 1; i < infoList.size() - 1; ++i) {
//Search under "Posts:"
//and above "Personal Message", "View Profile" etc buttons
String thisLine = infoList.get(i);
//If this line isn't empty and doesn't contain user's avatar
if (!Objects.equals(thisLine, "") && thisLine != null
&& !Objects.equals(thisLine, " \n")
&& !thisLine.contains("avatar")
&& !thisLine.contains("<a href=")) {
p_personalText = thisLine; //Then this line has user's personal text
//Remove any line breaks and spaces on the start and end
p_personalText = p_personalText.replace("\n", "")
.replace("\r", "").trim();
}
}
//Add new post in postsList, extended information needed
postsList.add(new Post(p_thumbnailUrl, p_userName, p_subject, p_post
, p_postIndex, p_postNum, p_postDate, p_isDeleted, p_rank
, p_specialRank, p_gender, p_numberOfPosts, p_personalText
, p_urlOfStars, p_numberOfStars));
} else{ //Deleted user
//Add new post in postsList, only standard information needed
postsList.add(new Post(p_thumbnailUrl, p_userName, p_subject
, p_post, p_postIndex, p_postNum, p_postDate, p_isDeleted));
}
}
}
/* Parse method end */
}
//-------------------------------------TOPIC ASYNC TASK END-----------------------------------------
//----------------------------------------POPULATE UI METHOD----------------------------------------
/**
* This method runs on the main thread. It reads from the postsList and dynamically
* adds a card for each post to the ScrollView.
*/
private void populateLayout() {
//Set topic title if not already present
if (topicTitle == null || Objects.equals(topicTitle, "")) {
topicTitle = parsedTitle;
if (actionbar != null){
actionbar.setTitle(topicTitle);
}
}
//Now that parsing is complete and we have the url for every page enable page nav buttons
firstPage.setEnabled(true);
previousPage.setEnabled(true);
nextPage.setEnabled(true);
lastPage.setEnabled(true);
//Initialize an inflater
LayoutInflater inflater = (LayoutInflater) getApplicationContext()
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
//Create a card for each post
for (Post item : postsList) {
//Inflate a topic post row layout
View convertView = inflater.inflate(R.layout.activity_topic_post_row
, postsLinearLayout, false);
//Get an ImageLoader instance
if (imageLoader == null)
imageLoader = ImageController.getInstance().getImageLoader();
//Initialize layout's graphic elements
//Basic stuff
final CardView cardView = (CardView) convertView.findViewById(R.id.card_view);
final FrameLayout postDateAndNumberExp = (FrameLayout) convertView.findViewById(R.id.post_date_and_number_exp);
TextView postDate = (TextView) convertView.findViewById(R.id.post_date);
TextView postNum = (TextView) convertView.findViewById(R.id.post_number);
CircularNetworkImageView thumbnail = (CircularNetworkImageView) convertView.findViewById(R.id.thumbnail);
final TextView username = (TextView) convertView.findViewById(R.id.username);
final TextView subject = (TextView) convertView.findViewById(R.id.subject);
final WebView post = (WebView) convertView.findViewById(R.id.post);
//User's extra
RelativeLayout header = (RelativeLayout) convertView.findViewById(R.id.header);
final LinearLayout userExtraInfo = (LinearLayout) convertView.findViewById(R.id.user_extra_info);
//Post's WebView parameters set
post.setClickable(true);
post.setWebViewClient(new LinkLauncher());
//Avoiding errors about layout having 0 width/height
thumbnail.setMinimumWidth(1);
thumbnail.setMinimumHeight(1);
//Set thumbnail size
thumbnail.setMaxWidth(THUMBNAIL_SIZE);
thumbnail.setMaxHeight(THUMBNAIL_SIZE);
//Thumbnail image set
if (item.getThumbnailUrl() != null) {
thumbnail.setImageUrl(item.getThumbnailUrl(), imageLoader);
}
//Username set
username.setText(item.getAuthor());
//Post's submit date set
postDate.setText(item.getPostDate());
//Post's index number set
if (item.getPostNumber() != 0)
postNum.setText("#" + item.getPostNumber());
else
postNum.setText("");
//Post's subject set
subject.setText(item.getSubject());
//Post's text set
post.loadDataWithBaseURL("file:///android_asset/", item.getContent(), "text/html", "UTF-8", null);
//If user is not deleted then we have more to do
if(!item.isDeleted()) { //Set extra info
//Variables for Graphics
TextView g_specialRank, g_rank, g_gender, g_numberOfPosts, g_personalText;
LinearLayout g_stars_holder = (LinearLayout) convertView.findViewById(R.id.stars);
//Variables for content
String c_specialRank = item.getSpecialRank()
, c_rank = item.getRank()
, c_gender = item.getGender()
, c_numberOfPosts = item.getNumberOfPosts()
, c_personalText = item.getPersonalText()
, c_urlOfStars = item.getUrlOfStars();
int c_numberOfStars = item.getNumberOfStars();
if(!Objects.equals(c_specialRank, "") && c_specialRank != null){
g_specialRank = (TextView) convertView.findViewById(R.id.special_rank);
g_specialRank.setText(c_specialRank);
g_specialRank.setVisibility(View.VISIBLE);
}
if(!Objects.equals(c_rank, "") && c_rank != null){
g_rank = (TextView) convertView.findViewById(R.id.rank);
g_rank.setText(c_rank);
g_rank.setVisibility(View.VISIBLE);
}
if(!Objects.equals(c_gender, "") && c_gender != null){
g_gender = (TextView) convertView.findViewById(R.id.gender);
g_gender.setText(c_gender);
g_gender.setVisibility(View.VISIBLE);
}
if(!Objects.equals(c_numberOfPosts, "") && c_numberOfPosts != null){
g_numberOfPosts = (TextView) convertView.findViewById(R.id.number_of_posts);
g_numberOfPosts.setText(c_numberOfPosts);
g_numberOfPosts.setVisibility(View.VISIBLE);
}
if(!Objects.equals(c_personalText, "") && c_personalText != null){
g_personalText = (TextView) convertView.findViewById(R.id.personal_text);
g_personalText.setText("\"" + c_personalText + "\"");
g_personalText.setVisibility(View.VISIBLE);
}
for(int i=0; i<c_numberOfStars; ++i){
CircularNetworkImageView star = new CircularNetworkImageView(this);
star.setImageUrl(c_urlOfStars, imageLoader);
//Remove spacing between stars...
//Don't know why this is happening in the first place
LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
LinearLayout.LayoutParams.WRAP_CONTENT,
LinearLayout.LayoutParams.WRAP_CONTENT
);
params.setMargins((int) getResources().getDimension(R.dimen.stars_margin)
, 0
, (int) getResources().getDimension(R.dimen.stars_margin)
, 0);
star.setLayoutParams(params);
g_stars_holder.addView(star, 0);
g_stars_holder.setVisibility(View.VISIBLE);
}
/* --Header expand/collapse functionality-- */
header.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
animateUserExtraInfoVisibility(userExtraInfo);
}
});
//Clicking the expanded part of a header should collapse the extra info
userExtraInfo.setOnClickListener(new View.OnClickListener(){
@Override
public void onClick(View v){
animateUserExtraInfoVisibility(v);
}
});
/* --Header expand/collapse functionality end-- */
}
/* --Card expand/collapse functionality-- */
//Should expand/collapse when card is touched
cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
animatePostExtraInfoVisibility(postDateAndNumberExp, username, subject);
}
});
//Also when post is clicked
post.setOnTouchListener(new View.OnTouchListener() {
//Long press handling
private final int LONG_PRESS_DURATION = 1000;
private final Handler webViewLongClickHandler = new Handler();
private boolean wasLongClick = false;
private float downCoordinateX;
private float downCoordinateY;
private final float SCROLL_THRESHOLD = 7;
final Runnable WebViewLongClick = new Runnable() {
public void run() {
wasLongClick = true;
//TODO
}
};
//Other variables
final static int FINGER_RELEASED = 0;
final static int FINGER_TOUCHED = 1;
final static int FINGER_DRAGGING = 2;
final static int FINGER_UNDEFINED = 3;
private int fingerState = FINGER_RELEASED;
@Override
public boolean onTouch(View view, MotionEvent motionEvent) {
switch (motionEvent.getAction()) {
case MotionEvent.ACTION_DOWN:
downCoordinateX = motionEvent.getX();
downCoordinateY = motionEvent.getY();
if (fingerState == FINGER_RELEASED)
fingerState = FINGER_TOUCHED;
else
fingerState = FINGER_UNDEFINED;
//Start long click runnable
webViewLongClickHandler.postDelayed(WebViewLongClick
, LONG_PRESS_DURATION);
break;
case MotionEvent.ACTION_UP:
fingerState = FINGER_RELEASED;
webViewLongClickHandler.removeCallbacks(WebViewLongClick);
if(!wasLongClick) {
//If this was a link don't expand the card
WebView.HitTestResult htResult = post.getHitTestResult();
if (htResult.getExtra() != null
&& htResult.getExtra() != null)
return false;
//Else expand/collapse card
cardView.performClick();
}
else
wasLongClick = false;
break;
case MotionEvent.ACTION_MOVE:
//If finger moved too much, cancel long click
if (((Math.abs(downCoordinateX - motionEvent.getX()) > SCROLL_THRESHOLD ||
Math.abs(downCoordinateY - motionEvent.getY()) > SCROLL_THRESHOLD))) {
webViewLongClickHandler.removeCallbacks(WebViewLongClick);
}
if (fingerState == FINGER_TOUCHED || fingerState == FINGER_DRAGGING)
fingerState = FINGER_DRAGGING;
else fingerState = FINGER_UNDEFINED;
break;
default:
fingerState = FINGER_UNDEFINED;
}
return false;
}
});
/* --Card expand/collapse-like functionality end-- */
//Add view to the linear layout that holds all posts
postsLinearLayout.addView(convertView);
//Set post focus
if(postFocus != NO_POST_FOCUS){
if(item.getPostIndex() == postFocus){
//TODO
}
}
}
}
//--------------------------------------POPULATE UI METHOD END--------------------------------------
//--------------------------POST'S INFO VISIBILITY CHANGE ANIMATION METHOD--------------------------
/**
* Method that animates view's visibility changes for post's extra info
*/
private void animatePostExtraInfoVisibility(final View dateAndPostNum, TextView username,
TextView subject) {
//If the view is gone fade it in
if (dateAndPostNum.getVisibility() == View.GONE) {
//Show full username
username.setMaxLines(Integer.MAX_VALUE); //As in the android sourcecode
username.setEllipsize(null);
//Show full subject
subject.setTextColor(ContextCompat.getColor(this, R.color.black));
subject.setMaxLines(Integer.MAX_VALUE); //As in the android sourcecode
subject.setEllipsize(null);
dateAndPostNum.clearAnimation();
// Prepare the View for the animation
dateAndPostNum.setVisibility(View.VISIBLE);
dateAndPostNum.setAlpha(0.0f);
// Start the animation
dateAndPostNum.animate()
.translationY(0)
.alpha(1.0f)
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
dateAndPostNum.setVisibility(View.VISIBLE);
}
});
}
//If the view is visible fade it out
else {
username.setMaxLines(1); //As in the android sourcecode
username.setEllipsize(TextUtils.TruncateAt.END);
subject.setTextColor(ContextCompat.getColor(this, R.color.secondary_text));
subject.setMaxLines(1); //As in the android sourcecode
subject.setEllipsize(TextUtils.TruncateAt.END);
dateAndPostNum.clearAnimation();
// Start the animation
dateAndPostNum.animate()
.translationY(dateAndPostNum.getHeight())
.alpha(0.0f)
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
dateAndPostNum.setVisibility(View.GONE);
}
});
}
}
//------------------------POST'S INFO VISIBILITY CHANGE ANIMATION METHOD END------------------------
//--------------------------USER'S INFO VISIBILITY CHANGE ANIMATION METHOD--------------------------
/**
* Method that animates view's visibility changes for user's extra info
*/
private void animateUserExtraInfoVisibility(final View userExtra){
//If the view is gone fade it in
if (userExtra.getVisibility() == View.GONE) {
userExtra.clearAnimation();
userExtra.setVisibility(View.VISIBLE);
userExtra.setAlpha(0.0f);
// Start the animation
userExtra.animate()
.translationY(0)
.alpha(1.0f)
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
userExtra.setVisibility(View.VISIBLE);
}
});
}
//If the view is visible fade it out
else {
userExtra.clearAnimation();
// Start the animation
userExtra.animate()
.translationY(userExtra.getHeight())
.alpha(0.0f)
.setDuration(300)
.setListener(new AnimatorListenerAdapter() {
@Override
public void onAnimationEnd(Animator animation) {
super.onAnimationEnd(animation);
userExtra.setVisibility(View.GONE);
}
});
}
}
//------------------------POST'S INFO VISIBILITY CHANGE ANIMATION METHOD END------------------------
//--------------------------------------CUSTOM WEBVIEW CLIENT---------------------------------------
/**
* This class is used to handle link clicks in WebViews.
* When link url is one that the app can handle internally, it does.
* Otherwise user is prompt to open the link in a browser.
*/
private class LinkLauncher extends WebViewClient { //Used to handle link clicks
//Older versions
@SuppressWarnings("deprecation")
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
final Uri uri = Uri.parse(url);
return handleUri(uri);
}
//Newest versions
@TargetApi(Build.VERSION_CODES.N)
@Override
public boolean shouldOverrideUrlLoading(WebView view, WebResourceRequest request) {
final Uri uri = request.getUrl();
return handleUri(uri);
}
//Handle url clicks
private boolean handleUri(final Uri uri) {
//Method always returns true as we don't want any url to be loaded in WebViews
Log.i(TAG, "Uri =" + uri);
final String host = uri.getHost(); //Get requested url's host
//Determine if you are going to pass the url to a
//host's application activity or load it in a browser.
if (Objects.equals(host, "www.thmmy.gr")) {
//This is my web site, so figure out what Activity should launch
if (uri.toString().contains("topic=")) { //This url points to a topic
//Is the link pointing to current topic?
if(Objects.equals(
uri.toString().substring(0, uri.toString().lastIndexOf(".")), base_url)){
//Don't restart Activity
//Just change post focus
//TODO
}
else {
//Restart activity with new data
Intent intent = getIntent();
intent.putExtra("TOPIC_URL", uri.toString());
intent.putExtra("TOPIC_TITLE", "");
finish();
startActivity(intent);
}
}
return true;
}
//Otherwise, the link is not for a page on my site, so launch
//another Activity that handles URLs
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
startActivity(intent);
return true;
}
}
//------------------------------------CUSTOM WEBVIEW CLIENT END-------------------------------------
//----------------------------------------REPETITIVE UPDATER----------------------------------------
/**
* This class is used to implement the repetitive increment/decrement of page value
* when long pressing one of the page navigation buttons.
*/
class RepetitiveUpdater implements Runnable {
private final int step;
RepetitiveUpdater(int step){this.step = step;}
public void run() {
long REPEAT_DELAY = 250;
if( autoIncrement ){
increment(step);
repeatUpdateHandler.postDelayed( new RepetitiveUpdater(step), REPEAT_DELAY);
} else if( autoDecrement ){
decrement(step);
repeatUpdateHandler.postDelayed( new RepetitiveUpdater(step), REPEAT_DELAY);
}
}
}
//--------------------------------------REPETITIVE UPDATER END--------------------------------------
}