@ -10,10 +10,15 @@ import android.net.Uri;
import android.os.Build ;
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.annotation.Nullable ;
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.Editable ;
import android.text.TextUtils ;
import android.text.TextUtils ;
import android.text.TextWatcher ;
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 +26,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 ;
@ -30,8 +36,14 @@ import android.widget.TextView;
import com.squareup.picasso.Picasso ;
import com.squareup.picasso.Picasso ;
import java.text.DateFormat ;
import java.text.ParseException ;
import java.text.SimpleDateFormat ;
import java.util.ArrayList ;
import java.util.ArrayList ;
import java.util.Calendar ;
import java.util.Date ;
import java.util.List ;
import java.util.List ;
import java.util.Locale ;
import java.util.Objects ;
import java.util.Objects ;
import gr.thmmy.mthmmy.R ;
import gr.thmmy.mthmmy.R ;
@ -42,7 +54,8 @@ import gr.thmmy.mthmmy.model.Post;
import gr.thmmy.mthmmy.model.ThmmyFile ;
import gr.thmmy.mthmmy.model.ThmmyFile ;
import gr.thmmy.mthmmy.model.ThmmyPage ;
import gr.thmmy.mthmmy.model.ThmmyPage ;
import gr.thmmy.mthmmy.utils.CircleTransform ;
import gr.thmmy.mthmmy.utils.CircleTransform ;
import mthmmy.utils.Report ;
import timber.log.Timber ;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK ;
import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK ;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE ;
import static gr.thmmy.mthmmy.activities.board.BoardActivity.BUNDLE_BOARD_TITLE ;
@ -50,21 +63,20 @@ 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 ;
import static gr.thmmy.mthmmy.activities.topic.Posting.htmlToBBcode ;
import static gr.thmmy.mthmmy.base.BaseActivity.getSessionManager ;
/ * *
/ * *
* 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
* /
private static final String TAG = "TopicAdapter" ;
/ * *
/ * *
* Int that holds thumbnail ' s size defined in R . dimen
* Int that holds thumbnail ' s size defined in R . dimen
* /
* /
private static int THUMBNAIL_SIZE ;
private static int THUMBNAIL_SIZE ;
private final Context context ;
private final Context context ;
private String topicTitle ;
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 +99,20 @@ 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 ;
private final int VIEW_TYPE_QUICK_REPLY = 1 ;
/ * *
private String [ ] replyDataHolder = new String [ 2 ] ;
* Custom { @link RecyclerView . ViewHolder } implementation
private int replySubject = 0 , replyText = 1 ;
* /
private String loadedPageUrl = "" ;
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 ) {
, String topicTitle , String loadedPageUrl ) {
this . context = context ;
this . context = context ;
this . postsList = postsList ;
this . postsList = postsList ;
@ -159,24 +122,55 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
viewProperties . add ( new boolean [ 3 ] ) ;
viewProperties . add ( new boolean [ 3 ] ) ;
}
}
this . topicTask = topicTask ;
this . topicTask = topicTask ;
this . topicTitle = topicTitle ;
this . loadedPageUrl = loadedPageUrl ;
}
void prepareForReply ( TopicActivity . ReplyTask replyTask ) {
this . replyTask = replyTask ;
}
void setTopicInfo ( String topicTitle , String loadedPageUrl ) {
this . topicTitle = topicTitle ;
this . loadedPageUrl = loadedPageUrl ;
}
}
@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 ) {
if ( viewType = = VIEW_TYPE_POST ) {
View itemView = LayoutInflater . from ( parent . getContext ( ) )
View itemView = LayoutInflater . from ( parent . getContext ( ) )
. inflate ( R . layout . activity_topic_post_row , parent , false ) ;
. 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 ( ) ) .
@SuppressLint ( "SetJavaScriptEnabled" )
inflate ( R . layout . activity_topic_quick_reply_row , parent , false ) ;
view . findViewById ( R . id . quick_reply_submit ) . setEnabled ( true ) ;
//Default post subject
replyDataHolder [ replySubject ] = "Re: " + topicTitle ;
//Build quotes
String quotes = "" ;
for ( int quotePosition : toQuoteList ) {
quotes + = buildQuote ( quotePosition ) ;
}
if ( ! Objects . equals ( quotes , "" ) )
replyDataHolder [ replyText ] = htmlToBBcode ( quotes ) ;
return new QuickReplyViewHolder ( view , new CustomEditTextListener ( replySubject ) ,
new CustomEditTextListener ( replyText ) ) ;
}
return null ;
}
@SuppressLint ( { "SetJavaScriptEnabled" , "SetTextI18n" } )
@Override
@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 Post currentPost = postsList . get ( position ) ;
final PostViewHolder holder = ( PostViewHolder ) currentHolder ;
//Post's WebView parameters
//Post's WebView parameters
holder . post . setClickable ( true ) ;
holder . post . setClickable ( true ) ;
@ -211,15 +205,18 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
holder . postNum . setText ( "" ) ;
holder . postNum . setText ( "" ) ;
holder . subject . setText ( currentPost . getSubject ( ) ) ;
holder . subject . setText ( currentPost . getSubject ( ) ) ;
holder . post . loadDataWithBaseURL ( "file:///android_asset/" , currentPost . getContent ( ) , "text/html" , "UTF-8" , null ) ;
holder . post . loadDataWithBaseURL ( "file:///android_asset/" , currentPost . getContent ( ) , "text/html" , "UTF-8" , null ) ;
if ( currentPost . getAttachedFiles ( ) ! = null & & currentPost . getAttachedFiles ( ) . size ( ) ! = 0 ) {
if ( ( currentPost . getAttachedFiles ( ) ! = null & & currentPost . getAttachedFiles ( ) . size ( ) ! = 0 )
| | ( currentPost . getLastEdit ( ) ! = null ) ) {
holder . bodyFooterDivider . setVisibility ( View . VISIBLE ) ;
holder . bodyFooterDivider . setVisibility ( View . VISIBLE ) ;
holder . postFooter . removeAllViews ( ) ;
if ( currentPost . getAttachedFiles ( ) ! = null & & currentPost . getAttachedFiles ( ) . size ( ) ! = 0 ) {
int filesTextColor ;
int filesTextColor ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . M ) {
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . M ) {
filesTextColor = context . getResources ( ) . getColor ( R . color . accent , null ) ;
filesTextColor = context . getResources ( ) . getColor ( R . color . accent , null ) ;
} else //noinspection deprecation
} else //noinspection deprecation
filesTextColor = context . getResources ( ) . getColor ( R . color . accent ) ;
filesTextColor = context . getResources ( ) . getColor ( R . color . accent ) ;
holder . postFooter . removeAllViews ( ) ;
for ( final ThmmyFile attachedFile : currentPost . getAttachedFiles ( ) ) {
for ( final ThmmyFile attachedFile : currentPost . getAttachedFiles ( ) ) {
final TextView attached = new TextView ( context ) ;
final TextView attached = new TextView ( context ) ;
attached . setTextSize ( 10f ) ;
attached . setTextSize ( 10f ) ;
@ -240,6 +237,21 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
holder . postFooter . addView ( attached ) ;
holder . postFooter . addView ( attached ) ;
}
}
}
if ( currentPost . getLastEdit ( ) ! = null & & currentPost . getLastEdit ( ) . length ( ) > 0 ) {
int lastEditTextColor ;
if ( Build . VERSION . SDK_INT > = Build . VERSION_CODES . M ) {
lastEditTextColor = context . getResources ( ) . getColor ( R . color . white , null ) ;
} else //noinspection deprecation
lastEditTextColor = context . getResources ( ) . getColor ( R . color . white ) ;
final TextView lastEdit = new TextView ( context ) ;
lastEdit . setTextSize ( 12f ) ;
lastEdit . setText ( currentPost . getLastEdit ( ) ) ;
lastEdit . setTextColor ( lastEditTextColor ) ;
lastEdit . setPadding ( 0 , 3 , 0 , 3 ) ;
holder . postFooter . addView ( lastEdit ) ;
}
} else {
} else {
holder . bodyFooterDivider . setVisibility ( View . GONE ) ;
holder . bodyFooterDivider . setVisibility ( View . GONE ) ;
holder . postFooter . removeAllViews ( ) ;
holder . postFooter . removeAllViews ( ) ;
@ -325,11 +337,10 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
}
}
if ( ! currentPost . isDeleted ( ) ) {
if ( ! currentPost . isDeleted ( ) ) {
//Sets graphics behavior
//Sets graphics behavior
holder . header . setOnClickListener ( new View . OnClickListener ( ) {
holder . thumbnail . setOnClickListener ( new View . OnClickListener ( ) {
@Override
@Override
public void onClick ( View v ) {
public void onClick ( View view ) {
//Clicking an expanded header starts profile activity
//Clicking the thumbnail opens user's profile
if ( viewProperties . get ( holder . getAdapterPosition ( ) ) [ isUserExtraInfoVisibile ] ) {
Intent intent = new Intent ( context , ProfileActivity . class ) ;
Intent intent = new Intent ( context , ProfileActivity . class ) ;
Bundle extras = new Bundle ( ) ;
Bundle extras = new Bundle ( ) ;
extras . putString ( BUNDLE_PROFILE_URL , currentPost . getProfileURL ( ) ) ;
extras . putString ( BUNDLE_PROFILE_URL , currentPost . getProfileURL ( ) ) ;
@ -342,7 +353,11 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
intent . setFlags ( FLAG_ACTIVITY_NEW_TASK ) ;
intent . setFlags ( FLAG_ACTIVITY_NEW_TASK ) ;
context . startActivity ( intent ) ;
context . startActivity ( intent ) ;
}
}
} ) ;
holder . header . setOnClickListener ( new View . OnClickListener ( ) {
@Override
public void onClick ( View v ) {
//Clicking the header makes it expand/collapse
boolean [ ] tmp = viewProperties . get ( holder . getAdapterPosition ( ) ) ;
boolean [ ] tmp = viewProperties . get ( holder . getAdapterPosition ( ) ) ;
tmp [ isUserExtraInfoVisibile ] = ! tmp [ isUserExtraInfoVisibile ] ;
tmp [ isUserExtraInfoVisibile ] = ! tmp [ isUserExtraInfoVisibile ] ;
viewProperties . set ( holder . getAdapterPosition ( ) , tmp ) ;
viewProperties . set ( holder . getAdapterPosition ( ) , tmp ) ;
@ -354,7 +369,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
@Override
@Override
public void onClick ( View v ) {
public void onClick ( View v ) {
boolean [ ] tmp = viewProperties . get ( holder . getAdapterPosition ( ) ) ;
boolean [ ] tmp = viewProperties . get ( holder . getAdapterPosition ( ) ) ;
tmp [ 1 ] = false ;
tmp [ isUserExtraInfoVisibile ] = false ;
viewProperties . set ( holder . getAdapterPosition ( ) , tmp ) ;
viewProperties . set ( holder . getAdapterPosition ( ) , tmp ) ;
TopicAnimations . animateUserExtraInfoVisibility ( v ) ;
TopicAnimations . animateUserExtraInfoVisibility ( v ) ;
@ -390,7 +405,7 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
holder . subject . setEllipsize ( TextUtils . TruncateAt . END ) ;
holder . subject . setEllipsize ( TextUtils . TruncateAt . END ) ;
}
}
//noinspection PointlessBooleanExpression,ConstantConditions
//noinspection PointlessBooleanExpression,ConstantConditions
if ( ! BaseActivity . getSessionManager ( ) . isLoggedIn ( ) | | true ) //Hide it until reply is implemented
if ( ! BaseActivity . getSessionManager ( ) . isLoggedIn ( ) )
holder . quoteToggle . setVisibility ( View . GONE ) ;
holder . quoteToggle . setVisibility ( View . GONE ) ;
else {
else {
if ( viewProperties . get ( position ) [ isQuoteButtonChecked ] )
if ( viewProperties . get ( position ) [ isQuoteButtonChecked ] )
@ -403,14 +418,14 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
public void onClick ( View view ) {
public void onClick ( View view ) {
boolean [ ] tmp = viewProperties . get ( holder . getAdapterPosition ( ) ) ;
boolean [ ] tmp = viewProperties . get ( holder . getAdapterPosition ( ) ) ;
if ( tmp [ isQuoteButtonChecked ] ) {
if ( tmp [ isQuoteButtonChecked ] ) {
if ( toQuoteList . contains ( currentPost . getPostNumber ( ) ) ) {
if ( toQuoteList . contains ( postsList . indexOf ( currentPost ) ) ) {
toQuoteList . remove ( toQuoteList . indexOf ( currentPost . getPostNumber ( ) ) ) ;
toQuoteList . remove ( toQuoteList . indexOf ( postsList . indexOf ( currentPost ) ) ) ;
} else
} else
Report . i ( TAG , "An error occurred while trying to exclude post from" +
Timber . i ( "An error occurred while trying to exclude post from" +
"toQuoteList, post wasn't there!" ) ;
"toQuoteList, post wasn't there!" ) ;
holder . quoteToggle . setImageResource ( R . drawable . ic_format_quote_unchecked ) ;
holder . quoteToggle . setImageResource ( R . drawable . ic_format_quote_unchecked ) ;
} else {
} else {
toQuoteList . add ( currentPost . getPostNumber ( ) ) ;
toQuoteList . add ( postsList . indexOf ( currentPost ) ) ;
holder . quoteToggle . setImageResource ( R . drawable . ic_format_quote_checked ) ;
holder . quoteToggle . setImageResource ( R . drawable . ic_format_quote_checked ) ;
}
}
tmp [ isQuoteButtonChecked ] = ! tmp [ isQuoteButtonChecked ] ;
tmp [ isQuoteButtonChecked ] = ! tmp [ isQuoteButtonChecked ] ;
@ -435,6 +450,41 @@ class TopicAdapter extends RecyclerView.Adapter<TopicAdapter.MyViewHolder> {
} ) ;
} ) ;
//Also when post is clicked
//Also when post is clicked
holder . post . setOnTouchListener ( new CustomTouchListener ( holder . post , holder . cardView ) ) ;
holder . post . setOnTouchListener ( new CustomTouchListener ( holder . post , holder . cardView ) ) ;
} else if ( currentHolder instanceof QuickReplyViewHolder ) {
final QuickReplyViewHolder holder = ( QuickReplyViewHolder ) currentHolder ;
//noinspection ConstantConditions
Picasso . with ( context )
. load ( getSessionManager ( ) . getAvatarLink ( ) )
. 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 ) ;
holder . username . setText ( getSessionManager ( ) . getUsername ( ) ) ;
holder . quickReplySubject . setText ( replyDataHolder [ replySubject ] ) ;
if ( replyDataHolder [ replyText ] ! = null & & ! Objects . equals ( replyDataHolder [ replyText ] , "" ) )
holder . quickReply . setText ( replyDataHolder [ replyText ] ) ;
holder . submitButton . setOnClickListener ( new View . OnClickListener ( ) {
@Override
public void onClick ( View view ) {
if ( holder . quickReplySubject . getText ( ) . toString ( ) . isEmpty ( ) ) return ;
if ( holder . quickReply . getText ( ) . toString ( ) . isEmpty ( ) ) return ;
holder . submitButton . setEnabled ( false ) ;
replyTask . execute ( holder . quickReplySubject . getText ( ) . toString ( ) ,
holder . quickReply . getText ( ) . toString ( ) ) ;
holder . quickReplySubject . getText ( ) . clear ( ) ;
holder . quickReplySubject . setText ( "Re: " + topicTitle ) ;
holder . quickReply . getText ( ) . clear ( ) ;
}
} ) ;
}
}
}
void customNotifyDataSetChanged ( TopicActivity . TopicTask topicTask ) {
void customNotifyDataSetChanged ( TopicActivity . TopicTask topicTask ) {
@ -452,6 +502,79 @@ 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 ImageView thumbnail ;
final TextView username ;
final EditText quickReply , quickReplySubject ;
final AppCompatImageButton submitButton ;
final CustomEditTextListener replySubject , replyText ;
QuickReplyViewHolder ( View quickReply , CustomEditTextListener replySubject
, CustomEditTextListener replyText ) {
super ( quickReply ) ;
thumbnail = ( ImageView ) quickReply . findViewById ( R . id . thumbnail ) ;
username = ( TextView ) quickReply . findViewById ( R . id . username ) ;
this . quickReply = ( EditText ) quickReply . findViewById ( R . id . quick_reply_text ) ;
this . replyText = replyText ;
this . quickReply . addTextChangedListener ( replyText ) ;
quickReplySubject = ( EditText ) quickReply . findViewById ( R . id . quick_reply_subject ) ;
this . replySubject = replySubject ;
quickReplySubject . addTextChangedListener ( replySubject ) ;
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 +715,84 @@ 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 ;
}
}
}
private class CustomEditTextListener implements TextWatcher {
private final int positionInDataHolder ;
CustomEditTextListener ( int positionInDataHolder ) {
this . positionInDataHolder = positionInDataHolder ;
}
@Override
public void beforeTextChanged ( CharSequence charSequence , int i , int i2 , int i3 ) {
}
@Override
public void onTextChanged ( CharSequence charSequence , int i , int i2 , int i3 ) {
replyDataHolder [ positionInDataHolder ] = charSequence . toString ( ) ;
}
@Override
public void afterTextChanged ( Editable editable ) {
}
}
@Nullable
private String buildQuote ( int quotePosition ) {
Date postDate = null ;
{
String date = postsList . get ( quotePosition ) . getPostDate ( ) ;
if ( date ! = null ) {
DateFormat format = new SimpleDateFormat ( "MMMM d, yyyy, h:m:s a" , Locale . ENGLISH ) ;
date = date . replace ( "Ιανουαρίου" , "January" ) ;
date = date . replace ( "Φεβρουαρίου" , "February" ) ;
date = date . replace ( "Μαρτίου" , "March" ) ;
date = date . replace ( "Απριλίου" , "April" ) ;
date = date . replace ( "Μαΐου" , "May" ) ;
date = date . replace ( "Ιουνίου" , "June" ) ;
date = date . replace ( "Ιουλίου" , "July" ) ;
date = date . replace ( "Αυγούστου" , "August" ) ;
date = date . replace ( "Σεπτεμβρίου" , "September" ) ;
date = date . replace ( "Οκτωβρίου" , "October" ) ;
date = date . replace ( "Νοεμβρίου" , "November" ) ;
date = date . replace ( "Δεκεμβρίου" , "December" ) ;
if ( date . contains ( "Today" ) ) {
date = date . replace ( "Today at" ,
Calendar . getInstance ( ) . getDisplayName ( Calendar . MONTH ,
Calendar . LONG , Locale . ENGLISH )
+ " " + Calendar . getInstance ( ) . get ( Calendar . DAY_OF_MONTH )
+ ", " + Calendar . getInstance ( ) . get ( Calendar . YEAR ) + "," ) ;
} else if ( date . contains ( "Σήμερα" ) ) {
date = date . replace ( "Σήμερα στις" ,
Calendar . getInstance ( ) . getDisplayName ( Calendar . MONTH ,
Calendar . LONG , Locale . ENGLISH )
+ " " + Calendar . getInstance ( ) . get ( Calendar . DAY_OF_MONTH )
+ ", " + Calendar . getInstance ( ) . get ( Calendar . YEAR ) + "," ) ;
if ( date . contains ( "πμ" ) ) date = date . replace ( "πμ" , "am" ) ;
if ( date . contains ( "μμ" ) ) date = date . replace ( "μμ" , "pm" ) ;
}
try {
postDate = format . parse ( date ) ;
} catch ( ParseException e ) {
e . printStackTrace ( ) ;
}
}
}
if ( postsList . get ( quotePosition ) . getPostIndex ( ) ! = 0 ) {
if ( postDate ! = null ) {
return "[quote author=" + postsList . get ( quotePosition ) . getAuthor ( )
+ " link=topic=" + ThmmyPage . getTopicId ( loadedPageUrl ) + ".msg"
+ postsList . get ( quotePosition ) . getPostIndex ( )
+ "#msg" + postsList . get ( quotePosition ) . getPostIndex ( )
+ " date=" + postDate . getTime ( ) / 1000 + "]"
+ "\n" + postsList . get ( quotePosition ) . getContent ( )
+ "\n" + "[/quote]" + "\n\n" ;
}
}
return null ;
}
}
/ * *
/ * *