Twidere-App-Android-Twitter.../twidere/src/main/kotlin/org/mariotaku/twidere/view/holder/StatusViewHolder.kt

716 lines
31 KiB
Kotlin
Raw Normal View History

2016-06-29 15:47:52 +02:00
package org.mariotaku.twidere.view.holder
2017-04-20 14:04:37 +02:00
import android.graphics.Typeface
2016-06-29 15:47:52 +02:00
import android.support.v4.content.ContextCompat
import android.support.v4.widget.TextViewCompat
2016-06-29 15:47:52 +02:00
import android.support.v7.widget.RecyclerView
import android.support.v7.widget.RecyclerView.ViewHolder
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.text.Spanned
2016-06-29 15:47:52 +02:00
import android.text.style.ForegroundColorSpan
2017-04-20 14:04:37 +02:00
import android.text.style.StyleSpan
2016-06-29 15:47:52 +02:00
import android.view.View
import android.view.View.OnClickListener
import android.view.View.OnLongClickListener
import android.widget.ImageView
import android.widget.TextView
2017-03-01 15:12:25 +01:00
import com.bumptech.glide.RequestManager
import kotlinx.android.synthetic.main.list_item_status.view.*
2017-05-13 08:19:23 +02:00
import org.mariotaku.ktextension.*
import org.mariotaku.microblog.library.mastodon.annotation.StatusVisibility
import org.mariotaku.twidere.Constants.*
2016-06-29 15:47:52 +02:00
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
2017-03-02 02:08:54 +01:00
import org.mariotaku.twidere.extension.loadProfileImage
import org.mariotaku.twidere.extension.model.applyTo
2017-04-23 07:48:09 +02:00
import org.mariotaku.twidere.extension.model.quoted_user_acct
import org.mariotaku.twidere.extension.model.retweeted_by_user_acct
import org.mariotaku.twidere.extension.model.user_acct
2016-06-29 15:47:52 +02:00
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
2017-02-07 15:55:36 +01:00
import org.mariotaku.twidere.task.CreateFavoriteTask
import org.mariotaku.twidere.task.DestroyFavoriteTask
import org.mariotaku.twidere.task.RetweetStatusTask
2016-06-29 15:47:52 +02:00
import org.mariotaku.twidere.util.*
import org.mariotaku.twidere.util.HtmlEscapeHelper.toPlainText
import org.mariotaku.twidere.util.Utils.getUserTypeIconRes
2017-03-02 07:59:19 +01:00
import org.mariotaku.twidere.view.ShapedImageView
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), IStatusViewHolder {
2016-06-29 15:47:52 +02:00
2017-03-02 07:59:19 +01:00
override val profileImageView: ShapedImageView 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 }
2017-04-20 07:28:57 +02:00
private val summaryView by lazy { itemView.summary }
2016-06-29 15:47:52 +02:00
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 }
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 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
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
adapter.requestManager.loadProfileImage(itemView.context, R.drawable.ic_profile_image_twidere,
adapter.profileImageStyle, profileImageView.cornerRadius,
profileImageView.cornerRadiusRatio).into(profileImageView)
nameView.name = TWIDERE_PREVIEW_NAME
nameView.screenName = "@" + TWIDERE_PREVIEW_SCREEN_NAME
2016-06-29 15:47:52 +02:00
nameView.updateText(adapter.bidiFormatter)
2017-04-20 14:04:37 +02:00
summaryView.hideIfEmpty()
2016-06-29 15:47:52 +02:00
if (adapter.linkHighlightingStyle == VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
2017-05-13 08:19:23 +02:00
textView.spannable = toPlainText(TWIDERE_PREVIEW_TEXT_HTML)
2016-12-08 08:47:17 +01:00
} else {
2016-06-29 15:47:52 +02:00
val linkify = adapter.twidereLinkify
val text = HtmlSpanBuilder.fromHtml(TWIDERE_PREVIEW_TEXT_HTML)
2016-06-29 15:47:52 +02:00
linkify.applyAllLinks(text, null, -1, false, adapter.linkHighlightingStyle, true)
2017-05-13 08:19:23 +02:00
textView.spannable = text
2016-06-29 15:47:52 +02:00
}
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
}
override fun display(status: ParcelableStatus, displayInReplyTo: Boolean,
displayPinned: Boolean) {
2016-06-29 15:47:52 +02:00
2017-01-07 07:16:02 +01:00
val context = itemView.context
2017-03-02 07:59:19 +01:00
val requestManager = adapter.requestManager
2016-06-29 15:47:52 +02:00
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
2017-02-28 07:35:31 +01:00
if (displayPinned && status.is_pinned_status) {
2016-08-19 16:25:27 +02:00
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!!,
2017-04-23 07:48:09 +02:00
status.retweeted_by_user_name, status.retweeted_by_user_acct!!, nameFirst)
2017-05-13 08:19:23 +02:00
statusInfoLabel.spannable = context.getString(R.string.name_retweeted, formatter.unicodeWrap(retweetedBy))
2016-07-03 05:11:56 +02:00
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) {
if (status.in_reply_to_name != null && status.in_reply_to_screen_name != null) {
val inReplyTo = colorNameManager.getDisplayName(status.in_reply_to_user_key!!,
status.in_reply_to_name, status.in_reply_to_screen_name, nameFirst)
2017-05-13 08:19:23 +02:00
statusInfoLabel.spannable = context.getString(R.string.in_reply_to_name, formatter.unicodeWrap(inReplyTo))
} else {
2017-05-13 08:19:23 +02:00
statusInfoLabel.spannable = context.getString(R.string.label_status_type_reply)
}
2016-07-03 05:11:56 +02:00
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?.support_entities ?: false
2016-06-29 15:47:52 +02:00
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.name = colorNameManager.getUserNickname(quoted_user_key,
status.quoted_user_name)
2017-04-23 07:48:09 +02:00
quotedNameView.screenName = "@${status.quoted_user_acct}"
2016-06-29 15:47:52 +02:00
val quotedDisplayEnd = status.extras?.quoted_display_text_range?.getOrNull(1) ?: -1
2016-06-29 15:47:52 +02:00
val quotedText: CharSequence
if (adapter.linkHighlightingStyle != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
quotedText = SpannableStringBuilder.valueOf(status.quoted_text_unescaped)
status.quoted_spans?.applyTo(quotedText)
2016-06-29 15:47:52 +02:00
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) {
2017-05-13 08:19:23 +02:00
quotedTextView.spannable = quotedText.subSequence(0, quotedDisplayEnd)
2016-06-29 15:47:52 +02:00
} else {
2017-05-13 08:19:23 +02:00
quotedTextView.spannable = 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))
2016-09-01 08:02:17 +02:00
}
2017-03-02 07:59:19 +01:00
displayQuotedMedia(requestManager, status)
2017-01-24 12:10:24 +01:00
} else {
quotedNameView.visibility = View.GONE
quotedTextView.visibility = View.VISIBLE
if (quoteContentAvailable) {
2017-03-02 07:59:19 +01:00
displayQuotedMedia(requestManager, 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-05-13 08:19:23 +02:00
quotedTextView.spannable = 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
quotedView.drawStart(ThemeUtils.getColorFromAttribute(context,
R.attr.quoteIndicatorBackgroundColor))
2016-06-29 15:47:52 +02: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
val userColor = colorNameManager.getUserColor(status.user_key)
2016-06-29 15:47:52 +02:00
if (status.is_retweet) {
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 {
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.name = colorNameManager.getUserNickname(status.user_key, status.user_name)
2017-04-23 07:48:09 +02:00
nameView.screenName = "@${status.user_acct}"
2016-06-29 15:47:52 +02:00
if (adapter.profileImageEnabled) {
profileImageView.visibility = View.VISIBLE
requestManager.loadProfileImage(context, status, adapter.profileImageStyle,
2017-03-21 11:55:03 +01:00
profileImageView.cornerRadius, profileImageView.cornerRadiusRatio,
adapter.profileImageSize).into(profileImageView)
2016-06-29 15:47:52 +02:00
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
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()
}
2017-02-17 12:34:02 +01:00
if (status.media.isNotNullOrEmpty()) {
mediaLabel.displayMediaLabel(status.card_name, status.media, status.location,
status.place_full_name, status.is_possibly_sensitive)
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
2017-02-17 12:34:02 +01:00
mediaLabel.contentDescription = status.media?.firstOrNull()?.alt_text
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
2017-02-17 12:34:02 +01:00
mediaLabel.contentDescription = status.media?.firstOrNull()?.alt_text
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
2017-03-02 07:59:19 +01:00
mediaPreview.displayMedia(requestManager = requestManager,
2017-03-08 03:08:56 +01:00
media = status.media, accountKey = status.account_key,
mediaClickListener = this)
2016-06-29 15:47:52 +02:00
}
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
}
2017-05-13 08:19:23 +02:00
summaryView.spannable = status.extras?.summary_text
2017-04-20 07:28:57 +02:00
summaryView.hideIfEmpty()
2016-06-29 15:47:52 +02:00
val text: CharSequence
2017-04-20 14:04:37 +02:00
val displayEnd: Int
if (!summaryView.empty) {
text = SpannableStringBuilder.valueOf(context.getString(R.string.label_status_show_more)).apply {
val colorSecondary = ThemeUtils.getTextColorSecondary(context)
setSpan(ForegroundColorSpan(colorSecondary), 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
setSpan(StyleSpan(Typeface.ITALIC), 0, length, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE)
}
displayEnd = -1
} else if (adapter.linkHighlightingStyle != VALUE_LINK_HIGHLIGHT_OPTION_CODE_NONE) {
text = SpannableStringBuilder.valueOf(status.text_unescaped).apply {
status.spans?.applyTo(this)
linkify.applyAllLinks(this, status.account_key, layoutPosition.toLong(),
status.is_possibly_sensitive, adapter.linkHighlightingStyle,
skipLinksInText)
}
2017-04-20 14:04:37 +02:00
displayEnd = status.extras?.display_text_range?.getOrNull(1) ?: -1
2016-06-29 15:47:52 +02:00
} else {
text = status.text_unescaped
2017-04-20 14:04:37 +02:00
displayEnd = status.extras?.display_text_range?.getOrNull(1) ?: -1
2016-06-29 15:47:52 +02:00
}
if (displayEnd != -1 && displayEnd <= text.length) {
2017-05-13 08:19:23 +02:00
textView.spannable = text.subSequence(0, displayEnd)
2016-06-29 15:47:52 +02:00
} else {
2017-05-13 08:19:23 +02:00
textView.spannable = text
2016-06-29 15:47:52 +02:00
}
2017-04-20 07:28:57 +02:00
textView.hideIfEmpty()
2016-06-29 15:47:52 +02:00
if (replyCount > 0) {
2017-05-13 08:19:23 +02:00
replyCountView.spannable = UnitConvertUtils.calculateProperCount(replyCount)
2016-06-29 15:47:52 +02:00
} else {
2017-05-13 08:19:23 +02:00
replyCountView.spannable = null
2016-06-29 15:47:52 +02:00
}
2017-05-13 08:19:23 +02:00
replyCountView.hideIfEmpty()
2016-06-29 15:47:52 +02:00
when (status.extras?.visibility) {
StatusVisibility.PRIVATE -> {
retweetButton.isEnabled = false
retweetIcon.setImageResource(R.drawable.ic_action_lock)
retweetIcon.isEnabled = false
}
StatusVisibility.DIRECT -> {
retweetButton.isEnabled = false
retweetIcon.setImageResource(R.drawable.ic_action_message)
retweetIcon.isEnabled = false
}
else -> {
retweetButton.isEnabled = true
retweetIcon.setImageResource(R.drawable.ic_action_retweet)
retweetIcon.isEnabled = true
}
}
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
} else {
2017-02-07 15:55:36 +01:00
val creatingRetweet = RetweetStatusTask.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)
}
2017-04-29 18:34:26 +02:00
retweetCount = status.retweet_count
2016-06-29 15:47:52 +02:00
if (retweetCount > 0) {
2017-05-13 08:19:23 +02:00
retweetCountView.spannable = UnitConvertUtils.calculateProperCount(retweetCount)
2016-06-29 15:47:52 +02:00
} else {
2017-05-13 08:19:23 +02:00
retweetCountView.spannable = null
2016-06-29 15:47:52 +02:00
}
2017-05-13 08:19:23 +02:00
retweetCountView.hideIfEmpty()
2017-02-07 15:55:36 +01:00
if (DestroyFavoriteTask.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
} else {
2017-02-07 15:55:36 +01:00
val creatingFavorite = CreateFavoriteTask.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
}
2017-04-29 18:34:26 +02:00
favoriteCount = status.favorite_count
2017-05-13 08:19:23 +02:00
2016-06-29 15:47:52 +02:00
if (favoriteCount > 0) {
2017-05-13 08:19:23 +02:00
favoriteCountView.spannable = UnitConvertUtils.calculateProperCount(favoriteCount)
2016-06-29 15:47:52 +02:00
} else {
2017-05-13 08:19:23 +02:00
favoriteCountView.spannable = null
2016-06-29 15:47:52 +02:00
}
2017-05-13 08:19:23 +02:00
favoriteCountView.hideIfEmpty()
2016-06-29 15:47:52 +02:00
nameView.updateText(formatter)
2016-07-03 05:11:56 +02:00
quotedNameView.updateText(formatter)
2016-06-29 15:47:52 +02:00
}
2017-03-02 07:59:19 +01:00
private fun displayQuotedMedia(requestManager: RequestManager, status: ParcelableStatus) {
2017-01-24 12:10:24 +01:00
if (status.quoted_media?.isNotEmpty() ?: false) {
quotedMediaLabel.displayMediaLabel(null, status.quoted_media, null, null,
status.is_possibly_sensitive)
2017-01-24 12:10:24 +01:00
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 if (status.media.isNotNullOrEmpty()) {
// Already displaying media, show label only
quotedMediaPreview.visibility = View.GONE
quotedMediaLabel.visibility = View.VISIBLE
2017-01-24 12:10:24 +01:00
} else {
// Show media
quotedMediaPreview.visibility = View.VISIBLE
quotedMediaLabel.visibility = View.GONE
2017-03-02 07:59:19 +01:00
quotedMediaPreview.displayMedia(requestManager = requestManager,
2017-03-08 03:08:56 +01:00
media = status.quoted_media, accountKey = status.account_key,
mediaClickListener = this)
2017-01-24 12:10:24 +01:00
}
} else {
// No media, hide all related views
quotedMediaPreview.visibility = View.GONE
quotedMediaLabel.visibility = View.GONE
}
}
override fun onMediaClick(view: View, current: ParcelableMedia, accountKey: UserKey?, id: Long) {
2017-02-28 03:37:03 +01:00
if (view.parent == quotedMediaPreview) {
statusClickListener?.onQuotedMediaClick(this, view, current, layoutPosition)
2017-02-28 03:37:03 +01:00
} else {
statusClickListener?.onMediaClick(this, view, current, layoutPosition)
2017-02-28 03:37:03 +01:00
}
2016-06-29 15:47:52 +02:00
}
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)
retweetButton.setOnLongClickListener(eventListener)
favoriteButton.setOnLongClickListener(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)
2017-04-20 07:28:57 +02:00
summaryView.textSize = 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
mediaLabel.textSize = textSize * 0.95f
quotedMediaLabel.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
mediaPreview.style = adapter.mediaPreviewStyle
quotedMediaPreview.style = adapter.mediaPreviewStyle
2016-06-29 15:47:52 +02:00
// profileImageView.setStyle(adapter.getProfileImageStyle());
val nameFirst = adapter.nameFirst
nameView.nameFirst = nameFirst
quotedNameView.nameFirst = 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
2017-02-02 11:18:34 +01:00
nameView.applyFontFamily(adapter.lightFont)
timeView.applyFontFamily(adapter.lightFont)
2017-04-20 07:28:57 +02:00
summaryView.applyFontFamily(adapter.lightFont)
2017-02-02 11:18:34 +01:00
textView.applyFontFamily(adapter.lightFont)
mediaLabel.applyFontFamily(adapter.lightFont)
2017-02-02 11:18:34 +01:00
quotedNameView.applyFontFamily(adapter.lightFont)
quotedTextView.applyFontFamily(adapter.lightFont)
quotedMediaLabel.applyFontFamily(adapter.lightFont)
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 TextView.displayMediaLabel(cardName: String?, media: Array<ParcelableMedia?>?,
2017-02-28 03:37:03 +01:00
location: ParcelableLocation?, placeFullName: String?,
sensitive: Boolean) {
if (sensitive) {
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(this, R.drawable.ic_label_warning, 0, 0, 0)
2017-03-04 04:35:48 +01:00
setText(R.string.label_sensitive_content)
} else if (media != null && media.isNotEmpty()) {
val type = media.type
if (type in videoTypes) {
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(this, R.drawable.ic_label_video, 0, 0, 0)
setText(R.string.label_video)
} else if (media.size > 1) {
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(this, R.drawable.ic_label_gallery, 0, 0, 0)
setText(R.string.label_photos)
} else {
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(this, R.drawable.ic_label_gallery, 0, 0, 0)
setText(R.string.label_photo)
}
2016-06-29 15:47:52 +02:00
} else {
TextViewCompat.setCompoundDrawablesRelativeWithIntrinsicBounds(this, R.drawable.ic_label_gallery, 0, 0, 0)
setText(R.string.label_media)
2016-06-29 15:47:52 +02:00
}
refreshDrawableState()
}
2017-03-04 07:07:14 +01:00
private val Array<ParcelableMedia?>.type: Int get() {
forEach { if (it != null) return it.type }
return 0
2016-06-29 15:47:52 +02:00
}
private fun hasVideo(media: Array<ParcelableMedia?>?): Boolean {
if (media == null) return false
return media.any { item ->
if (item == null) return@any false
return@any videoTypes.contains(item.type)
2016-06-29 15:47:52 +02:00
}
}
internal class EventListener(holder: StatusViewHolder) : OnClickListener, OnLongClickListener {
private val holderRef = WeakReference(holder)
2016-06-29 15:47:52 +02:00
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 -> {
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)
}
holder.favoriteButton -> {
return listener.onItemActionLongClick(holder, R.id.favorite, position)
}
holder.retweetButton -> {
return listener.onItemActionLongClick(holder, R.id.retweet, position)
}
2016-06-29 15:47:52 +02:00
}
return false
}
}
2017-02-09 14:43:51 +01:00
companion object {
const val layoutResource = R.layout.list_item_status
private val videoTypes = intArrayOf(ParcelableMedia.Type.VIDEO, ParcelableMedia.Type.ANIMATED_GIF,
ParcelableMedia.Type.EXTERNAL_PLAYER)
2017-02-09 14:43:51 +01:00
}
2016-06-29 15:47:52 +02:00
}