Browse Source

Topic reply init.

pull/24/head
Apostolos Fanakis 8 years ago
parent
commit
85eef4f8c1
  1. 134
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java
  2. 186
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  3. 3
      app/src/main/res/layout/activity_topic_post_row.xml
  4. 53
      app/src/main/res/layout/activity_topic_quick_reply_row.xml
  5. 2
      app/src/main/res/values/strings.xml

134
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicActivity.java

@ -14,14 +14,19 @@ import android.util.SparseArray;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Selector;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList;
import java.util.Objects;
@ -33,7 +38,9 @@ import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.utils.ParseHelpers;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import mthmmy.utils.Report;
import okhttp3.MultipartBody;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
/**
@ -62,10 +69,11 @@ public class TopicActivity extends BaseActivity {
private TopicAdapter topicAdapter;
private ArrayList<Post> postsList;
private static final int NO_POST_FOCUS = -1;
private static int postFocus = NO_POST_FOCUS;
private int postFocus = NO_POST_FOCUS;
private static int postFocusPosition = 0;
//Quotes
public static final ArrayList<Integer> toQuoteList = new ArrayList<>();
//Reply
private FloatingActionButton replyFAB;
private String replyPageUrl = null;
//Topic's pages
private int thisPage = 1;
private int numberOfPages = 1;
@ -85,7 +93,6 @@ public class TopicActivity extends BaseActivity {
private ImageButton nextPage;
private ImageButton lastPage;
//Other variables
private FloatingActionButton replyFAB;
private MaterialProgressBar progressBar;
private static String base_url = "";
private String topicTitle;
@ -132,42 +139,27 @@ public class TopicActivity extends BaseActivity {
recyclerView.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager);
topicAdapter = new TopicAdapter(this, postsList,
topicTask);
topicAdapter = new TopicAdapter(this, postsList, topicTask);
recyclerView.setAdapter(topicAdapter);
replyFAB = (FloatingActionButton) findViewById(R.id.topic_fab);
replyFAB.setEnabled(false);
replyFAB.hide();
/*if (!sessionManager.isLoggedIn()) replyFAB.hide();
final LinearLayout bottomNavBar = (LinearLayout) findViewById(R.id.bottom_navigation_bar);
if (!sessionManager.isLoggedIn()) replyFAB.hide();
else {
replyFAB.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (sessionManager.isLoggedIn()) {
//TODO Reply
} else {
new AlertDialog.Builder(TopicActivity.this)
.setMessage("You need to be logged in to reply!")
.setPositiveButton("Login", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
Intent intent = new Intent(TopicActivity.this, LoginActivity.class);
startActivity(intent);
finish();
overridePendingTransition(R.anim.push_right_in, R.anim.push_right_out);
}
})
.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialogInterface, int i) {
}
})
.show();
postsList.add(null);
topicAdapter.prepareForReply(new ReplyTask());
replyFAB.hide();
bottomNavBar.setVisibility(View.GONE);
topicAdapter.notifyItemInserted(postsList.size());
}
}
});
}*/
}
//Sets bottom navigation bar
firstPage = (ImageButton) findViewById(R.id.page_first_button);
@ -488,6 +480,7 @@ public class TopicActivity extends BaseActivity {
progressBar.setVisibility(ProgressBar.INVISIBLE);
topicAdapter.customNotifyDataSetChanged(new TopicTask());
if (replyPageUrl == null) replyFAB.setVisibility(View.GONE);
if (replyFAB.getVisibility() != View.GONE) replyFAB.setEnabled(true);
//Set current page
@ -528,6 +521,12 @@ public class TopicActivity extends BaseActivity {
private void parse(Document topic) {
ParseHelpers.Language language = ParseHelpers.Language.getLanguage(topic);
//Find reply page url
{
Element replyButton = topic.select("a:has(img[alt=Reply])").first();
if (replyButton != null) replyPageUrl = replyButton.attr("href");
}
//Finds topic title if missing
if (topicTitle == null || Objects.equals(topicTitle, "")) {
parsedTitle = topic.select("td[id=top_subject]").first().text();
@ -555,7 +554,84 @@ public class TopicActivity extends BaseActivity {
postsList.clear();
postsList.addAll(TopicParser.parseTopic(topic, language));
//postsList = TopicParser.parseTopic(topic, language);
}
}
class ReplyTask extends AsyncTask<String, Void, Boolean> {
@Override
protected void onPreExecute() {
progressBar.setVisibility(ProgressBar.VISIBLE);
paginationEnabled(false);
replyFAB.setEnabled(false);
}
@Override
protected Boolean doInBackground(String... message) {
Document document;
String numReplies, seqnum, sc, subject, topic;
Request request = new Request.Builder()
.url(replyPageUrl + ";wap2")
.build();
try {
Response response = client.newCall(request).execute();
document = Jsoup.parse(response.body().string());
//https://www.thmmy.gr/smf/index.php?action=post;topic=67565.15;num_replies=27
numReplies = replyPageUrl.substring(replyPageUrl.indexOf("num_replies=") + 12);
seqnum = document.select("input[name=seqnum]").first().attr("value");
sc = document.select("input[name=sc]").first().attr("value");
subject = document.select("input[name=subject]").first().attr("value");
topic = document.select("input[name=topic]").first().attr("value");
Log.d(TAG, "numReplies " + numReplies + "\n"
+ "seqnum " + seqnum + "\n"
+ "sc " + sc + "\n"
+ "subject " + subject + "\n"
+ "topic " + topic + "\n");
} catch (IOException e) {
Report.i(TAG, "Post failed.", e);
return false;
} catch (Selector.SelectorParseException e) {
Report.e(TAG, "Post failed.", e);
return false;
}
Log.d(TAG, message[0]);
RequestBody postBody = null;
try {
postBody = new MultipartBody.Builder()
.setType(MultipartBody.FORM)
.addFormDataPart("message", URLEncoder.encode(message[0], "UTF-8"))
.addFormDataPart("num_replies", numReplies)
.addFormDataPart("seqnum", seqnum)
.addFormDataPart("sc", sc)
.addFormDataPart("subject", subject)
.addFormDataPart("topic", topic)
.addFormDataPart("goback", "1")
.build();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
Request post = new Request.Builder()
.url("https://www.thmmy.gr/smf/index.php?action=post2")
.header("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/56.0.2924.87 Safari/537.36")
.post(postBody)
.build();
try {
client.newCall(post).execute();
return true;
} catch (IOException e) {
Report.i(TAG, "Post failed.", e);
return false;
}
}
@Override
protected void onPostExecute(Boolean result) {
progressBar.setVisibility(ProgressBar.GONE);
}
}
}

186
app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java

@ -11,9 +11,11 @@ import android.os.Build;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.widget.AppCompatImageButton;
import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
@ -21,6 +23,7 @@ import android.view.ViewGroup;
import android.webkit.WebResourceRequest;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
@ -31,6 +34,7 @@ import android.widget.TextView;
import com.squareup.picasso.Picasso;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;
@ -50,12 +54,11 @@ import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_USERNAME;
import static gr.thmmy.mthmmy.activities.topic.TopicActivity.toQuoteList;
/**
* Custom {@link android.support.v7.widget.RecyclerView.Adapter} used for topics.
*/
class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
class TopicAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
/**
* Debug Tag for logging debug output to LogCat
*/
@ -65,6 +68,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
*/
private static int THUMBNAIL_SIZE;
private final Context context;
private ArrayList<Integer> toQuoteList = new ArrayList<>();
private final List<Post> postsList;
/**
* Used to hold the state of visibility and other attributes for views that are animated or
@ -87,69 +91,16 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
*/
private static final int isQuoteButtonChecked = 2;
private TopicActivity.TopicTask topicTask;
/**
* Custom {@link RecyclerView.ViewHolder} implementation
*/
class MyViewHolder extends RecyclerView.ViewHolder {
final CardView cardView;
final LinearLayout cardChildLinear;
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 View bodyFooterDivider;
final LinearLayout postFooter;
final TextView specialRank, rank, gender, numberOfPosts, personalText, stars;
MyViewHolder(View view) {
super(view);
//Initializes layout's graphic elements
//Standard stuff
cardView = (CardView) view.findViewById(R.id.card_view);
cardChildLinear = (LinearLayout) view.findViewById(R.id.card_child_linear);
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);
post.setBackgroundColor(Color.argb(1, 255, 255, 255));
quoteToggle = (ImageButton) view.findViewById(R.id.toggle_quote_button);
bodyFooterDivider = view.findViewById(R.id.body_footer_divider);
postFooter = (LinearLayout) view.findViewById(R.id.post_footer);
//User's extra info
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 = (TextView) view.findViewById(R.id.stars);
}
/**
* Cancels all pending Picasso requests
*/
void cleanup() {
Picasso.with(context).cancelRequest(thumbnail);
thumbnail.setImageDrawable(null);
}
}
private TopicActivity.ReplyTask replyTask;
private final int VIEW_TYPE_POST = 0;
private final int VIEW_TYPE_QUICK_REPLY = 1;
private boolean firstTime = false;
/**
* @param context the context of the {@link RecyclerView}
* @param postsList List of {@link Post} objects to use
*/
TopicAdapter(Context context, List<Post> postsList,
TopicActivity.TopicTask topicTask) {
TopicAdapter(Context context, List<Post> postsList, TopicActivity.TopicTask topicTask) {
this.context = context;
this.postsList = postsList;
@ -161,22 +112,36 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
this.topicTask = topicTask;
}
void prepareForReply(TopicActivity.ReplyTask replyTask) {
this.replyTask = replyTask;
firstTime = true;
}
@Override
public void onViewRecycled(final MyViewHolder holder) {
holder.cleanup();
public int getItemViewType(int position) {
return postsList.get(position) == null ? VIEW_TYPE_QUICK_REPLY : VIEW_TYPE_POST;
}
@Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
if (viewType == VIEW_TYPE_POST) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.activity_topic_post_row, parent, false);
return new MyViewHolder(itemView);
return new PostViewHolder(itemView);
} else if (viewType == VIEW_TYPE_QUICK_REPLY) {
View view = LayoutInflater.from(parent.getContext()).
inflate(R.layout.activity_topic_quick_reply_row, parent, false);
return new QuickReplyViewHolder(view);
}
return null;
}
@SuppressLint("SetJavaScriptEnabled")
@Override
public void onBindViewHolder(final MyViewHolder holder, final int position) {
public void onBindViewHolder(final RecyclerView.ViewHolder currentHolder, final int position) {
if (currentHolder instanceof PostViewHolder) {
final Post currentPost = postsList.get(position);
final PostViewHolder holder = (PostViewHolder) currentHolder;
//Post's WebView parameters
holder.post.setClickable(true);
@ -435,6 +400,34 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
});
//Also when post is clicked
holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView));
} else if (currentHolder instanceof QuickReplyViewHolder) {
final QuickReplyViewHolder holder = (QuickReplyViewHolder) currentHolder;
if (firstTime) {
//Build quotes
String quotes = "";
for (int quotePosition : toQuoteList) {
//Date postDate = new Date();
Log.d(TAG, postsList.get(quotePosition).getPostDate());
if (postsList.get(quotePosition).getPostIndex() != 0) {
quotes += "[quote author=" + postsList.get(quotePosition).getAuthor()
+ " link=topic=68525.msg" + postsList.get(quotePosition).getPostIndex()
+ "#msg" + postsList.get(quotePosition).getPostIndex()
+ " date=" + "1000"
+ "\n" + postsList.get(quotePosition).getContent()
+ "\n" + "[/quote]" + "\n";
}
}
holder.quickReply.setText(quotes);
}
holder.submitButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
if (holder.quickReply.getText().toString().isEmpty()) return;
holder.submitButton.setEnabled(false);
replyTask.execute(holder.quickReply.getText().toString());
}
});
}
}
void customNotifyDataSetChanged(TopicActivity.TopicTask topicTask) {
@ -452,6 +445,68 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
return postsList.size();
}
/**
* Custom {@link RecyclerView.ViewHolder} implementation
*/
private class PostViewHolder extends RecyclerView.ViewHolder {
final CardView cardView;
final LinearLayout cardChildLinear;
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 View bodyFooterDivider;
final LinearLayout postFooter;
final TextView specialRank, rank, gender, numberOfPosts, personalText, stars;
PostViewHolder(View view) {
super(view);
//Initializes layout's graphic elements
//Standard stuff
cardView = (CardView) view.findViewById(R.id.card_view);
cardChildLinear = (LinearLayout) view.findViewById(R.id.card_child_linear);
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);
post.setBackgroundColor(Color.argb(1, 255, 255, 255));
quoteToggle = (ImageButton) view.findViewById(R.id.toggle_quote_button);
bodyFooterDivider = view.findViewById(R.id.body_footer_divider);
postFooter = (LinearLayout) view.findViewById(R.id.post_footer);
//User's extra info
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 = (TextView) view.findViewById(R.id.stars);
}
}
/**
* Custom {@link RecyclerView.ViewHolder} implementation
*/
private static class QuickReplyViewHolder extends RecyclerView.ViewHolder {
final EditText quickReply;
final AppCompatImageButton submitButton;
QuickReplyViewHolder(View quickReply) {
super(quickReply);
this.quickReply = (EditText) quickReply.findViewById(R.id.quick_reply_text);
submitButton = (AppCompatImageButton) quickReply.findViewById(R.id.quick_reply_submit);
}
}
/**
* This class is a gesture detector for WebViews. It handles post's clicks, long clicks and
* touch and drag.
@ -592,6 +647,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
//Method always returns true as no url should be loaded in the WebViews
return true;
}
}
/**

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

@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"

53
app/src/main/res/layout/activity_topic_quick_reply_row.xml

@ -0,0 +1,53 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingEnd="4dp"
android:paddingStart="4dp">
<android.support.v7.widget.CardView
xmlns:card_view="http://schemas.android.com/apk/res-auto"
android:id="@+id/card_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_gravity="center"
android:foreground="?android:attr/selectableItemBackground"
card_view:cardBackgroundColor="@color/card_background"
card_view:cardCornerRadius="5dp"
card_view:cardElevation="2dp"
card_view:cardPreventCornerOverlap="false"
card_view:cardUseCompatPadding="true">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<android.support.design.widget.TextInputLayout
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_weight="1"
android:orientation="vertical">
<EditText
android:id="@+id/quick_reply_text"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/quick_reply"
android:inputType="textMultiLine"/>
</android.support.design.widget.TextInputLayout>
<android.support.v7.widget.AppCompatImageButton
android:id="@+id/quick_reply_submit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom"
android:layout_marginBottom="5dp"
android:layout_marginEnd="5dp"
android:background="@color/card_background"
android:contentDescription="@string/quick_reply_submit"
android:src="@drawable/ic_send"/>
</LinearLayout>
</android.support.v7.widget.CardView>
</FrameLayout>

2
app/src/main/res/values/strings.xml

@ -44,6 +44,8 @@
<string name="button_page">Page</string>
<string name="button_next">next</string>
<string name="button_last">last</string>
<string name="quick_reply">Quick reply&#8230;</string>
<string name="quick_reply_submit">Submit</string>
<!--Profile Activity-->
<string name="username">Username</string>

Loading…
Cancel
Save