2016-06-29 15:47:52 +02:00
|
|
|
package org.mariotaku.twidere.view.holder
|
|
|
|
|
|
|
|
import android.support.v4.content.ContextCompat
|
|
|
|
import android.support.v7.widget.RecyclerView
|
|
|
|
import android.support.v7.widget.RecyclerView.ViewHolder
|
|
|
|
import android.text.*
|
|
|
|
import android.text.style.ForegroundColorSpan
|
|
|
|
import android.view.View
|
|
|
|
import android.view.View.OnClickListener
|
|
|
|
import android.view.View.OnLongClickListener
|
|
|
|
import android.widget.ImageView
|
2016-08-21 15:30:07 +02:00
|
|
|
import kotlinx.android.synthetic.main.list_item_status.view.*
|
2017-01-28 08:15:35 +01:00
|
|
|
import org.mariotaku.ktextension.applyFontFamily
|
2016-06-29 15:47:52 +02:00
|
|
|
import org.mariotaku.twidere.Constants
|
|
|
|
import org.mariotaku.twidere.R
|
2017-01-24 12:10:24 +01:00
|
|
|
import org.mariotaku.twidere.TwidereConstants.USER_TYPE_FANFOU_COM
|
2016-06-29 15:47:52 +02:00
|
|
|
import org.mariotaku.twidere.adapter.iface.IStatusesAdapter
|
|
|
|
import org.mariotaku.twidere.constant.SharedPreferenceConstants.VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE
|
|
|
|
import org.mariotaku.twidere.graphic.like.LikeAnimationDrawable
|
|
|
|
import org.mariotaku.twidere.model.ParcelableLocation
|
|
|
|
import org.mariotaku.twidere.model.ParcelableMedia
|
|
|
|
import org.mariotaku.twidere.model.ParcelableStatus
|
|
|
|
import org.mariotaku.twidere.model.UserKey
|
|
|
|
import org.mariotaku.twidere.model.util.ParcelableLocationUtils
|
|
|
|
import org.mariotaku.twidere.model.util.ParcelableStatusUtils
|
|
|
|
import org.mariotaku.twidere.util.*
|
|
|
|
import org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText
|
|
|
|
import org.mariotaku.twidere.util.Utils.getUserTypeIconRes
|
2017-01-07 15:45:33 +01:00
|
|
|
import org.mariotaku.twidere.view.ProfileImageView
|
2016-06-29 15:47:52 +02:00
|
|
|
import org.mariotaku.twidere.view.holder.iface.IStatusViewHolder
|
|
|
|
import java.lang.ref.WeakReference
|
|
|
|
|
|
|
|
/**
|
|
|
|
* IDE gives me warning if I don't change default comment, so I wrote this XD
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* Created by mariotaku on 14/11/19.
|
|
|
|
*/
|
|
|
|
class StatusViewHolder(private val adapter: IStatusesAdapter<*>, itemView: View) : ViewHolder(itemView), Constants, IStatusViewHolder {
|
|
|
|
|
2017-01-07 15:45:33 +01:00
|
|
|
override val profileImageView: ProfileImageView by lazy { itemView.profileImage }
|
2016-06-29 15:47:52 +02:00
|
|
|
override val profileTypeView: ImageView by lazy { itemView.profileType }
|
|
|
|
|
|
|
|
private val itemContent by lazy { itemView.itemContent }
|
|
|
|
private val mediaPreview by lazy { itemView.mediaPreview }
|
|
|
|
private val statusContentUpperSpace by lazy { itemView.statusContentUpperSpace }
|
|
|
|
private val textView by lazy { itemView.text }
|
|
|
|
private val nameView by lazy { itemView.name }
|
|
|
|
private val itemMenu by lazy { itemView.itemMenu }
|
2016-07-03 05:11:56 +02:00
|
|
|
private val statusInfoLabel by lazy { itemView.statusInfoLabel }
|
|
|
|
private val statusInfoIcon by lazy { itemView.statusInfoIcon }
|
2016-06-29 15:47:52 +02:00
|
|
|
private val extraTypeView by lazy { itemView.extraType }
|
2016-07-03 05:11:56 +02:00
|
|
|
private val quotedNameView by lazy { itemView.quotedName }
|
|
|
|
private val timeView by lazy { itemView.time }
|
|
|
|
private val replyCountView by lazy { itemView.replyCount }
|
|
|
|
private val retweetCountView by lazy { itemView.retweetCount }
|
2016-09-01 08:02:17 +02:00
|
|
|
private val quotedView by lazy { itemView.quotedView }
|
2016-07-03 05:11:56 +02:00
|
|
|
private val quotedTextView by lazy { itemView.quotedText }
|
|
|
|
private val actionButtons by lazy { itemView.actionButtons }
|
|
|
|
private val mediaLabel by lazy { itemView.mediaLabel }
|
2016-09-09 05:58:26 +02:00
|
|
|
private val quotedMediaLabel by lazy { itemView.quotedMediaLabel }
|
2016-07-03 05:11:56 +02:00
|
|
|
private val statusContentLowerSpace by lazy { itemView.statusContentLowerSpace }
|
|
|
|
private val quotedMediaPreview by lazy { itemView.quotedMediaPreview }
|
2016-07-05 15:19:51 +02:00
|
|
|
private val favoriteIcon by lazy { itemView.favoriteIcon }
|
|
|
|
private val retweetIcon by lazy { itemView.retweetIcon }
|
|
|
|
private val favoriteCountView by lazy { itemView.favoriteCount }
|
|
|
|
private val mediaLabelTextView by lazy { itemView.mediaLabelText }
|
2016-09-09 05:58:26 +02:00
|
|
|
private val quotedMediaLabelTextView by lazy { itemView.quotedMediaLabelText }
|
2016-07-05 15:19:51 +02:00
|
|
|
private val replyButton by lazy { itemView.reply }
|
|
|
|
private val retweetButton by lazy { itemView.retweet }
|
|
|
|
private val favoriteButton by lazy { itemView.favorite }
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
private val eventListener: EventListener
|
|
|
|
|
|
|
|
private var statusClickListener: IStatusViewHolder.StatusClickListener? = null
|
|
|
|
|
|
|
|
|
|
|
|
init {
|
|
|
|
this.eventListener = EventListener(this)
|
|
|
|
|
|
|
|
if (adapter.mediaPreviewEnabled) {
|
2016-07-06 03:18:12 +02:00
|
|
|
View.inflate(mediaPreview.context, R.layout.layout_card_media_preview,
|
2016-06-29 15:47:52 +02:00
|
|
|
itemView.mediaPreview)
|
2016-07-06 03:18:12 +02:00
|
|
|
View.inflate(quotedMediaPreview.context, R.layout.layout_card_media_preview,
|
2016-06-29 15:47:52 +02:00
|
|
|
itemView.quotedMediaPreview)
|
|
|
|
}
|
2017-01-28 08:32:28 +01:00
|
|
|
|
|
|
|
nameView.applyFontFamily(adapter.lightFont)
|
|
|
|
timeView.applyFontFamily(adapter.lightFont)
|
2017-01-28 08:15:35 +01:00
|
|
|
textView.applyFontFamily(adapter.lightFont)
|
2017-01-28 08:32:28 +01:00
|
|
|
mediaLabelTextView.applyFontFamily(adapter.lightFont)
|
|
|
|
|
|
|
|
quotedNameView.applyFontFamily(adapter.lightFont)
|
2017-01-28 08:15:35 +01:00
|
|
|
quotedTextView.applyFontFamily(adapter.lightFont)
|
2017-01-28 08:32:28 +01:00
|
|
|
quotedMediaLabelTextView.applyFontFamily(adapter.lightFont)
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
2016-07-03 05:11:56 +02:00
|
|
|
|
2016-06-29 15:47:52 +02:00
|
|
|
fun displaySampleStatus() {
|
|
|
|
val profileImageEnabled = adapter.profileImageEnabled
|
|
|
|
profileImageView.visibility = if (profileImageEnabled) View.VISIBLE else View.GONE
|
|
|
|
statusContentUpperSpace.visibility = View.VISIBLE
|
|
|
|
|
2016-12-12 14:03:58 +01:00
|
|
|
profileImageView.setImageResource(R.drawable.ic_profile_image_twidere)
|
2016-06-29 15:47:52 +02:00
|
|
|
nameView.setName(Constants.TWIDERE_PREVIEW_NAME)
|
|
|
|
nameView.setScreenName("@" + Constants.TWIDERE_PREVIEW_SCREEN_NAME)
|
|
|
|
nameView.updateText(adapter.bidiFormatter)
|
|
|
|
if (adapter.linkHighlightingStyle == VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
|
2016-12-08 08:47:17 +01:00
|
|
|
textView.text = toPlainText(Constants.TWIDERE_PREVIEW_TEXT_HTML)
|
|
|
|
} else {
|
2016-06-29 15:47:52 +02:00
|
|
|
val linkify = adapter.twidereLinkify
|
|
|
|
val text = HtmlSpanBuilder.fromHtml(Constants.TWIDERE_PREVIEW_TEXT_HTML)
|
|
|
|
linkify.applyAllLinks(text, null, -1, false, adapter.linkHighlightingStyle, true)
|
|
|
|
textView.text = text
|
|
|
|
}
|
2017-01-19 03:58:52 +01:00
|
|
|
timeView.time = System.currentTimeMillis()
|
2016-06-29 15:47:52 +02:00
|
|
|
val showCardActions = isCardActionsShown
|
|
|
|
if (adapter.mediaPreviewEnabled) {
|
|
|
|
mediaPreview.visibility = View.VISIBLE
|
2016-07-03 05:11:56 +02:00
|
|
|
mediaLabel.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
} else {
|
|
|
|
mediaPreview.visibility = View.GONE
|
2016-07-03 05:11:56 +02:00
|
|
|
mediaLabel.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
2016-07-03 05:11:56 +02:00
|
|
|
actionButtons.visibility = if (showCardActions) View.VISIBLE else View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
itemMenu.visibility = if (showCardActions) View.VISIBLE else View.GONE
|
2016-07-03 05:11:56 +02:00
|
|
|
statusContentLowerSpace.visibility = if (showCardActions) View.GONE else View.VISIBLE
|
|
|
|
quotedMediaPreview.visibility = View.GONE
|
2016-12-05 15:01:42 +01:00
|
|
|
quotedMediaLabel.visibility = View.GONE
|
2016-12-12 14:03:58 +01:00
|
|
|
mediaPreview.displayMedia(R.drawable.featured_graphics)
|
2016-06-29 15:47:52 +02:00
|
|
|
extraTypeView.setImageResource(R.drawable.ic_action_gallery)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun displayStatus(status: ParcelableStatus, displayInReplyTo: Boolean,
|
|
|
|
shouldDisplayExtraType: Boolean) {
|
|
|
|
|
2017-01-07 07:16:02 +01:00
|
|
|
val context = itemView.context
|
2016-06-29 15:47:52 +02:00
|
|
|
val loader = adapter.mediaLoader
|
|
|
|
val twitter = adapter.twitterWrapper
|
|
|
|
val linkify = adapter.twidereLinkify
|
|
|
|
val formatter = adapter.bidiFormatter
|
2017-01-09 06:16:23 +01:00
|
|
|
val colorNameManager = adapter.userColorNameManager
|
2016-06-29 15:47:52 +02:00
|
|
|
val nameFirst = adapter.nameFirst
|
|
|
|
val showCardActions = isCardActionsShown
|
|
|
|
|
2016-07-03 05:11:56 +02:00
|
|
|
actionButtons.visibility = if (showCardActions) View.VISIBLE else View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
itemMenu.visibility = if (showCardActions) View.VISIBLE else View.GONE
|
2016-07-03 05:11:56 +02:00
|
|
|
statusContentLowerSpace.visibility = if (showCardActions) View.GONE else View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
val replyCount = status.reply_count
|
|
|
|
val retweetCount: Long
|
|
|
|
val favoriteCount: Long
|
|
|
|
|
2016-08-19 16:25:27 +02:00
|
|
|
if (status.is_pinned_status) {
|
|
|
|
statusInfoLabel.setText(R.string.pinned_status)
|
|
|
|
statusInfoIcon.setImageResource(R.drawable.ic_activity_action_pinned)
|
|
|
|
statusInfoLabel.visibility = View.VISIBLE
|
|
|
|
statusInfoIcon.visibility = View.VISIBLE
|
|
|
|
|
|
|
|
statusContentUpperSpace.visibility = View.GONE
|
|
|
|
} else if (TwitterCardUtils.isPoll(status)) {
|
2016-07-03 05:11:56 +02:00
|
|
|
statusInfoLabel.setText(R.string.label_poll)
|
|
|
|
statusInfoIcon.setImageResource(R.drawable.ic_activity_action_poll)
|
|
|
|
statusInfoLabel.visibility = View.VISIBLE
|
|
|
|
statusInfoIcon.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
statusContentUpperSpace.visibility = View.GONE
|
|
|
|
} else if (status.retweet_id != null) {
|
2017-01-09 06:16:23 +01:00
|
|
|
val retweetedBy = colorNameManager.getDisplayName(status.retweeted_by_user_key!!,
|
2016-06-29 15:47:52 +02:00
|
|
|
status.retweeted_by_user_name, status.retweeted_by_user_screen_name, nameFirst)
|
2016-07-03 05:11:56 +02:00
|
|
|
statusInfoLabel.text = context.getString(R.string.name_retweeted, formatter.unicodeWrap(retweetedBy))
|
|
|
|
statusInfoIcon.setImageResource(R.drawable.ic_activity_action_retweet)
|
|
|
|
statusInfoLabel.visibility = View.VISIBLE
|
|
|
|
statusInfoIcon.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
statusContentUpperSpace.visibility = View.GONE
|
2017-01-09 06:16:23 +01:00
|
|
|
} else if (status.in_reply_to_status_id != null && status.in_reply_to_user_key != null && displayInReplyTo) {
|
|
|
|
val inReplyTo = colorNameManager.getDisplayName(status.in_reply_to_user_key!!,
|
2016-06-29 15:47:52 +02:00
|
|
|
status.in_reply_to_name, status.in_reply_to_screen_name, nameFirst)
|
2016-07-03 05:11:56 +02:00
|
|
|
statusInfoLabel.text = context.getString(R.string.in_reply_to_name, formatter.unicodeWrap(inReplyTo))
|
|
|
|
statusInfoIcon.setImageResource(R.drawable.ic_activity_action_reply)
|
|
|
|
statusInfoLabel.visibility = View.VISIBLE
|
|
|
|
statusInfoIcon.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
statusContentUpperSpace.visibility = View.GONE
|
|
|
|
} else {
|
2016-07-03 05:11:56 +02:00
|
|
|
statusInfoLabel.visibility = View.GONE
|
|
|
|
statusInfoIcon.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
statusContentUpperSpace.visibility = View.VISIBLE
|
|
|
|
}
|
|
|
|
|
|
|
|
val skipLinksInText = status.extras != null && status.extras.support_entities
|
|
|
|
if (status.is_quote) {
|
|
|
|
|
2016-09-01 08:02:17 +02:00
|
|
|
quotedView.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
val quoteContentAvailable = status.quoted_text_plain != null && status.quoted_text_unescaped != null
|
2017-01-24 12:10:24 +01:00
|
|
|
val isFanfouStatus = status.account_key.host == USER_TYPE_FANFOU_COM
|
|
|
|
if (quoteContentAvailable && !isFanfouStatus) {
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedNameView.visibility = View.VISIBLE
|
|
|
|
quotedTextView.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
|
2017-01-09 06:16:23 +01:00
|
|
|
val quoted_user_key = status.quoted_user_key!!
|
|
|
|
quotedNameView.setName(colorNameManager.getUserNickname(quoted_user_key,
|
2016-06-29 15:47:52 +02:00
|
|
|
status.quoted_user_name))
|
2017-01-09 06:16:23 +01:00
|
|
|
quotedNameView.setScreenName("@${status.quoted_user_screen_name}")
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
var quotedDisplayEnd = -1
|
|
|
|
if (status.extras.quoted_display_text_range != null) {
|
|
|
|
quotedDisplayEnd = status.extras.quoted_display_text_range!![1]
|
|
|
|
}
|
|
|
|
val quotedText: CharSequence
|
|
|
|
if (adapter.linkHighlightingStyle != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
|
|
|
|
quotedText = SpannableStringBuilder.valueOf(status.quoted_text_unescaped)
|
|
|
|
ParcelableStatusUtils.applySpans(quotedText as Spannable, status.quoted_spans)
|
|
|
|
linkify.applyAllLinks(quotedText, status.account_key, layoutPosition.toLong(),
|
|
|
|
status.is_possibly_sensitive, adapter.linkHighlightingStyle,
|
|
|
|
skipLinksInText)
|
|
|
|
} else {
|
|
|
|
quotedText = status.quoted_text_unescaped
|
|
|
|
}
|
|
|
|
if (quotedDisplayEnd != -1 && quotedDisplayEnd <= quotedText.length) {
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedTextView.text = quotedText.subSequence(0, quotedDisplayEnd)
|
2016-06-29 15:47:52 +02:00
|
|
|
} else {
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedTextView.text = quotedText
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
2016-07-03 05:11:56 +02:00
|
|
|
if (quotedTextView.length() == 0) {
|
2016-06-29 15:47:52 +02:00
|
|
|
// No text
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedTextView.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
} else {
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedTextView.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
2017-01-09 06:16:23 +01:00
|
|
|
val quoted_user_color = colorNameManager.getUserColor(quoted_user_key)
|
|
|
|
if (quoted_user_color != 0) {
|
|
|
|
quotedView.drawStart(quoted_user_color)
|
2016-09-01 08:02:17 +02:00
|
|
|
} else {
|
|
|
|
quotedView.drawStart(ThemeUtils.getColorFromAttribute(context, R.attr.quoteIndicatorBackgroundColor, 0))
|
|
|
|
}
|
|
|
|
|
2017-01-24 12:10:24 +01:00
|
|
|
displayQuotedMedia(loader, status)
|
|
|
|
} else {
|
|
|
|
quotedNameView.visibility = View.GONE
|
|
|
|
quotedTextView.visibility = View.VISIBLE
|
|
|
|
|
|
|
|
if (quoteContentAvailable) {
|
|
|
|
displayQuotedMedia(loader, status)
|
2016-09-01 08:02:17 +02:00
|
|
|
} else {
|
|
|
|
quotedMediaPreview.visibility = View.GONE
|
2016-09-09 05:58:26 +02:00
|
|
|
quotedMediaLabel.visibility = View.GONE
|
2016-09-01 08:02:17 +02:00
|
|
|
}
|
2016-06-29 15:47:52 +02:00
|
|
|
|
2017-01-31 16:24:33 +01:00
|
|
|
quotedTextView.text = if (!quoteContentAvailable) {
|
2017-01-24 12:10:24 +01:00
|
|
|
// Display 'not available' label
|
2017-01-31 16:24:33 +01:00
|
|
|
SpannableString.valueOf(context.getString(R.string.label_status_not_available)).apply {
|
|
|
|
setSpan(ForegroundColorSpan(ThemeUtils.getColorFromAttribute(context,
|
|
|
|
android.R.attr.textColorTertiary, textView.currentTextColor)), 0,
|
|
|
|
length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
|
|
|
|
}
|
2017-01-24 12:10:24 +01:00
|
|
|
} else {
|
|
|
|
// Display 'original status' label
|
|
|
|
context.getString(R.string.label_original_status)
|
|
|
|
}
|
2016-06-29 15:47:52 +02:00
|
|
|
|
2016-09-01 08:02:17 +02:00
|
|
|
quotedView.drawStart(ThemeUtils.getColorFromAttribute(context, R.attr.quoteIndicatorBackgroundColor, 0))
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
2017-01-15 18:55:53 +01:00
|
|
|
itemContent.drawStart(colorNameManager.getUserColor(status.user_key))
|
2016-06-29 15:47:52 +02:00
|
|
|
} else {
|
2016-09-01 08:02:17 +02:00
|
|
|
quotedView.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
|
2017-01-15 18:55:53 +01:00
|
|
|
val userColor = colorNameManager.getUserColor(status.user_key)
|
|
|
|
|
2016-06-29 15:47:52 +02:00
|
|
|
if (status.is_retweet) {
|
2017-01-15 18:55:53 +01:00
|
|
|
val retweetUserColor = colorNameManager.getUserColor(status.retweeted_by_user_key!!)
|
2016-06-29 15:47:52 +02:00
|
|
|
if (retweetUserColor == 0) {
|
|
|
|
itemContent.drawStart(userColor)
|
|
|
|
} else if (userColor == 0) {
|
|
|
|
itemContent.drawStart(retweetUserColor)
|
|
|
|
} else {
|
|
|
|
itemContent.drawStart(retweetUserColor, userColor)
|
|
|
|
}
|
|
|
|
} else {
|
2017-01-15 18:55:53 +01:00
|
|
|
itemContent.drawStart(userColor)
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-01-19 03:58:52 +01:00
|
|
|
timeView.time = if (status.is_retweet) {
|
|
|
|
status.retweet_timestamp
|
2016-06-29 15:47:52 +02:00
|
|
|
} else {
|
2017-01-19 03:58:52 +01:00
|
|
|
status.timestamp
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
2017-01-09 06:16:23 +01:00
|
|
|
|
|
|
|
nameView.setName(colorNameManager.getUserNickname(status.user_key, status.user_name))
|
2016-06-29 15:47:52 +02:00
|
|
|
nameView.setScreenName("@${status.user_screen_name}")
|
|
|
|
|
|
|
|
if (adapter.profileImageEnabled) {
|
|
|
|
profileImageView.visibility = View.VISIBLE
|
|
|
|
loader.displayProfileImage(profileImageView, status)
|
|
|
|
|
2016-07-03 05:11:56 +02:00
|
|
|
profileTypeView.setImageResource(getUserTypeIconRes(status.user_is_verified, status.user_is_protected))
|
|
|
|
profileTypeView.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
} else {
|
2016-07-03 05:11:56 +02:00
|
|
|
profileImageView.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
loader.cancelDisplayTask(profileImageView)
|
|
|
|
|
2016-07-03 05:11:56 +02:00
|
|
|
profileTypeView.setImageDrawable(null)
|
|
|
|
profileTypeView.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (adapter.showAccountsColor) {
|
|
|
|
itemContent.drawEnd(status.account_color)
|
|
|
|
} else {
|
|
|
|
itemContent.drawEnd()
|
|
|
|
}
|
|
|
|
|
2016-09-01 08:02:17 +02:00
|
|
|
if (status.media?.isNotEmpty() ?: false) {
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
if (!adapter.sensitiveContentEnabled && status.is_possibly_sensitive) {
|
|
|
|
// Sensitive content, show label instead of media view
|
2016-09-01 08:02:17 +02:00
|
|
|
mediaLabel.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
mediaPreview.visibility = View.GONE
|
|
|
|
} else if (!adapter.mediaPreviewEnabled) {
|
|
|
|
// Media preview disabled, just show label
|
2016-09-01 08:02:17 +02:00
|
|
|
mediaLabel.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
mediaPreview.visibility = View.GONE
|
|
|
|
} else {
|
|
|
|
// Show media
|
2016-07-03 05:11:56 +02:00
|
|
|
mediaLabel.visibility = View.GONE
|
2016-09-01 08:02:17 +02:00
|
|
|
mediaPreview.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
mediaPreview.displayMedia(status.media, loader, status.account_key, -1, this,
|
|
|
|
adapter.mediaLoadingHandler)
|
|
|
|
}
|
2016-09-01 08:02:17 +02:00
|
|
|
} else {
|
|
|
|
// No media, hide all related views
|
|
|
|
mediaLabel.visibility = View.GONE
|
|
|
|
mediaPreview.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
2016-09-01 08:02:17 +02:00
|
|
|
|
2016-06-29 15:47:52 +02:00
|
|
|
var displayEnd = -1
|
|
|
|
if (status.extras.display_text_range != null) {
|
|
|
|
displayEnd = status.extras.display_text_range!![1]
|
|
|
|
}
|
|
|
|
|
|
|
|
val text: CharSequence
|
|
|
|
if (adapter.linkHighlightingStyle != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
|
|
|
|
text = SpannableStringBuilder.valueOf(status.text_unescaped)
|
|
|
|
ParcelableStatusUtils.applySpans(text as Spannable, status.spans)
|
|
|
|
linkify.applyAllLinks(text, status.account_key, layoutPosition.toLong(),
|
|
|
|
status.is_possibly_sensitive, adapter.linkHighlightingStyle,
|
|
|
|
skipLinksInText)
|
|
|
|
} else {
|
|
|
|
text = status.text_unescaped
|
|
|
|
}
|
|
|
|
|
|
|
|
if (displayEnd != -1 && displayEnd <= text.length) {
|
|
|
|
textView.text = text.subSequence(0, displayEnd)
|
|
|
|
} else {
|
|
|
|
textView.text = text
|
|
|
|
}
|
|
|
|
if (textView.length() == 0) {
|
|
|
|
// No text
|
|
|
|
textView.visibility = View.GONE
|
|
|
|
} else {
|
|
|
|
textView.visibility = View.VISIBLE
|
|
|
|
}
|
|
|
|
|
|
|
|
if (replyCount > 0) {
|
2016-07-03 05:11:56 +02:00
|
|
|
replyCountView.text = UnitConvertUtils.calculateProperCount(replyCount)
|
|
|
|
replyCountView.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
} else {
|
2016-07-03 05:11:56 +02:00
|
|
|
replyCountView.text = null
|
|
|
|
replyCountView.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if (twitter.isDestroyingStatus(status.account_key, status.my_retweet_id)) {
|
2016-07-05 15:19:51 +02:00
|
|
|
retweetIcon.isActivated = false
|
2016-06-29 15:47:52 +02:00
|
|
|
retweetCount = Math.max(0, status.retweet_count - 1)
|
|
|
|
} else {
|
|
|
|
val creatingRetweet = twitter.isCreatingRetweet(status.account_key, status.id)
|
2016-07-05 15:19:51 +02:00
|
|
|
retweetIcon.isActivated = creatingRetweet || status.retweeted ||
|
2016-06-29 15:47:52 +02:00
|
|
|
Utils.isMyRetweet(status.account_key, status.retweeted_by_user_key,
|
|
|
|
status.my_retweet_id)
|
|
|
|
retweetCount = status.retweet_count + if (creatingRetweet) 1 else 0
|
|
|
|
}
|
|
|
|
|
|
|
|
if (retweetCount > 0) {
|
2016-07-03 05:11:56 +02:00
|
|
|
retweetCountView.text = UnitConvertUtils.calculateProperCount(retweetCount)
|
|
|
|
retweetCountView.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
} else {
|
2016-07-03 05:11:56 +02:00
|
|
|
retweetCountView.text = null
|
|
|
|
retweetCountView.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
if (twitter.isDestroyingFavorite(status.account_key, status.id)) {
|
2016-07-03 05:11:56 +02:00
|
|
|
favoriteIcon.isActivated = false
|
2016-06-29 15:47:52 +02:00
|
|
|
favoriteCount = Math.max(0, status.favorite_count - 1)
|
|
|
|
} else {
|
|
|
|
val creatingFavorite = twitter.isCreatingFavorite(status.account_key, status.id)
|
2016-07-03 05:11:56 +02:00
|
|
|
favoriteIcon.isActivated = creatingFavorite || status.is_favorite
|
2016-06-29 15:47:52 +02:00
|
|
|
favoriteCount = status.favorite_count + if (creatingFavorite) 1 else 0
|
|
|
|
}
|
|
|
|
if (favoriteCount > 0) {
|
2016-07-05 15:19:51 +02:00
|
|
|
favoriteCountView.text = UnitConvertUtils.calculateProperCount(favoriteCount)
|
|
|
|
favoriteCountView.visibility = View.VISIBLE
|
2016-06-29 15:47:52 +02:00
|
|
|
} else {
|
2016-07-05 15:19:51 +02:00
|
|
|
favoriteCountView.text = null
|
|
|
|
favoriteCountView.visibility = View.GONE
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
if (shouldDisplayExtraType) {
|
|
|
|
displayExtraTypeIcon(status.card_name, status.media, status.location,
|
|
|
|
status.place_full_name, status.is_possibly_sensitive)
|
|
|
|
} else {
|
|
|
|
extraTypeView.visibility = View.GONE
|
|
|
|
}
|
|
|
|
|
|
|
|
nameView.updateText(formatter)
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedNameView.updateText(formatter)
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2017-01-24 12:10:24 +01:00
|
|
|
private fun displayQuotedMedia(loader: MediaLoaderWrapper, status: ParcelableStatus) {
|
|
|
|
if (status.quoted_media?.isNotEmpty() ?: false) {
|
|
|
|
|
|
|
|
if (!adapter.sensitiveContentEnabled && status.is_possibly_sensitive) {
|
|
|
|
// Sensitive content, show label instead of media view
|
|
|
|
quotedMediaPreview.visibility = View.GONE
|
|
|
|
quotedMediaLabel.visibility = View.VISIBLE
|
|
|
|
} else if (!adapter.mediaPreviewEnabled) {
|
|
|
|
// Media preview disabled, just show label
|
|
|
|
quotedMediaPreview.visibility = View.GONE
|
|
|
|
quotedMediaLabel.visibility = View.VISIBLE
|
|
|
|
} else {
|
|
|
|
// Show media
|
|
|
|
quotedMediaPreview.visibility = View.VISIBLE
|
|
|
|
quotedMediaLabel.visibility = View.GONE
|
|
|
|
|
|
|
|
quotedMediaPreview.displayMedia(status.quoted_media, loader, status.account_key, -1,
|
|
|
|
null, null)
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
// No media, hide all related views
|
|
|
|
quotedMediaPreview.visibility = View.GONE
|
|
|
|
quotedMediaLabel.visibility = View.GONE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2016-06-29 15:47:52 +02:00
|
|
|
override fun onMediaClick(view: View, media: ParcelableMedia, accountKey: UserKey, extraId: Long) {
|
|
|
|
statusClickListener?.onMediaClick(this, view, media, layoutPosition)
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
fun setOnClickListeners() {
|
|
|
|
setStatusClickListener(adapter.statusClickListener)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun setStatusClickListener(listener: IStatusViewHolder.StatusClickListener?) {
|
|
|
|
statusClickListener = listener
|
|
|
|
itemContent.setOnClickListener(eventListener)
|
|
|
|
itemContent.setOnLongClickListener(eventListener)
|
|
|
|
|
|
|
|
itemMenu.setOnClickListener(eventListener)
|
|
|
|
profileImageView.setOnClickListener(eventListener)
|
2016-07-05 15:19:51 +02:00
|
|
|
replyButton.setOnClickListener(eventListener)
|
|
|
|
retweetButton.setOnClickListener(eventListener)
|
|
|
|
favoriteButton.setOnClickListener(eventListener)
|
2016-07-06 15:21:34 +02:00
|
|
|
|
|
|
|
mediaLabel.setOnClickListener(eventListener)
|
2017-01-17 18:59:44 +01:00
|
|
|
|
|
|
|
quotedView.setOnClickListener(eventListener)
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
2016-07-05 15:19:51 +02:00
|
|
|
|
2016-06-29 15:47:52 +02:00
|
|
|
override fun setTextSize(textSize: Float) {
|
|
|
|
nameView.setPrimaryTextSize(textSize)
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedNameView.setPrimaryTextSize(textSize)
|
2016-06-29 15:47:52 +02:00
|
|
|
textView.textSize = textSize
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedTextView.textSize = textSize
|
2016-06-29 15:47:52 +02:00
|
|
|
nameView.setSecondaryTextSize(textSize * 0.85f)
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedNameView.setSecondaryTextSize(textSize * 0.85f)
|
|
|
|
timeView.textSize = textSize * 0.85f
|
|
|
|
statusInfoLabel.textSize = textSize * 0.75f
|
2016-06-29 15:47:52 +02:00
|
|
|
|
2016-07-05 15:19:51 +02:00
|
|
|
mediaLabelTextView.textSize = textSize * 0.95f
|
2016-06-29 15:47:52 +02:00
|
|
|
|
2016-07-03 05:11:56 +02:00
|
|
|
replyCountView.textSize = textSize
|
|
|
|
retweetCountView.textSize = textSize
|
2016-07-05 15:19:51 +02:00
|
|
|
favoriteCountView.textSize = textSize
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
fun setupViewOptions() {
|
|
|
|
setTextSize(adapter.textSize)
|
2017-01-07 15:45:33 +01:00
|
|
|
profileImageView.style = adapter.profileImageStyle
|
|
|
|
|
2016-06-29 15:47:52 +02:00
|
|
|
mediaPreview.setStyle(adapter.mediaPreviewStyle)
|
2016-09-01 08:02:17 +02:00
|
|
|
quotedMediaPreview.setStyle(adapter.mediaPreviewStyle)
|
2016-06-29 15:47:52 +02:00
|
|
|
// profileImageView.setStyle(adapter.getProfileImageStyle());
|
|
|
|
|
|
|
|
val nameFirst = adapter.nameFirst
|
|
|
|
nameView.setNameFirst(nameFirst)
|
2016-07-03 05:11:56 +02:00
|
|
|
quotedNameView.setNameFirst(nameFirst)
|
2016-06-29 15:47:52 +02:00
|
|
|
|
|
|
|
val favIcon: Int
|
|
|
|
val favStyle: Int
|
|
|
|
val favColor: Int
|
2017-01-07 07:16:02 +01:00
|
|
|
val context = itemView.context
|
2016-06-29 15:47:52 +02:00
|
|
|
if (adapter.useStarsForLikes) {
|
|
|
|
favIcon = R.drawable.ic_action_star
|
|
|
|
favStyle = LikeAnimationDrawable.Style.FAVORITE
|
|
|
|
favColor = ContextCompat.getColor(context, R.color.highlight_favorite)
|
|
|
|
} else {
|
|
|
|
favIcon = R.drawable.ic_action_heart
|
|
|
|
favStyle = LikeAnimationDrawable.Style.LIKE
|
|
|
|
favColor = ContextCompat.getColor(context, R.color.highlight_like)
|
|
|
|
}
|
|
|
|
val icon = ContextCompat.getDrawable(context, favIcon)
|
|
|
|
val drawable = LikeAnimationDrawable(icon,
|
2016-07-05 15:19:51 +02:00
|
|
|
favoriteCountView.textColors.defaultColor, favColor, favStyle)
|
2016-06-29 15:47:52 +02:00
|
|
|
drawable.mutate()
|
2016-07-03 05:11:56 +02:00
|
|
|
favoriteIcon.setImageDrawable(drawable)
|
2017-01-19 03:58:52 +01:00
|
|
|
timeView.showAbsoluteTime = adapter.showAbsoluteTime
|
2016-06-29 15:47:52 +02:00
|
|
|
|
2016-07-03 05:11:56 +02:00
|
|
|
favoriteIcon.activatedColor = favColor
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
override fun playLikeAnimation(listener: LikeAnimationDrawable.OnLikedListener) {
|
|
|
|
var handled = false
|
2016-07-03 05:11:56 +02:00
|
|
|
val drawable = favoriteIcon.drawable
|
2016-06-29 15:47:52 +02:00
|
|
|
if (drawable is LikeAnimationDrawable) {
|
|
|
|
drawable.setOnLikedListener(listener)
|
|
|
|
drawable.start()
|
|
|
|
handled = true
|
|
|
|
}
|
|
|
|
if (!handled) {
|
|
|
|
listener.onLiked()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private val isCardActionsShown: Boolean
|
|
|
|
get() = adapter.isCardActionsShown(layoutPosition)
|
|
|
|
|
|
|
|
private fun showCardActions() {
|
|
|
|
adapter.showCardActions(layoutPosition)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun hideTempCardActions(): Boolean {
|
|
|
|
adapter.showCardActions(RecyclerView.NO_POSITION)
|
|
|
|
return !adapter.isCardActionsShown(RecyclerView.NO_POSITION)
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun displayExtraTypeIcon(cardName: String?, media: Array<ParcelableMedia?>?,
|
|
|
|
location: ParcelableLocation?, placeFullName: String?,
|
|
|
|
sensitive: Boolean) {
|
|
|
|
if (TwitterCardUtils.CARD_NAME_AUDIO == cardName) {
|
|
|
|
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_music)
|
|
|
|
extraTypeView.visibility = View.VISIBLE
|
|
|
|
} else if (TwitterCardUtils.CARD_NAME_ANIMATED_GIF == cardName) {
|
|
|
|
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_movie)
|
|
|
|
extraTypeView.visibility = View.VISIBLE
|
|
|
|
} else if (TwitterCardUtils.CARD_NAME_PLAYER == cardName) {
|
|
|
|
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_play_circle)
|
|
|
|
extraTypeView.visibility = View.VISIBLE
|
|
|
|
} else if (media?.isNotEmpty() ?: false) {
|
|
|
|
if (hasVideo(media)) {
|
|
|
|
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_movie)
|
|
|
|
} else {
|
|
|
|
extraTypeView.setImageResource(if (sensitive) R.drawable.ic_action_warning else R.drawable.ic_action_gallery)
|
|
|
|
}
|
|
|
|
extraTypeView.visibility = View.VISIBLE
|
|
|
|
} else if (ParcelableLocationUtils.isValidLocation(location) || !TextUtils.isEmpty(placeFullName)) {
|
|
|
|
extraTypeView.setImageResource(R.drawable.ic_action_location)
|
|
|
|
extraTypeView.visibility = View.VISIBLE
|
|
|
|
} else {
|
|
|
|
extraTypeView.visibility = View.GONE
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
private fun hasVideo(media: Array<ParcelableMedia?>?): Boolean {
|
|
|
|
if (media == null) return false
|
2016-12-06 06:15:22 +01:00
|
|
|
media.filterNotNull().forEach {
|
|
|
|
when (it.type) {
|
2016-06-29 15:47:52 +02:00
|
|
|
ParcelableMedia.Type.VIDEO, ParcelableMedia.Type.ANIMATED_GIF, ParcelableMedia.Type.EXTERNAL_PLAYER -> return true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
|
|
|
internal class EventListener(holder: StatusViewHolder) : OnClickListener, OnLongClickListener {
|
|
|
|
|
|
|
|
val holderRef: WeakReference<StatusViewHolder>
|
|
|
|
|
|
|
|
init {
|
|
|
|
this.holderRef = WeakReference(holder)
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onClick(v: View) {
|
|
|
|
val holder = holderRef.get() ?: return
|
|
|
|
val listener = holder.statusClickListener ?: return
|
|
|
|
val position = holder.layoutPosition
|
|
|
|
when (v) {
|
|
|
|
holder.itemContent -> {
|
|
|
|
listener.onStatusClick(holder, position)
|
|
|
|
}
|
2017-01-17 18:59:44 +01:00
|
|
|
holder.quotedView -> {
|
|
|
|
listener.onQuotedStatusClick(holder, position)
|
|
|
|
}
|
2016-06-29 15:47:52 +02:00
|
|
|
holder.itemMenu -> {
|
|
|
|
listener.onItemMenuClick(holder, v, position)
|
|
|
|
}
|
2016-07-03 05:11:56 +02:00
|
|
|
holder.profileImageView -> {
|
2016-06-29 15:47:52 +02:00
|
|
|
listener.onUserProfileClick(holder, position)
|
|
|
|
}
|
2016-07-05 15:19:51 +02:00
|
|
|
holder.replyButton -> {
|
2016-06-29 15:47:52 +02:00
|
|
|
listener.onItemActionClick(holder, R.id.reply, position)
|
|
|
|
}
|
2016-07-05 15:19:51 +02:00
|
|
|
holder.retweetButton -> {
|
2016-06-29 15:47:52 +02:00
|
|
|
listener.onItemActionClick(holder, R.id.retweet, position)
|
|
|
|
}
|
2016-07-05 15:19:51 +02:00
|
|
|
holder.favoriteButton -> {
|
2016-06-29 15:47:52 +02:00
|
|
|
listener.onItemActionClick(holder, R.id.favorite, position)
|
|
|
|
}
|
2016-07-08 03:44:43 +02:00
|
|
|
holder.mediaLabel -> {
|
2016-08-27 07:36:38 +02:00
|
|
|
val firstMedia = holder.adapter.getStatus(position)?.media?.firstOrNull() ?: return
|
|
|
|
listener.onMediaClick(holder, v, firstMedia, position)
|
2016-07-08 03:44:43 +02:00
|
|
|
}
|
2016-06-29 15:47:52 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
override fun onLongClick(v: View): Boolean {
|
|
|
|
val holder = holderRef.get() ?: return false
|
|
|
|
val listener = holder.statusClickListener ?: return false
|
|
|
|
val position = holder.layoutPosition
|
2016-08-09 09:48:16 +02:00
|
|
|
when (v) {
|
|
|
|
holder.itemContent -> {
|
2016-06-29 15:47:52 +02:00
|
|
|
if (!holder.isCardActionsShown) {
|
|
|
|
holder.showCardActions()
|
|
|
|
return true
|
|
|
|
} else if (holder.hideTempCardActions()) {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return listener.onStatusLongClick(holder, position)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
2017-01-28 08:15:35 +01:00
|
|
|
|