mirror of
https://github.com/oxen-io/session-android.git
synced 2023-12-14 02:53:01 +01:00
142 lines
6.9 KiB
Kotlin
142 lines
6.9 KiB
Kotlin
package org.thoughtcrime.securesms.home
|
|
|
|
import android.content.Context
|
|
import android.content.res.Resources
|
|
import android.graphics.Typeface
|
|
import android.graphics.drawable.ColorDrawable
|
|
import android.util.AttributeSet
|
|
import android.util.TypedValue
|
|
import android.view.View
|
|
import android.widget.LinearLayout
|
|
import androidx.core.content.ContextCompat
|
|
import androidx.core.view.isVisible
|
|
import androidx.recyclerview.widget.RecyclerView
|
|
import dagger.hilt.android.AndroidEntryPoint
|
|
import network.loki.messenger.R
|
|
import network.loki.messenger.databinding.ViewConversationBinding
|
|
import org.session.libsession.utilities.recipients.Recipient
|
|
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities.highlightMentions
|
|
import org.thoughtcrime.securesms.database.RecipientDatabase.NOTIFY_TYPE_ALL
|
|
import org.thoughtcrime.securesms.database.RecipientDatabase.NOTIFY_TYPE_NONE
|
|
import org.thoughtcrime.securesms.database.model.ThreadRecord
|
|
import org.thoughtcrime.securesms.dependencies.ConfigFactory
|
|
import org.thoughtcrime.securesms.mms.GlideRequests
|
|
import org.thoughtcrime.securesms.util.DateUtils
|
|
import org.thoughtcrime.securesms.util.getAccentColor
|
|
import org.thoughtcrime.securesms.util.getConversationUnread
|
|
import java.util.Locale
|
|
import javax.inject.Inject
|
|
|
|
@AndroidEntryPoint
|
|
class ConversationView : LinearLayout {
|
|
|
|
@Inject lateinit var configFactory: ConfigFactory
|
|
|
|
private val binding: ViewConversationBinding by lazy { ViewConversationBinding.bind(this) }
|
|
private val screenWidth = Resources.getSystem().displayMetrics.widthPixels
|
|
var thread: ThreadRecord? = null
|
|
|
|
// region Lifecycle
|
|
constructor(context: Context) : super(context)
|
|
constructor(context: Context, attrs: AttributeSet) : super(context, attrs)
|
|
constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int) : super(context, attrs, defStyleAttr)
|
|
|
|
override fun onFinishInflate() {
|
|
super.onFinishInflate()
|
|
layoutParams = RecyclerView.LayoutParams(screenWidth, RecyclerView.LayoutParams.WRAP_CONTENT)
|
|
}
|
|
// endregion
|
|
|
|
// region Updating
|
|
fun bind(thread: ThreadRecord, isTyping: Boolean, glide: GlideRequests) {
|
|
this.thread = thread
|
|
if (thread.isPinned) {
|
|
binding.conversationViewDisplayNameTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(
|
|
0,
|
|
0,
|
|
R.drawable.ic_pin,
|
|
0
|
|
)
|
|
} else {
|
|
binding.conversationViewDisplayNameTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0)
|
|
}
|
|
binding.root.background = if (thread.unreadCount > 0) {
|
|
ContextCompat.getDrawable(context, R.drawable.conversation_unread_background)
|
|
} else {
|
|
ContextCompat.getDrawable(context, R.drawable.conversation_view_background)
|
|
}
|
|
val unreadCount = thread.unreadCount
|
|
if (thread.recipient.isBlocked) {
|
|
binding.accentView.setBackgroundResource(R.color.destructive)
|
|
binding.accentView.visibility = View.VISIBLE
|
|
} else {
|
|
val accentColor = context.getAccentColor()
|
|
val background = ColorDrawable(accentColor)
|
|
binding.accentView.background = background
|
|
// Using thread.isRead we can determine if the last message was our own, and display it as 'read' even though previous messages may not be
|
|
// This would also not trigger the disappearing message timer which may or may not be desirable
|
|
binding.accentView.visibility = if (unreadCount > 0 && !thread.isRead) View.VISIBLE else View.INVISIBLE
|
|
}
|
|
val formattedUnreadCount = if (unreadCount == 0) {
|
|
null
|
|
} else {
|
|
if (unreadCount < 10000) unreadCount.toString() else "9999+"
|
|
}
|
|
binding.unreadCountTextView.text = formattedUnreadCount
|
|
val textSize = if (unreadCount < 1000) 12.0f else 10.0f
|
|
binding.unreadCountTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
|
|
binding.unreadCountIndicator.isVisible = (unreadCount != 0 && !thread.isRead)
|
|
|| (configFactory.convoVolatile?.getConversationUnread(thread) == true)
|
|
binding.unreadMentionTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
|
|
binding.unreadMentionIndicator.isVisible = (thread.unreadMentionCount != 0 && thread.recipient.address.isGroup)
|
|
val senderDisplayName = getUserDisplayName(thread.recipient)
|
|
?: thread.recipient.address.toString()
|
|
binding.conversationViewDisplayNameTextView.text = senderDisplayName
|
|
binding.timestampTextView.text = DateUtils.getDisplayFormattedTimeSpanString(context, Locale.getDefault(), thread.date)
|
|
val recipient = thread.recipient
|
|
binding.muteIndicatorImageView.isVisible = recipient.isMuted || recipient.notifyType != NOTIFY_TYPE_ALL
|
|
val drawableRes = if (recipient.isMuted || recipient.notifyType == NOTIFY_TYPE_NONE) {
|
|
R.drawable.ic_outline_notifications_off_24
|
|
} else {
|
|
R.drawable.ic_notifications_mentions
|
|
}
|
|
binding.muteIndicatorImageView.setImageResource(drawableRes)
|
|
val rawSnippet = thread.getDisplayBody(context)
|
|
val snippet = highlightMentions(rawSnippet, thread.threadId, context)
|
|
binding.snippetTextView.text = snippet
|
|
binding.snippetTextView.typeface = if (unreadCount > 0 && !thread.isRead) Typeface.DEFAULT_BOLD else Typeface.DEFAULT
|
|
binding.snippetTextView.visibility = if (isTyping) View.GONE else View.VISIBLE
|
|
if (isTyping) {
|
|
binding.typingIndicatorView.root.startAnimation()
|
|
} else {
|
|
binding.typingIndicatorView.root.stopAnimation()
|
|
}
|
|
binding.typingIndicatorView.root.visibility = if (isTyping) View.VISIBLE else View.GONE
|
|
binding.statusIndicatorImageView.visibility = View.VISIBLE
|
|
when {
|
|
!thread.isOutgoing -> binding.statusIndicatorImageView.visibility = View.GONE
|
|
thread.isFailed -> {
|
|
val drawable = ContextCompat.getDrawable(context, R.drawable.ic_error)?.mutate()
|
|
drawable?.setTint(ContextCompat.getColor(context, R.color.destructive))
|
|
binding.statusIndicatorImageView.setImageDrawable(drawable)
|
|
}
|
|
thread.isPending -> binding.statusIndicatorImageView.setImageResource(R.drawable.ic_circle_dot_dot_dot)
|
|
thread.isRead -> binding.statusIndicatorImageView.setImageResource(R.drawable.ic_filled_circle_check)
|
|
else -> binding.statusIndicatorImageView.setImageResource(R.drawable.ic_circle_check)
|
|
}
|
|
binding.profilePictureView.update(thread.recipient)
|
|
}
|
|
|
|
fun recycle() {
|
|
binding.profilePictureView.recycle()
|
|
}
|
|
|
|
private fun getUserDisplayName(recipient: Recipient): String? {
|
|
return if (recipient.isLocalNumber) {
|
|
context.getString(R.string.note_to_self)
|
|
} else {
|
|
recipient.toShortString() // Internally uses the Contact API
|
|
}
|
|
}
|
|
// endregion
|
|
}
|