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. 666
      app/src/main/java/gr/thmmy/mthmmy/activities/topic/TopicAdapter.java
  3. 17
      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.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.LinearLayout;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast; import android.widget.Toast;
import org.jsoup.Jsoup; import org.jsoup.Jsoup;
import org.jsoup.nodes.Document; import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Selector;
import java.io.IOException; import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Objects; import java.util.Objects;
@ -33,7 +38,9 @@ import gr.thmmy.mthmmy.model.ThmmyPage;
import gr.thmmy.mthmmy.utils.ParseHelpers; import gr.thmmy.mthmmy.utils.ParseHelpers;
import me.zhanghai.android.materialprogressbar.MaterialProgressBar; import me.zhanghai.android.materialprogressbar.MaterialProgressBar;
import mthmmy.utils.Report; import mthmmy.utils.Report;
import okhttp3.MultipartBody;
import okhttp3.Request; import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response; import okhttp3.Response;
/** /**
@ -62,10 +69,11 @@ public class TopicActivity extends BaseActivity {
private TopicAdapter topicAdapter; private TopicAdapter topicAdapter;
private ArrayList<Post> postsList; private ArrayList<Post> postsList;
private static final int NO_POST_FOCUS = -1; 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; private static int postFocusPosition = 0;
//Quotes //Reply
public static final ArrayList<Integer> toQuoteList = new ArrayList<>(); private FloatingActionButton replyFAB;
private String replyPageUrl = null;
//Topic's pages //Topic's pages
private int thisPage = 1; private int thisPage = 1;
private int numberOfPages = 1; private int numberOfPages = 1;
@ -85,7 +93,6 @@ public class TopicActivity extends BaseActivity {
private ImageButton nextPage; private ImageButton nextPage;
private ImageButton lastPage; private ImageButton lastPage;
//Other variables //Other variables
private FloatingActionButton replyFAB;
private MaterialProgressBar progressBar; private MaterialProgressBar progressBar;
private static String base_url = ""; private static String base_url = "";
private String topicTitle; private String topicTitle;
@ -132,42 +139,27 @@ public class TopicActivity extends BaseActivity {
recyclerView.setHasFixedSize(true); recyclerView.setHasFixedSize(true);
LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext()); LinearLayoutManager layoutManager = new LinearLayoutManager(getApplicationContext());
recyclerView.setLayoutManager(layoutManager); recyclerView.setLayoutManager(layoutManager);
topicAdapter = new TopicAdapter(this, postsList, topicAdapter = new TopicAdapter(this, postsList, topicTask);
topicTask);
recyclerView.setAdapter(topicAdapter); recyclerView.setAdapter(topicAdapter);
replyFAB = (FloatingActionButton) findViewById(R.id.topic_fab); replyFAB = (FloatingActionButton) findViewById(R.id.topic_fab);
replyFAB.setEnabled(false); replyFAB.setEnabled(false);
replyFAB.hide(); final LinearLayout bottomNavBar = (LinearLayout) findViewById(R.id.bottom_navigation_bar);
/*if (!sessionManager.isLoggedIn()) replyFAB.hide(); if (!sessionManager.isLoggedIn()) replyFAB.hide();
else { else {
replyFAB.setOnClickListener(new View.OnClickListener() { replyFAB.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
if (sessionManager.isLoggedIn()) { if (sessionManager.isLoggedIn()) {
//TODO Reply postsList.add(null);
} else { topicAdapter.prepareForReply(new ReplyTask());
new AlertDialog.Builder(TopicActivity.this) replyFAB.hide();
.setMessage("You need to be logged in to reply!") bottomNavBar.setVisibility(View.GONE);
.setPositiveButton("Login", new DialogInterface.OnClickListener() { topicAdapter.notifyItemInserted(postsList.size());
@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();
} }
} }
}); });
}*/ }
//Sets bottom navigation bar //Sets bottom navigation bar
firstPage = (ImageButton) findViewById(R.id.page_first_button); firstPage = (ImageButton) findViewById(R.id.page_first_button);
@ -488,6 +480,7 @@ public class TopicActivity extends BaseActivity {
progressBar.setVisibility(ProgressBar.INVISIBLE); progressBar.setVisibility(ProgressBar.INVISIBLE);
topicAdapter.customNotifyDataSetChanged(new TopicTask()); topicAdapter.customNotifyDataSetChanged(new TopicTask());
if (replyPageUrl == null) replyFAB.setVisibility(View.GONE);
if (replyFAB.getVisibility() != View.GONE) replyFAB.setEnabled(true); if (replyFAB.getVisibility() != View.GONE) replyFAB.setEnabled(true);
//Set current page //Set current page
@ -528,6 +521,12 @@ public class TopicActivity extends BaseActivity {
private void parse(Document topic) { private void parse(Document topic) {
ParseHelpers.Language language = ParseHelpers.Language.getLanguage(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 //Finds topic title if missing
if (topicTitle == null || Objects.equals(topicTitle, "")) { if (topicTitle == null || Objects.equals(topicTitle, "")) {
parsedTitle = topic.select("td[id=top_subject]").first().text(); parsedTitle = topic.select("td[id=top_subject]").first().text();
@ -555,7 +554,84 @@ public class TopicActivity extends BaseActivity {
postsList.clear(); postsList.clear();
postsList.addAll(TopicParser.parseTopic(topic, language)); 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);
} }
} }
} }

666
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.os.Bundle;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.v4.content.res.ResourcesCompat; import android.support.v4.content.res.ResourcesCompat;
import android.support.v7.widget.AppCompatImageButton;
import android.support.v7.widget.CardView; import android.support.v7.widget.CardView;
import android.support.v7.widget.RecyclerView; import android.support.v7.widget.RecyclerView;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
@ -21,6 +23,7 @@ import android.view.ViewGroup;
import android.webkit.WebResourceRequest; import android.webkit.WebResourceRequest;
import android.webkit.WebView; import android.webkit.WebView;
import android.webkit.WebViewClient; import android.webkit.WebViewClient;
import android.widget.EditText;
import android.widget.FrameLayout; import android.widget.FrameLayout;
import android.widget.ImageButton; import android.widget.ImageButton;
import android.widget.ImageView; import android.widget.ImageView;
@ -31,6 +34,7 @@ import android.widget.TextView;
import com.squareup.picasso.Picasso; import com.squareup.picasso.Picasso;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Objects; 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_THUMBNAIL_URL;
import static gr.thmmy.mthmmy.activities.profile.ProfileActivity.BUNDLE_PROFILE_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.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. * 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 * 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 static int THUMBNAIL_SIZE;
private final Context context; private final Context context;
private ArrayList<Integer> toQuoteList = new ArrayList<>();
private final List<Post> postsList; private final List<Post> postsList;
/** /**
* Used to hold the state of visibility and other attributes for views that are animated or * 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 static final int isQuoteButtonChecked = 2;
private TopicActivity.TopicTask topicTask; private TopicActivity.TopicTask topicTask;
private TopicActivity.ReplyTask replyTask;
/** private final int VIEW_TYPE_POST = 0;
* Custom {@link RecyclerView.ViewHolder} implementation private final int VIEW_TYPE_QUICK_REPLY = 1;
*/ private boolean firstTime = false;
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);
}
}
/** /**
* @param context the context of the {@link RecyclerView} * @param context the context of the {@link RecyclerView}
* @param postsList List of {@link Post} objects to use * @param postsList List of {@link Post} objects to use
*/ */
TopicAdapter(Context context, List<Post> postsList, TopicAdapter(Context context, List<Post> postsList, TopicActivity.TopicTask topicTask) {
TopicActivity.TopicTask topicTask) {
this.context = context; this.context = context;
this.postsList = postsList; this.postsList = postsList;
@ -161,280 +112,322 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
this.topicTask = topicTask; this.topicTask = topicTask;
} }
void prepareForReply(TopicActivity.ReplyTask replyTask) {
this.replyTask = replyTask;
firstTime = true;
}
@Override @Override
public void onViewRecycled(final MyViewHolder holder) { public int getItemViewType(int position) {
holder.cleanup(); return postsList.get(position) == null ? VIEW_TYPE_QUICK_REPLY : VIEW_TYPE_POST;
} }
@Override @Override
public MyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) { public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
View itemView = LayoutInflater.from(parent.getContext()) if (viewType == VIEW_TYPE_POST) {
.inflate(R.layout.activity_topic_post_row, parent, false); View itemView = LayoutInflater.from(parent.getContext())
return new MyViewHolder(itemView); .inflate(R.layout.activity_topic_post_row, parent, false);
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") @SuppressLint("SetJavaScriptEnabled")
@Override @Override
public void onBindViewHolder(final MyViewHolder holder, final int position) { public void onBindViewHolder(final RecyclerView.ViewHolder currentHolder, final int position) {
final Post currentPost = postsList.get(position); if (currentHolder instanceof PostViewHolder) {
final Post currentPost = postsList.get(position);
//Post's WebView parameters final PostViewHolder holder = (PostViewHolder) currentHolder;
holder.post.setClickable(true);
holder.post.setWebViewClient(new LinkLauncher()); //Post's WebView parameters
holder.post.setClickable(true);
//Avoids errors about layout having 0 width/height holder.post.setWebViewClient(new LinkLauncher());
holder.thumbnail.setMinimumWidth(1);
holder.thumbnail.setMinimumHeight(1); //Avoids errors about layout having 0 width/height
//Sets thumbnail size holder.thumbnail.setMinimumWidth(1);
holder.thumbnail.setMaxWidth(THUMBNAIL_SIZE); holder.thumbnail.setMinimumHeight(1);
holder.thumbnail.setMaxHeight(THUMBNAIL_SIZE); //Sets thumbnail size
holder.thumbnail.setMaxWidth(THUMBNAIL_SIZE);
//noinspection ConstantConditions holder.thumbnail.setMaxHeight(THUMBNAIL_SIZE);
Picasso.with(context)
.load(currentPost.getThumbnailUrl()) //noinspection ConstantConditions
.resize(THUMBNAIL_SIZE, THUMBNAIL_SIZE) Picasso.with(context)
.centerCrop() .load(currentPost.getThumbnailUrl())
.error(ResourcesCompat.getDrawable(context.getResources() .resize(THUMBNAIL_SIZE, THUMBNAIL_SIZE)
, R.drawable.ic_default_user_thumbnail, null)) .centerCrop()
.placeholder(ResourcesCompat.getDrawable(context.getResources() .error(ResourcesCompat.getDrawable(context.getResources()
, R.drawable.ic_default_user_thumbnail, null)) , R.drawable.ic_default_user_thumbnail, null))
.transform(new CircleTransform()) .placeholder(ResourcesCompat.getDrawable(context.getResources()
.into(holder.thumbnail); , R.drawable.ic_default_user_thumbnail, null))
.transform(new CircleTransform())
//Sets username,submit date, index number, subject, post's and attached files texts .into(holder.thumbnail);
holder.username.setText(currentPost.getAuthor());
holder.postDate.setText(currentPost.getPostDate()); //Sets username,submit date, index number, subject, post's and attached files texts
if (currentPost.getPostNumber() != 0) holder.username.setText(currentPost.getAuthor());
holder.postNum.setText(context.getString( holder.postDate.setText(currentPost.getPostDate());
R.string.user_number_of_posts, currentPost.getPostNumber())); if (currentPost.getPostNumber() != 0)
else holder.postNum.setText(context.getString(
holder.postNum.setText(""); R.string.user_number_of_posts, currentPost.getPostNumber()));
holder.subject.setText(currentPost.getSubject()); else
holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null); holder.postNum.setText("");
if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) { holder.subject.setText(currentPost.getSubject());
holder.bodyFooterDivider.setVisibility(View.VISIBLE); holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null);
int filesTextColor; if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { holder.bodyFooterDivider.setVisibility(View.VISIBLE);
filesTextColor = context.getResources().getColor(R.color.accent, null); int filesTextColor;
} else //noinspection deprecation if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
filesTextColor = context.getResources().getColor(R.color.accent); filesTextColor = context.getResources().getColor(R.color.accent, null);
} else //noinspection deprecation
holder.postFooter.removeAllViews(); filesTextColor = context.getResources().getColor(R.color.accent);
for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) {
final TextView attached = new TextView(context); holder.postFooter.removeAllViews();
attached.setTextSize(10f); for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) {
attached.setClickable(true); final TextView attached = new TextView(context);
attached.setTypeface(Typeface.createFromAsset(context.getAssets() attached.setTextSize(10f);
attached.setClickable(true);
attached.setTypeface(Typeface.createFromAsset(context.getAssets()
, "fonts/fontawesome-webfont.ttf"));
attached.setText(faIconFromFilename(attachedFile.getFilename()) + " "
+ attachedFile.getFilename() + attachedFile.getFileInfo());
attached.setTextColor(filesTextColor);
attached.setPadding(0, 3, 0, 3);
attached.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
((BaseActivity) context).launchDownloadService(attachedFile);
}
});
holder.postFooter.addView(attached);
}
} else {
holder.bodyFooterDivider.setVisibility(View.GONE);
holder.postFooter.removeAllViews();
}
String mSpecialRank, mRank, mGender, mNumberOfPosts, mPersonalText;
int mNumberOfStars, mUserColor;
if (!currentPost.isDeleted()) { //Sets user's extra info
mSpecialRank = currentPost.getSpecialRank();
mRank = currentPost.getRank();
mGender = currentPost.getGender();
mNumberOfPosts = currentPost.getNumberOfPosts();
mPersonalText = currentPost.getPersonalText();
mNumberOfStars = currentPost.getNumberOfStars();
mUserColor = currentPost.getUserColor();
} else {
mSpecialRank = null;
mRank = null;
mGender = null;
mNumberOfPosts = null;
mPersonalText = null;
mNumberOfStars = 0;
mUserColor = 0;
}
if (!Objects.equals(mSpecialRank, "") && mSpecialRank != null) {
holder.specialRank.setText(mSpecialRank);
holder.specialRank.setVisibility(View.VISIBLE);
} else
holder.specialRank.setVisibility(View.GONE);
if (!Objects.equals(mRank, "") && mRank != null) {
holder.rank.setText(mRank);
holder.rank.setVisibility(View.VISIBLE);
} else
holder.rank.setVisibility(View.GONE);
if (!Objects.equals(mGender, "") && mGender != null) {
holder.gender.setText(mGender);
holder.gender.setVisibility(View.VISIBLE);
} else
holder.gender.setVisibility(View.GONE);
if (!Objects.equals(mNumberOfPosts, "") && mNumberOfPosts != null) {
holder.numberOfPosts.setText(mNumberOfPosts);
holder.numberOfPosts.setVisibility(View.VISIBLE);
} else
holder.numberOfPosts.setVisibility(View.GONE);
if (!Objects.equals(mPersonalText, "") && mPersonalText != null) {
holder.personalText.setText("\"" + mPersonalText + "\"");
holder.personalText.setVisibility(View.VISIBLE);
} else
holder.personalText.setVisibility(View.GONE);
if (mNumberOfStars > 0) {
holder.stars.setTypeface(Typeface.createFromAsset(context.getAssets()
, "fonts/fontawesome-webfont.ttf")); , "fonts/fontawesome-webfont.ttf"));
attached.setText(faIconFromFilename(attachedFile.getFilename()) + " "
+ attachedFile.getFilename() + attachedFile.getFileInfo());
attached.setTextColor(filesTextColor);
attached.setPadding(0, 3, 0, 3);
attached.setOnClickListener(new View.OnClickListener() { String aStar = context.getResources().getString(R.string.fa_icon_star);
String usersStars = "";
for (int i = 0; i < mNumberOfStars; ++i) {
usersStars += aStar;
}
holder.stars.setText(usersStars);
holder.stars.setTextColor(mUserColor);
holder.stars.setVisibility(View.VISIBLE);
} else
holder.stars.setVisibility(View.GONE);
//Special card for special member of the month!
if (mUserColor == TopicParser.USER_COLOR_PINK) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
holder.cardChildLinear.setBackground(context.getResources().
getDrawable(R.drawable.member_of_the_month_card, null));
} else //noinspection deprecation
holder.cardChildLinear.setBackground(context.getResources().
getDrawable(R.drawable.member_of_the_month_card));
} else holder.cardChildLinear.setBackground(null);
//Avoid's view's visibility recycling
if (!currentPost.isDeleted() && viewProperties.get(position)[isUserExtraInfoVisibile]) {
holder.userExtraInfo.setVisibility(View.VISIBLE);
holder.userExtraInfo.setAlpha(1.0f);
} else {
holder.userExtraInfo.setVisibility(View.GONE);
holder.userExtraInfo.setAlpha(0.0f);
}
if (!currentPost.isDeleted()) {
//Sets graphics behavior
holder.header.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View v) {
((BaseActivity) context).launchDownloadService(attachedFile); //Clicking an expanded header starts profile activity
if (viewProperties.get(holder.getAdapterPosition())[isUserExtraInfoVisibile]) {
Intent intent = new Intent(context, ProfileActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_PROFILE_URL, currentPost.getProfileURL());
if (currentPost.getThumbnailUrl() == null)
extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, "");
else
extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, currentPost.getThumbnailUrl());
extras.putString(BUNDLE_PROFILE_USERNAME, currentPost.getAuthor());
intent.putExtras(extras);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
boolean[] tmp = viewProperties.get(holder.getAdapterPosition());
tmp[isUserExtraInfoVisibile] = !tmp[isUserExtraInfoVisibile];
viewProperties.set(holder.getAdapterPosition(), tmp);
TopicAnimations.animateUserExtraInfoVisibility(holder.userExtraInfo);
} }
}); });
//Clicking the expanded part of a header (the extra info) makes it collapse
holder.userExtraInfo.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
boolean[] tmp = viewProperties.get(holder.getAdapterPosition());
tmp[1] = false;
viewProperties.set(holder.getAdapterPosition(), tmp);
holder.postFooter.addView(attached); TopicAnimations.animateUserExtraInfoVisibility(v);
}
});
} else {
holder.header.setOnClickListener(null);
holder.userExtraInfo.setOnClickListener(null);
} }
} else {
holder.bodyFooterDivider.setVisibility(View.GONE);
holder.postFooter.removeAllViews();
}
String mSpecialRank, mRank, mGender, mNumberOfPosts, mPersonalText;
int mNumberOfStars, mUserColor;
if (!currentPost.isDeleted()) { //Sets user's extra info
mSpecialRank = currentPost.getSpecialRank();
mRank = currentPost.getRank();
mGender = currentPost.getGender();
mNumberOfPosts = currentPost.getNumberOfPosts();
mPersonalText = currentPost.getPersonalText();
mNumberOfStars = currentPost.getNumberOfStars();
mUserColor = currentPost.getUserColor();
} else {
mSpecialRank = null;
mRank = null;
mGender = null;
mNumberOfPosts = null;
mPersonalText = null;
mNumberOfStars = 0;
mUserColor = 0;
}
if (!Objects.equals(mSpecialRank, "") && mSpecialRank != null) { //Avoid's view's visibility recycling
holder.specialRank.setText(mSpecialRank); if (viewProperties.get(position)[isPostDateAndNumberVisibile]) { //Expanded
holder.specialRank.setVisibility(View.VISIBLE); holder.postDateAndNumberExp.setVisibility(View.VISIBLE);
} else holder.postDateAndNumberExp.setAlpha(1.0f);
holder.specialRank.setVisibility(View.GONE); holder.postDateAndNumberExp.setTranslationY(0);
if (!Objects.equals(mRank, "") && mRank != null) {
holder.rank.setText(mRank); holder.username.setMaxLines(Integer.MAX_VALUE);
holder.rank.setVisibility(View.VISIBLE); holder.username.setEllipsize(null);
} else
holder.rank.setVisibility(View.GONE); holder.subject.setTextColor(Color.parseColor("#FFFFFF"));
if (!Objects.equals(mGender, "") && mGender != null) { holder.subject.setMaxLines(Integer.MAX_VALUE);
holder.gender.setText(mGender); holder.subject.setEllipsize(null);
holder.gender.setVisibility(View.VISIBLE); } else { //Collapsed
} else holder.postDateAndNumberExp.setVisibility(View.GONE);
holder.gender.setVisibility(View.GONE); holder.postDateAndNumberExp.setAlpha(0.0f);
if (!Objects.equals(mNumberOfPosts, "") && mNumberOfPosts != null) { holder.postDateAndNumberExp.setTranslationY(holder.postDateAndNumberExp.getHeight());
holder.numberOfPosts.setText(mNumberOfPosts);
holder.numberOfPosts.setVisibility(View.VISIBLE); holder.username.setMaxLines(1);
} else holder.username.setEllipsize(TextUtils.TruncateAt.END);
holder.numberOfPosts.setVisibility(View.GONE);
if (!Objects.equals(mPersonalText, "") && mPersonalText != null) { holder.subject.setTextColor(Color.parseColor("#757575"));
holder.personalText.setText("\"" + mPersonalText + "\""); holder.subject.setMaxLines(1);
holder.personalText.setVisibility(View.VISIBLE); holder.subject.setEllipsize(TextUtils.TruncateAt.END);
} else
holder.personalText.setVisibility(View.GONE);
if (mNumberOfStars > 0) {
holder.stars.setTypeface(Typeface.createFromAsset(context.getAssets()
, "fonts/fontawesome-webfont.ttf"));
String aStar = context.getResources().getString(R.string.fa_icon_star);
String usersStars = "";
for (int i = 0; i < mNumberOfStars; ++i) {
usersStars += aStar;
} }
holder.stars.setText(usersStars); //noinspection PointlessBooleanExpression,ConstantConditions
holder.stars.setTextColor(mUserColor); if (!BaseActivity.getSessionManager().isLoggedIn() || true) //Hide it until reply is implemented
holder.stars.setVisibility(View.VISIBLE); holder.quoteToggle.setVisibility(View.GONE);
} else else {
holder.stars.setVisibility(View.GONE); if (viewProperties.get(position)[isQuoteButtonChecked])
//Special card for special member of the month! holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_checked);
if (mUserColor == TopicParser.USER_COLOR_PINK) { else
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked);
holder.cardChildLinear.setBackground(context.getResources(). //Sets graphics behavior
getDrawable(R.drawable.member_of_the_month_card, null)); holder.quoteToggle.setOnClickListener(new View.OnClickListener() {
} else //noinspection deprecation @Override
holder.cardChildLinear.setBackground(context.getResources(). public void onClick(View view) {
getDrawable(R.drawable.member_of_the_month_card)); boolean[] tmp = viewProperties.get(holder.getAdapterPosition());
} else holder.cardChildLinear.setBackground(null); if (tmp[isQuoteButtonChecked]) {
if (toQuoteList.contains(currentPost.getPostNumber())) {
//Avoid's view's visibility recycling toQuoteList.remove(toQuoteList.indexOf(currentPost.getPostNumber()));
if (!currentPost.isDeleted() && viewProperties.get(position)[isUserExtraInfoVisibile]) { } else
holder.userExtraInfo.setVisibility(View.VISIBLE); Report.i(TAG, "An error occurred while trying to exclude post from" +
holder.userExtraInfo.setAlpha(1.0f); "toQuoteList, post wasn't there!");
} else { holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked);
holder.userExtraInfo.setVisibility(View.GONE); } else {
holder.userExtraInfo.setAlpha(0.0f); toQuoteList.add(currentPost.getPostNumber());
} holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_checked);
if (!currentPost.isDeleted()) { }
//Sets graphics behavior tmp[isQuoteButtonChecked] = !tmp[isQuoteButtonChecked];
holder.header.setOnClickListener(new View.OnClickListener() { viewProperties.set(holder.getAdapterPosition(), tmp);
@Override
public void onClick(View v) {
//Clicking an expanded header starts profile activity
if (viewProperties.get(holder.getAdapterPosition())[isUserExtraInfoVisibile]) {
Intent intent = new Intent(context, ProfileActivity.class);
Bundle extras = new Bundle();
extras.putString(BUNDLE_PROFILE_URL, currentPost.getProfileURL());
if (currentPost.getThumbnailUrl() == null)
extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, "");
else
extras.putString(BUNDLE_PROFILE_THUMBNAIL_URL, currentPost.getThumbnailUrl());
extras.putString(BUNDLE_PROFILE_USERNAME, currentPost.getAuthor());
intent.putExtras(extras);
intent.setFlags(FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
} }
});
boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); }
tmp[isUserExtraInfoVisibile] = !tmp[isUserExtraInfoVisibile]; //Card expand/collapse when card is touched
viewProperties.set(holder.getAdapterPosition(), tmp); holder.cardView.setOnClickListener(new View.OnClickListener() {
TopicAnimations.animateUserExtraInfoVisibility(holder.userExtraInfo);
}
});
//Clicking the expanded part of a header (the extra info) makes it collapse
holder.userExtraInfo.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View v) { public void onClick(View view) {
//Change post's viewProperties accordingly
boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); boolean[] tmp = viewProperties.get(holder.getAdapterPosition());
tmp[1] = false; tmp[isPostDateAndNumberVisibile] = !tmp[isPostDateAndNumberVisibile];
viewProperties.set(holder.getAdapterPosition(), tmp); viewProperties.set(holder.getAdapterPosition(), tmp);
TopicAnimations.animateUserExtraInfoVisibility(v); TopicAnimations.animatePostExtraInfoVisibility(holder.postDateAndNumberExp
, holder.username, holder.subject
, Color.parseColor("#FFFFFF")
, Color.parseColor("#757575"));
} }
}); });
} else { //Also when post is clicked
holder.header.setOnClickListener(null); holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView));
holder.userExtraInfo.setOnClickListener(null); } else if (currentHolder instanceof QuickReplyViewHolder) {
} final QuickReplyViewHolder holder = (QuickReplyViewHolder) currentHolder;
if (firstTime) {
//Avoid's view's visibility recycling //Build quotes
if (viewProperties.get(position)[isPostDateAndNumberVisibile]) { //Expanded String quotes = "";
holder.postDateAndNumberExp.setVisibility(View.VISIBLE); for (int quotePosition : toQuoteList) {
holder.postDateAndNumberExp.setAlpha(1.0f); //Date postDate = new Date();
holder.postDateAndNumberExp.setTranslationY(0); Log.d(TAG, postsList.get(quotePosition).getPostDate());
if (postsList.get(quotePosition).getPostIndex() != 0) {
holder.username.setMaxLines(Integer.MAX_VALUE); quotes += "[quote author=" + postsList.get(quotePosition).getAuthor()
holder.username.setEllipsize(null); + " link=topic=68525.msg" + postsList.get(quotePosition).getPostIndex()
+ "#msg" + postsList.get(quotePosition).getPostIndex()
holder.subject.setTextColor(Color.parseColor("#FFFFFF")); + " date=" + "1000"
holder.subject.setMaxLines(Integer.MAX_VALUE); + "\n" + postsList.get(quotePosition).getContent()
holder.subject.setEllipsize(null); + "\n" + "[/quote]" + "\n";
} else { //Collapsed }
holder.postDateAndNumberExp.setVisibility(View.GONE); }
holder.postDateAndNumberExp.setAlpha(0.0f); holder.quickReply.setText(quotes);
holder.postDateAndNumberExp.setTranslationY(holder.postDateAndNumberExp.getHeight()); }
holder.submitButton.setOnClickListener(new View.OnClickListener() {
holder.username.setMaxLines(1);
holder.username.setEllipsize(TextUtils.TruncateAt.END);
holder.subject.setTextColor(Color.parseColor("#757575"));
holder.subject.setMaxLines(1);
holder.subject.setEllipsize(TextUtils.TruncateAt.END);
}
//noinspection PointlessBooleanExpression,ConstantConditions
if (!BaseActivity.getSessionManager().isLoggedIn() || true) //Hide it until reply is implemented
holder.quoteToggle.setVisibility(View.GONE);
else {
if (viewProperties.get(position)[isQuoteButtonChecked])
holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_checked);
else
holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked);
//Sets graphics behavior
holder.quoteToggle.setOnClickListener(new View.OnClickListener() {
@Override @Override
public void onClick(View view) { public void onClick(View view) {
boolean[] tmp = viewProperties.get(holder.getAdapterPosition()); if (holder.quickReply.getText().toString().isEmpty()) return;
if (tmp[isQuoteButtonChecked]) { holder.submitButton.setEnabled(false);
if (toQuoteList.contains(currentPost.getPostNumber())) { replyTask.execute(holder.quickReply.getText().toString());
toQuoteList.remove(toQuoteList.indexOf(currentPost.getPostNumber()));
} else
Report.i(TAG, "An error occurred while trying to exclude post from" +
"toQuoteList, post wasn't there!");
holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_unchecked);
} else {
toQuoteList.add(currentPost.getPostNumber());
holder.quoteToggle.setImageResource(R.drawable.ic_format_quote_checked);
}
tmp[isQuoteButtonChecked] = !tmp[isQuoteButtonChecked];
viewProperties.set(holder.getAdapterPosition(), tmp);
} }
}); });
} }
//Card expand/collapse when card is touched
holder.cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
//Change post's viewProperties accordingly
boolean[] tmp = viewProperties.get(holder.getAdapterPosition());
tmp[isPostDateAndNumberVisibile] = !tmp[isPostDateAndNumberVisibile];
viewProperties.set(holder.getAdapterPosition(), tmp);
TopicAnimations.animatePostExtraInfoVisibility(holder.postDateAndNumberExp
, holder.username, holder.subject
, Color.parseColor("#FFFFFF")
, Color.parseColor("#757575"));
}
});
//Also when post is clicked
holder.post.setOnTouchListener(new CustomTouchListener(holder.post, holder.cardView));
} }
void customNotifyDataSetChanged(TopicActivity.TopicTask topicTask) { void customNotifyDataSetChanged(TopicActivity.TopicTask topicTask) {
@ -452,6 +445,68 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
return postsList.size(); 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 * This class is a gesture detector for WebViews. It handles post's clicks, long clicks and
* touch and drag. * 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 //Method always returns true as no url should be loaded in the WebViews
return true; return true;
} }
} }
/** /**

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

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <LinearLayout
xmlns:tools="http://schemas.android.com/tools" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" xmlns:tools="http://schemas.android.com/tools"
android:layout_height="wrap_content" android:layout_width="match_parent"
android:orientation="vertical" android:layout_height="wrap_content"
android:paddingEnd="4dp" android:orientation="vertical"
android:paddingStart="4dp" android:paddingEnd="4dp"
tools:ignore="SmallSp"> android:paddingStart="4dp"
tools:ignore="SmallSp">
<FrameLayout <FrameLayout
android:id="@+id/post_date_and_number_exp" android:id="@+id/post_date_and_number_exp"

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_page">Page</string>
<string name="button_next">next</string> <string name="button_next">next</string>
<string name="button_last">last</string> <string name="button_last">last</string>
<string name="quick_reply">Quick reply&#8230;</string>
<string name="quick_reply_submit">Submit</string>
<!--Profile Activity--> <!--Profile Activity-->
<string name="username">Username</string> <string name="username">Username</string>

Loading…
Cancel
Save