diff --git a/app/build.gradle b/app/build.gradle
index e6c6380b..0cf9686f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -33,8 +33,8 @@ dependencies {
compile 'com.android.support:cardview-v7:25.0.1'
compile 'com.android.support:recyclerview-v7:25.0.1'
compile 'com.squareup.okhttp3:okhttp:3.5.0'
+ compile 'com.squareup.picasso:picasso:2.5.2'
compile 'org.jsoup:jsoup:1.10.1'
- compile 'com.android.volley:volley:1.0.0'
compile 'com.github.franmontiel:PersistentCookieJar:v1.0.0'
compile('com.mikepenz:materialdrawer:5.8.0@aar') {
transitive = true
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 8e49bf42..45de250a 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -6,7 +6,6 @@
postsList;
- private LinearLayout postsLinearLayout;
private static final int NO_POST_FOCUS = -1;
private int postFocus = NO_POST_FOCUS;
//Quote
- private final ArrayList toQuoteList = new ArrayList<>();
+ public static final ArrayList toQuoteList = new ArrayList<>();
/* --Topic's pages-- */
private int thisPage = 1;
- private String base_url = "";
+ public static String base_url = "";
private int numberOfPages = 1;
private final SparseArray pagesUrls = new SparseArray<>();
//Page select
@@ -83,21 +66,19 @@ public class TopicActivity extends BaseActivity {
private static final int SMALL_STEP = 1;
private static final int LARGE_STEP = 10;
private Integer pageRequestValue;
+
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;
+ @SuppressWarnings("unused")
private static final String TAG = "TopicActivity";
private String topicTitle;
- private String parsedTitle;
private FloatingActionButton replyFAB;
+ private String parsedTitle;
@Override
protected void onCreate(Bundle savedInstanceState) {
@@ -107,7 +88,7 @@ public class TopicActivity extends BaseActivity {
Bundle extras = getIntent().getExtras();
topicTitle = getIntent().getExtras().getString("TOPIC_TITLE");
- //Initialize toolbar
+ //Initialize toolbar, drawer and ProgressBar
toolbar = (Toolbar) findViewById(R.id.toolbar);
toolbar.setTitle(topicTitle);
setSupportActionBar(toolbar);
@@ -116,14 +97,8 @@ public class TopicActivity extends BaseActivity {
createDrawer();
- //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<>();
@@ -137,6 +112,7 @@ public class TopicActivity extends BaseActivity {
initDecrementButton(previousPage, SMALL_STEP);
initIncrementButton(nextPage, SMALL_STEP);
initIncrementButton(lastPage, LARGE_STEP);
+
firstPage.setEnabled(false);
previousPage.setEnabled(false);
nextPage.setEnabled(false);
@@ -211,11 +187,10 @@ public class TopicActivity extends BaseActivity {
@Override
protected void onDestroy() { //When finished cancel whatever request can still be canceled
super.onDestroy();
- ImageController.getInstance().cancelPendingRequests();
}
-//--------------------------------------BOTTOM NAV BAR METHODS--------------------------------------
+ //--------------------------------------BOTTOM NAV BAR METHODS--------------------------------------
private void initIncrementButton(ImageButton increment, final int step) {
// Increment once for a click
increment.setOnClickListener(new View.OnClickListener() {
@@ -318,8 +293,8 @@ public class TopicActivity extends BaseActivity {
private void changePage(int pageRequested) {
if (pageRequested != thisPage - 1) {
//Restart activity with new page
- Pair p1 = Pair.create((View)replyFAB, "fab");
- Pair p2 = Pair.create((View)toolbar, "toolbar");
+ Pair p1 = Pair.create((View) replyFAB, "fab");
+ Pair p2 = Pair.create((View) toolbar, "toolbar");
ActivityOptionsCompat options = ActivityOptionsCompat.
makeSceneTransitionAnimation(this, p1, p2);
@@ -332,7 +307,7 @@ public class TopicActivity extends BaseActivity {
}
//------------------------------------BOTTOM NAV BAR METHODS END------------------------------------
-//---------------------------------------TOPIC ASYNC TASK-------------------------------------------
+ //---------------------------------------TOPIC ASYNC TASK-------------------------------------------
public class TopicTask extends AsyncTask {
//Class variables
private static final String TAG = "TopicTask"; //Separate tag for AsyncTask
@@ -389,6 +364,14 @@ public class TopicActivity extends BaseActivity {
pageRequestValue = thisPage;
if (numberOfPages >= 1000)
pageIndicator.setTextSize(16);
+
+ firstPage.setEnabled(true);
+ previousPage.setEnabled(true);
+ nextPage.setEnabled(true);
+ lastPage.setEnabled(true);
+
+ if (topicTitle == null || Objects.equals(topicTitle, ""))
+ toolbar.setTitle(parsedTitle);
}
/* Parse method */
@@ -396,11 +379,10 @@ public class TopicActivity extends BaseActivity {
//Find topic title if missing
if (topicTitle == null || Objects.equals(topicTitle, "")) {
parsedTitle = document.select("td[id=top_subject]").first().text();
- if(parsedTitle.contains("Topic:")) {
+ if (parsedTitle.contains("Topic:")) {
parsedTitle = parsedTitle.substring(parsedTitle.indexOf("Topic:") + 7
, parsedTitle.indexOf("(Read") - 2);
- }
- else{
+ } else {
parsedTitle = parsedTitle.substring(parsedTitle.indexOf("Θέμα:") + 6
, parsedTitle.indexOf("(Αναγνώστηκε") - 2);
Log.d(TAG, parsedTitle);
@@ -432,298 +414,26 @@ public class TopicActivity extends BaseActivity {
* adds a card for each post to the ScrollView.
*/
private void populateLayout() {
- //Enable reply button
- replyFAB.setEnabled(true);
-
- //Set topic title if not already present
- if (topicTitle == null || Objects.equals(topicTitle, "")) {
- topicTitle = parsedTitle;
- if (toolbar != null) {
- toolbar.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 (final Post currentPost : 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);
- final ImageButton quoteToggle = (ImageButton) convertView.findViewById(R.id.toggle_quote_button);
-
- //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());
- post.getSettings().setJavaScriptEnabled(true);
- //TODO
- post.getSettings().setPluginState(WebSettings.PluginState.ON_DEMAND);
-
-
-
- //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 (currentPost.getThumbnailUrl() != null
- && !Objects.equals(currentPost.getThumbnailUrl(), "")) {
- thumbnail.setImageUrl(currentPost.getThumbnailUrl(), imageLoader);
- }
-
- //Username set
- username.setText(currentPost.getAuthor());
-
- //Post's submit date set
- postDate.setText(currentPost.getPostDate());
-
- //Post's index number set
- if (currentPost.getPostNumber() != 0)
- postNum.setText(getString(R.string.user_number_of_posts, currentPost.getPostNumber()));
- //postNum.setText("#" + currentPost.getPostNumber());
- else
- postNum.setText("");
-
- //Post's subject set
- subject.setText(currentPost.getSubject());
-
- //Post's text set
- post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null);
-
- quoteToggle.setOnClickListener(new View.OnClickListener() {
- @Override
- public void onClick(View view) {
- if (view.isSelected()) {
- if (toQuoteList.contains(currentPost.getPostNumber())) {
- toQuoteList.remove(toQuoteList.indexOf(currentPost.getPostNumber()));
- view.setSelected(false);
- } else
- Log.i(TAG, "An error occurred while trying to exclude post from" +
- "toQuoteList, post wasn't there!");
- } else {
- toQuoteList.add(currentPost.getPostNumber());
- view.setSelected(true);
- }
- }
- });
-
- //If user is not deleted then we have more to do
- if (!currentPost.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 = currentPost.getSpecialRank(), c_rank = currentPost.getRank(), c_gender = currentPost.getGender(), c_numberOfPosts = currentPost.getNumberOfPosts(), c_personalText = currentPost.getPersonalText(), c_urlOfStars = currentPost.getUrlOfStars();
- int c_numberOfStars = currentPost.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) {
- TopicAnimations.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) {
- TopicAnimations.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) {
- TopicAnimations.animatePostExtraInfoVisibility(postDateAndNumberExp
- , username, subject
- ,ContextCompat.getColor(getApplicationContext(), R.color.black)
- ,ContextCompat.getColor(getApplicationContext(), R.color.secondary_text));
- }
- });
-
- //Also when post is clicked
- post.setOnTouchListener(new CustomTouchListener(post,cardView, quoteToggle));
-
- /* --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) {
+ RecyclerView recyclerView = (RecyclerView)findViewById(R.id.topic_recycler_view);
+ recyclerView.setHasFixedSize(true);
+ RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
+ recyclerView.setLayoutManager(layoutManager);
+
+ TopicAdapter adapter = new TopicAdapter(getApplicationContext(), postsList);
+ recyclerView.setAdapter(adapter);
+
+ //Set post focus
+ if (postFocus != NO_POST_FOCUS) {
+ for (int i = 0; i < postsList.size(); ++i) {
+ Post currentPost = postsList.get(i);
if (currentPost.getPostIndex() == postFocus) {
//TODO
}
}
}
}
-//--------------------------------------POPULATE UI 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.
- */
- @SuppressWarnings("unchecked")
- 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
- final String uriString = uri.toString();
-
- //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 (uriString.contains("topic=")) { //This url points to a topic
- //Is the link pointing to current topic?
- if (Objects.equals(
- uriString.substring(0, uriString.lastIndexOf(".")), base_url)) {
-
- //Get uri's targeted message's index number
- String msgIndexReq = uriString.substring(uriString.indexOf("msg") + 3);
- if (msgIndexReq.contains("#"))
- msgIndexReq = msgIndexReq.substring(0, msgIndexReq.indexOf("#"));
- else
- msgIndexReq = msgIndexReq.substring(0, msgIndexReq.indexOf(";"));
-
- //Is this post already shown now? (is it in current page?)
- for (Post post : postsList) {
- if (post.getPostIndex() == Integer.parseInt(msgIndexReq)) {
- //Don't restart Activity
- //Just change post focus
- //TODO
- return true;
- }
- }
- }
- //Restart activity with new data
- Pair p1 = Pair.create((View) replyFAB, "fab");
- Pair p2 = Pair.create((View) toolbar, "toolbar");
- ActivityOptionsCompat options = ActivityOptionsCompat.
- makeSceneTransitionAnimation(TopicActivity.this, p1, p2);
-
- Intent intent = getIntent();
- intent.putExtra("TOPIC_URL", uri.toString());
- intent.putExtra("TOPIC_TITLE", "");
- startActivity(intent, options.toBundle());
- finish();
-
- }
- 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-------------------------------------
+//--------------------------------------POPULATE UI METHOD END--------------------------------------
//----------------------------------------REPETITIVE UPDATER----------------------------------------
@@ -750,94 +460,4 @@ public class TopicActivity extends BaseActivity {
}
}
//--------------------------------------REPETITIVE UPDATER END--------------------------------------
-
-//--------------------------------------CUSTOM TOUCH LISTENER---------------------------------------
- /**
- * This class is a gesture detector for WebViews.
- * It handles post's clicks, long clicks and touch and drag.
- */
-
- private class CustomTouchListener implements View.OnTouchListener {
- //Long press handling
- private final int LONG_PRESS_DURATION = 650;
- private final Handler webViewLongClickHandler = new Handler();
- private boolean wasLongClick = false;
- private float downCoordinateX;
- private float downCoordinateY;
- private final float SCROLL_THRESHOLD = 7;
- final private WebView post;
- final private CardView cardView;
- final private ImageButton quoteToggle;
-
- //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;
-
- CustomTouchListener(WebView pPost, CardView pCard, ImageButton pQuoteToggle){
- post = pPost;
- cardView = pCard;
- quoteToggle = pQuoteToggle;
- }
-
- final Runnable WebViewLongClick = new Runnable() {
- public void run() {
- wasLongClick = true;
- quoteToggle.performClick();
- }
- };
-
- @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:
- webViewLongClickHandler.removeCallbacks(WebViewLongClick);
-
- if (!wasLongClick && fingerState != FINGER_DRAGGING) {
- //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;
- fingerState = FINGER_RELEASED;
- 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);
- fingerState = FINGER_DRAGGING;
- } else fingerState = FINGER_UNDEFINED;
- break;
-
- default:
- fingerState = FINGER_UNDEFINED;
-
- }
- return false;
- }
- }
-//------------------------------------CUSTOM TOUCH LISTENER END-------------------------------------
}
\ No newline at end of file
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
new file mode 100644
index 00000000..938225c4
--- /dev/null
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
@@ -0,0 +1,431 @@
+package gr.thmmy.mthmmy.activities.topic;
+
+import android.annotation.TargetApi;
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Color;
+import android.net.Uri;
+import android.os.Build;
+import android.os.Handler;
+import android.support.v4.content.res.ResourcesCompat;
+import android.support.v7.widget.CardView;
+import android.support.v7.widget.RecyclerView;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.MotionEvent;
+import android.view.View;
+import android.view.ViewGroup;
+import android.webkit.WebResourceRequest;
+import android.webkit.WebView;
+import android.webkit.WebViewClient;
+import android.widget.FrameLayout;
+import android.widget.ImageButton;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+
+import com.squareup.picasso.Picasso;
+
+import java.util.List;
+import java.util.Objects;
+
+import gr.thmmy.mthmmy.R;
+import gr.thmmy.mthmmy.data.Post;
+import gr.thmmy.mthmmy.utils.CircleTransform;
+
+import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK;
+import static gr.thmmy.mthmmy.activities.topic.TopicActivity.base_url;
+import static gr.thmmy.mthmmy.activities.topic.TopicActivity.toQuoteList;
+
+class TopicAdapter extends RecyclerView.Adapter {
+ private static final String TAG = "TopicAdapter";
+
+ private static int THUMBNAIL_SIZE;
+ private final Context context;
+ private final List postsList;
+
+ class MyViewHolder extends RecyclerView.ViewHolder {
+ final CardView cardView;
+ final FrameLayout postDateAndNumberExp;
+ final TextView postDate, postNum, username, subject;
+ final ImageView thumbnail;
+ final public WebView post;
+ final ImageButton quoteToggle;
+ final RelativeLayout header;
+ final LinearLayout userExtraInfo;
+
+ final TextView specialRank, rank, gender, numberOfPosts, personalText;
+ final LinearLayout stars_holder;
+
+ MyViewHolder(View view) {
+ super(view);
+
+ //Initialize layout's graphic elements
+ //Basic stuff
+ cardView = (CardView) view.findViewById(R.id.card_view);
+ postDateAndNumberExp = (FrameLayout) view.findViewById(R.id.post_date_and_number_exp);
+ postDate = (TextView) view.findViewById(R.id.post_date);
+ postNum = (TextView) view.findViewById(R.id.post_number);
+ thumbnail = (ImageView) view.findViewById(R.id.thumbnail);
+ username = (TextView) view.findViewById(R.id.username);
+ subject = (TextView) view.findViewById(R.id.subject);
+ post = (WebView) view.findViewById(R.id.post);
+ quoteToggle = (ImageButton) view.findViewById(R.id.toggle_quote_button);
+
+ //User's extra
+ header = (RelativeLayout) view.findViewById(R.id.header);
+ userExtraInfo = (LinearLayout) view.findViewById(R.id.user_extra_info);
+ specialRank = (TextView) view.findViewById(R.id.special_rank);
+ rank = (TextView) view.findViewById(R.id.rank);
+ gender = (TextView) view.findViewById(R.id.gender);
+ numberOfPosts = (TextView) view.findViewById(R.id.number_of_posts);
+ personalText = (TextView) view.findViewById(R.id.personal_text);
+ stars_holder = (LinearLayout) view.findViewById(R.id.stars);
+ }
+
+ /**
+ * Possible cleanup needed (like so:)
+ * https://stackoverflow.com/questions/24897441/picasso-how-to-cancel-all-image-requests-made-in-an-adapter
+ * TODO
+ */
+ }
+
+
+ TopicAdapter(Context context, List postsList) {
+ this.context = context;
+ this.postsList = postsList;
+
+ THUMBNAIL_SIZE = (int) context.getResources().getDimension(R.dimen.thumbnail_size);
+ }
+
+ @Override
+ public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.activity_topic_post_row, parent, false);
+
+ return new MyViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindViewHolder(final MyViewHolder holder, int position) {
+ final Post currentPost = postsList.get(position);
+
+ //Post's WebView parameters set
+ holder.post.setClickable(true);
+ holder.post.setWebViewClient(new LinkLauncher());
+ holder.post.getSettings().setJavaScriptEnabled(true);
+
+ //Avoiding errors about layout having 0 width/height
+ holder.thumbnail.setMinimumWidth(1);
+ holder.thumbnail.setMinimumHeight(1);
+ //Set thumbnail size
+ holder.thumbnail.setMaxWidth(THUMBNAIL_SIZE);
+ holder.thumbnail.setMaxHeight(THUMBNAIL_SIZE);
+
+ //noinspection ConstantConditions
+ Picasso.with(context)
+ .load(currentPost.getThumbnailUrl())
+ .resize(THUMBNAIL_SIZE,THUMBNAIL_SIZE)
+ .centerCrop()
+ .error(ResourcesCompat.getDrawable(context.getResources()
+ , R.drawable.ic_default_user_thumbnail, null))
+ .placeholder(ResourcesCompat.getDrawable(context.getResources()
+ , R.drawable.ic_default_user_thumbnail, null))
+ .transform(new CircleTransform())
+ .into(holder.thumbnail);
+
+ //Username set
+ holder.username.setText(currentPost.getAuthor());
+
+ //Post's submit date set
+ holder.postDate.setText(currentPost.getPostDate());
+
+ //Post's index number set
+ if (currentPost.getPostNumber() != 0)
+ holder.postNum.setText(context.getString(
+ R.string.user_number_of_posts, currentPost.getPostNumber()));
+ else
+ holder.postNum.setText("");
+
+ //Post's subject set
+ holder.subject.setText(currentPost.getSubject());
+
+ //Post's text set
+ holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null);
+
+ holder.quoteToggle.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View view) {
+ if (view.isSelected()) {
+ if (toQuoteList.contains(currentPost.getPostNumber())) {
+ toQuoteList.remove(toQuoteList.indexOf(currentPost.getPostNumber()));
+ view.setSelected(false);
+ } else
+ Log.i(TAG, "An error occurred while trying to exclude post from" +
+ "toQuoteList, post wasn't there!");
+ } else {
+ toQuoteList.add(currentPost.getPostNumber());
+ view.setSelected(true);
+ }
+ }
+ });
+
+ //If user is not deleted then we have more to do
+ if (!currentPost.isDeleted()) { //Set extra info
+ //Variables for content
+ String c_specialRank = currentPost.getSpecialRank(), c_rank = currentPost.getRank(), c_gender = currentPost.getGender(), c_numberOfPosts = currentPost.getNumberOfPosts(), c_personalText = currentPost.getPersonalText(), c_urlOfStars = currentPost.getUrlOfStars();
+ int c_numberOfStars = currentPost.getNumberOfStars();
+
+ if (!Objects.equals(c_specialRank, "") && c_specialRank != null) {
+ holder.specialRank.setText(c_specialRank);
+ holder.specialRank.setVisibility(View.VISIBLE);
+ }
+ if (!Objects.equals(c_rank, "") && c_rank != null) {
+ holder.rank.setText(c_rank);
+ holder.rank.setVisibility(View.VISIBLE);
+ }
+ if (!Objects.equals(c_gender, "") && c_gender != null) {
+ holder.gender.setText(c_gender);
+ holder.gender.setVisibility(View.VISIBLE);
+ }
+ if (!Objects.equals(c_numberOfPosts, "") && c_numberOfPosts != null) {
+ holder.numberOfPosts.setText(c_numberOfPosts);
+ holder.numberOfPosts.setVisibility(View.VISIBLE);
+ }
+ if (!Objects.equals(c_personalText, "") && c_personalText != null) {
+ holder.personalText.setText("\"" + c_personalText + "\"");
+ holder.personalText.setVisibility(View.VISIBLE);
+ }
+
+ for (int i = 0; i < c_numberOfStars; ++i) {
+ ImageView star = new ImageView(context);
+
+ Picasso.with(context)
+ .load(c_urlOfStars)
+ .into(star);
+
+ //Remove spacing between stars...
+ //Don't know why this is happening in the first place
+ //TODO change layout? other solution?
+ LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(
+ LinearLayout.LayoutParams.WRAP_CONTENT,
+ LinearLayout.LayoutParams.WRAP_CONTENT
+ );
+ params.setMargins((int) context.getResources().getDimension(R.dimen.stars_margin)
+ , 0
+ , (int) context.getResources().getDimension(R.dimen.stars_margin)
+ , 0);
+ star.setLayoutParams(params);
+
+ holder.stars_holder.addView(star, 0);
+ holder.stars_holder.setVisibility(View.VISIBLE);
+ }
+
+ /* --Header expand/collapse functionality-- */
+
+ holder.header.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ TopicAnimations.animateUserExtraInfoVisibility(holder.userExtraInfo);
+ }
+ });
+
+ //Clicking the expanded part of a header should collapse the extra info
+ holder.userExtraInfo.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ TopicAnimations.animateUserExtraInfoVisibility(v);
+ }
+ });
+ /* --Header expand/collapse functionality end-- */
+ }
+
+ /* --Card expand/collapse functionality-- */
+
+ //Should expand/collapse when card is touched
+ holder.cardView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ TopicAnimations.animatePostExtraInfoVisibility(holder.postDateAndNumberExp
+ , holder.username, holder.subject
+ , Color.parseColor("#000000")
+ , Color.parseColor("#757575"));
+ }
+ });
+
+ //Also when post is clicked
+ holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView, holder.quoteToggle));
+ }
+
+ @Override
+ public int getItemCount() {
+ return postsList.size();
+ }
+
+//--------------------------------------CUSTOM TOUCH LISTENER---------------------------------------
+
+ /**
+ * This class is a gesture detector for WebViews.
+ * It handles post's clicks, long clicks and touch and drag.
+ */
+
+ private class CustomTouchListener implements View.OnTouchListener {
+ //Long press handling
+ private final int LONG_PRESS_DURATION = 650;
+ private final Handler webViewLongClickHandler = new Handler();
+ private boolean wasLongClick = false;
+ private float downCoordinateX;
+ private float downCoordinateY;
+ private final float SCROLL_THRESHOLD = 7;
+ final private WebView post;
+ final private CardView cardView;
+ final private ImageButton quoteToggle;
+
+ //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;
+
+ CustomTouchListener(WebView pPost, CardView pCard, ImageButton pQuoteToggle) {
+ post = pPost;
+ cardView = pCard;
+ quoteToggle = pQuoteToggle;
+ }
+
+ final Runnable WebViewLongClick = new Runnable() {
+ public void run() {
+ wasLongClick = true;
+ quoteToggle.performClick();
+ }
+ };
+
+ @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:
+ webViewLongClickHandler.removeCallbacks(WebViewLongClick);
+
+ if (!wasLongClick && fingerState != FINGER_DRAGGING) {
+ //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;
+ fingerState = FINGER_RELEASED;
+ 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);
+ fingerState = FINGER_DRAGGING;
+ } else fingerState = FINGER_UNDEFINED;
+ break;
+
+ default:
+ fingerState = FINGER_UNDEFINED;
+
+ }
+ return false;
+ }
+ }
+//------------------------------------CUSTOM TOUCH LISTENER 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.
+ */
+ @SuppressWarnings("unchecked")
+ 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 clicked = " + uri);
+ final String host = uri.getHost(); //Get requested url's host
+ final String uriString = uri.toString();
+
+ //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 (uriString.contains("topic=")) { //This url points to a topic
+ //Is the link pointing to current topic?
+ if (Objects.equals(
+ uriString.substring(0, uriString.lastIndexOf(".")), base_url)) {
+
+ //Get uri's targeted message's index number
+ String msgIndexReq = uriString.substring(uriString.indexOf("msg") + 3);
+ if (msgIndexReq.contains("#"))
+ msgIndexReq = msgIndexReq.substring(0, msgIndexReq.indexOf("#"));
+ else
+ msgIndexReq = msgIndexReq.substring(0, msgIndexReq.indexOf(";"));
+
+ //Is this post already shown now? (is it in current page?)
+ for (Post post : postsList) {
+ if (post.getPostIndex() == Integer.parseInt(msgIndexReq)) {
+ //Don't restart Activity
+ //Just change post focus
+ //TODO
+ return true;
+ }
+ }
+ }
+ //Restart activity with new data
+ //TODO
+ }
+ 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);
+ intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
+ context.startActivity(intent);
+ return true;
+ }
+ }
+//------------------------------------CUSTOM WEBVIEW CLIENT END-------------------------------------
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java
index 771b86ca..5b49cf65 100644
--- a/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java
+++ b/app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicParser.java
@@ -1,7 +1,5 @@
package gr.thmmy.mthmmy.activities.topic;
-import android.util.Log;
-
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
@@ -28,6 +26,7 @@ class TopicParser {
private static String genderAltMale;
private static String genderAltFemale;
+ @SuppressWarnings("unused")
private static final String TAG = "TopicParser";
static int parseCurrentPageIndex(Document doc) {
@@ -123,15 +122,18 @@ class TopicParser {
for (Element _noembed : noembedTag) {
embededVideosUrls.add(_noembed.text().substring(_noembed.text()
- .indexOf("href=\"https://www.youtube.com/watch?") + 6
- , _noembed.text().indexOf("target") - 6));
+ .indexOf("href=\"https://www.youtube.com/watch?") + 38
+ , _noembed.text().indexOf("target") - 2));
}
int tmp_counter = 0;
while (p_post.contains("