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.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);
}
}
}

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.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,280 +112,322 @@ 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) {
View itemView = LayoutInflater.from(parent.getContext())
.inflate(R.layout.activity_topic_post_row, parent, false);
return new MyViewHolder(itemView);
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 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) {
final Post currentPost = postsList.get(position);
//Post's WebView parameters
holder.post.setClickable(true);
holder.post.setWebViewClient(new LinkLauncher());
//Avoids errors about layout having 0 width/height
holder.thumbnail.setMinimumWidth(1);
holder.thumbnail.setMinimumHeight(1);
//Sets 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);
//Sets username,submit date, index number, subject, post's and attached files texts
holder.username.setText(currentPost.getAuthor());
holder.postDate.setText(currentPost.getPostDate());
if (currentPost.getPostNumber() != 0)
holder.postNum.setText(context.getString(
R.string.user_number_of_posts, currentPost.getPostNumber()));
else
holder.postNum.setText("");
holder.subject.setText(currentPost.getSubject());
holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null);
if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) {
holder.bodyFooterDivider.setVisibility(View.VISIBLE);
int filesTextColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
filesTextColor = context.getResources().getColor(R.color.accent, null);
} else //noinspection deprecation
filesTextColor = context.getResources().getColor(R.color.accent);
holder.postFooter.removeAllViews();
for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) {
final TextView attached = new TextView(context);
attached.setTextSize(10f);
attached.setClickable(true);
attached.setTypeface(Typeface.createFromAsset(context.getAssets()
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);
holder.post.setWebViewClient(new LinkLauncher());
//Avoids errors about layout having 0 width/height
holder.thumbnail.setMinimumWidth(1);
holder.thumbnail.setMinimumHeight(1);
//Sets 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);
//Sets username,submit date, index number, subject, post's and attached files texts
holder.username.setText(currentPost.getAuthor());
holder.postDate.setText(currentPost.getPostDate());
if (currentPost.getPostNumber() != 0)
holder.postNum.setText(context.getString(
R.string.user_number_of_posts, currentPost.getPostNumber()));
else
holder.postNum.setText("");
holder.subject.setText(currentPost.getSubject());
holder.post.loadDataWithBaseURL("file:///android_asset/", currentPost.getContent(), "text/html", "UTF-8", null);
if (currentPost.getAttachedFiles() != null && currentPost.getAttachedFiles().size() != 0) {
holder.bodyFooterDivider.setVisibility(View.VISIBLE);
int filesTextColor;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
filesTextColor = context.getResources().getColor(R.color.accent, null);
} else //noinspection deprecation
filesTextColor = context.getResources().getColor(R.color.accent);
holder.postFooter.removeAllViews();
for (final ThmmyFile attachedFile : currentPost.getAttachedFiles()) {
final TextView attached = new TextView(context);
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"));
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
public void onClick(View view) {
((BaseActivity) context).launchDownloadService(attachedFile);
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];
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) {
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"));
String aStar = context.getResources().getString(R.string.fa_icon_star);
String usersStars = "";
for (int i = 0; i < mNumberOfStars; ++i) {
usersStars += aStar;
//Avoid's view's visibility recycling
if (viewProperties.get(position)[isPostDateAndNumberVisibile]) { //Expanded
holder.postDateAndNumberExp.setVisibility(View.VISIBLE);
holder.postDateAndNumberExp.setAlpha(1.0f);
holder.postDateAndNumberExp.setTranslationY(0);
holder.username.setMaxLines(Integer.MAX_VALUE);
holder.username.setEllipsize(null);
holder.subject.setTextColor(Color.parseColor("#FFFFFF"));
holder.subject.setMaxLines(Integer.MAX_VALUE);
holder.subject.setEllipsize(null);
} else { //Collapsed
holder.postDateAndNumberExp.setVisibility(View.GONE);
holder.postDateAndNumberExp.setAlpha(0.0f);
holder.postDateAndNumberExp.setTranslationY(holder.postDateAndNumberExp.getHeight());
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);
}
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
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);
//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
public void onClick(View view) {
boolean[] tmp = viewProperties.get(holder.getAdapterPosition());
if (tmp[isQuoteButtonChecked]) {
if (toQuoteList.contains(currentPost.getPostNumber())) {
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);
}
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() {
});
}
//Card expand/collapse when card is touched
holder.cardView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
public void onClick(View view) {
//Change post's viewProperties accordingly
boolean[] tmp = viewProperties.get(holder.getAdapterPosition());
tmp[1] = false;
tmp[isPostDateAndNumberVisibile] = !tmp[isPostDateAndNumberVisibile];
viewProperties.set(holder.getAdapterPosition(), tmp);
TopicAnimations.animateUserExtraInfoVisibility(v);
TopicAnimations.animatePostExtraInfoVisibility(holder.postDateAndNumberExp
, holder.username, holder.subject
, Color.parseColor("#FFFFFF")
, Color.parseColor("#757575"));
}
});
} else {
holder.header.setOnClickListener(null);
holder.userExtraInfo.setOnClickListener(null);
}
//Avoid's view's visibility recycling
if (viewProperties.get(position)[isPostDateAndNumberVisibile]) { //Expanded
holder.postDateAndNumberExp.setVisibility(View.VISIBLE);
holder.postDateAndNumberExp.setAlpha(1.0f);
holder.postDateAndNumberExp.setTranslationY(0);
holder.username.setMaxLines(Integer.MAX_VALUE);
holder.username.setEllipsize(null);
holder.subject.setTextColor(Color.parseColor("#FFFFFF"));
holder.subject.setMaxLines(Integer.MAX_VALUE);
holder.subject.setEllipsize(null);
} else { //Collapsed
holder.postDateAndNumberExp.setVisibility(View.GONE);
holder.postDateAndNumberExp.setAlpha(0.0f);
holder.postDateAndNumberExp.setTranslationY(holder.postDateAndNumberExp.getHeight());
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() {
//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) {
boolean[] tmp = viewProperties.get(holder.getAdapterPosition());
if (tmp[isQuoteButtonChecked]) {
if (toQuoteList.contains(currentPost.getPostNumber())) {
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);
if (holder.quickReply.getText().toString().isEmpty()) return;
holder.submitButton.setEnabled(false);
replyTask.execute(holder.quickReply.getText().toString());
}
});
}
//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) {
@ -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;
}
}
/**

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

@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<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"
android:orientation="vertical"
android:paddingEnd="4dp"
android:paddingStart="4dp"
tools:ignore="SmallSp">
<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"
android:orientation="vertical"
android:paddingEnd="4dp"
android:paddingStart="4dp"
tools:ignore="SmallSp">
<FrameLayout
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_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